* Use goals from postgres to build goal filter
* Remove unnecessary goal preloading
* Add contains filter for goals
* Make sure the correct imported tables are used when goals are in filters
* Remove 'contains' filter type for now
* Remove TODO comment
* Fix QueryParser test
* move goals.ex into a goals subfolder
* extract goal filtering logic into a separate module
* remove duplication from Imported.Base
* Extract `get_filter_goals` function
* Credo suggestions
* Credo ignore nesting
* apply suggestion - remove Sql.Util
* apply suggestion - pass imported? via opts
* remove duplicate function
* Uncomment tests
* Fix 500 error with goal suggestions
---------
Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
* Update `ua_inspector` fork to sanitize multi-part prereleases properly
* Add regression tests
* Make another version bump to include a fix for a missed corner case
* Add ability to lookup by email and site domain in HelpScout integration
* Handle callback with invalid parameters gracefully
* Add routine adjusting iframe height to the content of HS integration
* Add requestStorageAccess routine to support iframe cookies in Safari
* Fill first email pick when on failed user lookup
* Fix a typo in a comment
* track browser_language, theme, and logged_in for 'Filter Menu: Open'
* track props for 'Signup' and 'Signup via invitation'
* do not track theme as 'system' for non-logged-in users
* fix tests
* Install @tanstack/react-router
* Fix with imported switch
* Refactor redirect to new search parser
* Deregister timeout in ComparisonInput
* Comment uses of window.location
* Fix with imported switch appearing in realtime dashboard
* Handle not found routes more gracefully
* Extend the GSC API with search functionality
* Fix typo in error tuple atom
* log GSC errors
* rename confusing variable name
* Fix the API response format and error handling
* Read results under the `results` key to be consistent with other
endpoints
* Return errors with a non-200 status code, and with an error payload
that will be well constructed into ApiError
* rebuild Google Keywords modal with useAPIClient
* Add pagination support in Search Terms API
* delete unused fixture file
* rename fixture files
* fix tests
* WIP
* Fix issue with more than one page cached
* Make sure we don't access properties of undefined objects
* slight cleanup
* reset limit to 100
* add back the bottom loading spinner when fetching next page
* disable refetchOnWindowFocus in the global queryClient
* render bottom loading spinner only when fetching next page
* create a wrapper for react-query
* fix exhaustive deps warnings in modals
* always pass the full api path to BreakdownModal
* improve function doc
---------
Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
Co-authored-by: RobertJoonas <56999674+RobertJoonas@users.noreply.github.com>
* Add listing sites, goals and custom props to Sites API
* Rename exmaple props in tests
* Rename `allowed_custom_props` -> `custom_properties`
* Expose goal name in GET endpoints for goals in Sites API
* Bump default pagination limit to 100 and max to 1000
* Introduce Goal.name/display_name and use the first one for name in API
* Extend goal list response but hide currency
* Settle on `display_name` instead of `name`
* Allow viewer members to get site details and list site goals
* Don't include currency in goal's display name
* Update tailwind config
Turns out `extra` wasn't scanned properly with
previous wildcards. I don't care any more, it's not slow.
* Add interface for updating funnels
* Extend ComboBox with the ability to preselect an initial value
* Implement editing funnels UI
* Update CHANGELOG
* s/add_funnel/setup_funnel
* modal width 2/5 => 2/3
* Let's not make the list disappear on modal pop-up
* Fix the damn modal width again
* Watch extra dir
* Format
* Remove commented code
The test is implemented elsewhere
* Track funnel modified to drop default selection
* Fix screen size adoption and format large numbers
* Preserve currency so that string casting includes it
* Format
* Fix ComboBox attribute for preselected option
* Replace useDebouncedEffect with useDebounce
This commit refactors the debouncing mechanism in a more extendable way.
Using debounce as a hook that returns a callback (rather than an effect)
makes it reusable for Combobox. This way the useDebounce hook does not
need to worry about whether the function should be called on the first
render or not.
This commit also gets rid of redundant doubled search state.
* rename input to search in Combobox
* Fix debounce in Combobox
* remove debounce-promise
* Fix React CI warnings in PlausibleCombobox
* Silence NPM CI in custom-hooks.js
* cancel scheduled API calls in useDebounce hook when unmounted
* Implement basic HelpScout integration
* Set 127.0.0.1 as a default customer IP in `Plans.with_prices/2`
* Use `is_nil/1` instead of `... == nil` (h/t @aerosol)
* Use `Path.join/1,2` to build API URLs a bit more safely (h/t @aerosol)
* Check for locked sites entirely within query logic
* Move conditional start of HelpScout vault to compile-time
* Include customer_id in error sent to Sentry
* Use `Plug.Crypto.secure_compare/2` for constant-time signature comparison
* Refactor token request function
* Use `Path.join/1` in one more spot
* Use route helper to build CRM URL
- `:verification` flag is no longer needed,
however we'll keep the old "awaiting first pageview" flow
for Community Edition where verification is not available
by default
- `:traffic_drop_notifications` have been tested and should
be enabled for everyone
* Expose current visitors 12h aggregate
* Remove unused site association
* Distinct drop/spike notification factories
* Rename modules accordingly + implement drop handling
* Rename periodic oban service
* Implement drop email
* Rest of the owl
* Update changelog
* Update moduledoc
* Update moduledoc
* Min threshold to 1
* Threshold 1
* Remove merge artifact
* Put panel behind a feature flag
* Format
Some users are reporting wrong results for stats querying from events table
but with session filters.
This seems to be caused by sampling: Namely both tables end up sampled and the
incorrect sample rate seems to get used.
This is sadly impossible to test for in our test suite, but reveals itself in
production with the following query:
```sql
SELECT
toUInt64 (round(uniq (se0.user_id) * any(_sample_factor))) AS visitors
FROM
events_v2 AS se0 SAMPLE 20000000
INNER JOIN (
SELECT
sss0.session_id AS session_id,
any(_sample_factor) AS _sample_factor
FROM
sessions_v2 AS sss0 SAMPLE 20000000
WHERE
(sss0.site_id = _CAST (8195000, 'Int64'))
AND (sss0.timestamp >= _CAST (1720497600, 'DateTime'))
AND (sss0.start < _CAST (1720584000, 'DateTime'))
AND (sss0.entry_page IN ('/'))
AND (sss0.sign = 1)
GROUP BY
sss0.session_id
) AS ss1 ON se0.session_id = ss1.session_id
WHERE
(se0.site_id = _CAST (8195000, 'Int64'))
AND (se0.timestamp >= _CAST (1720497600, 'DateTime'))
AND (se0.timestamp < _CAST (1720584000, 'DateTime'))
```
By removing the inner query SAMPLE clause the result changes >50%
Related old PR: https://github.com/plausible/analytics/pull/2962
This will likely require more work in the future so looking forward to that -
after my vacation.
* Refactor Expression.dimension to accept q
* Handle quarter- and half-hour timezones
Previously APIv2 output didn't start at a full hour for these time zones
and main graph was blank
The core reasoning is that ClickHouse `timeSlots` is not time-zone
aware and works off of unix epoch - meaning that in time zones which
have an offset of 5:45 the "hours" reported would start at minute :45.
The fix is kind of silly - we now divide each hour into 4 and handle
things that way.
Related basecamp issue: https://3.basecamp.com/5308029/buckets/36789884/card_tables/cards/7590936581
* Fix test typo
Some comparisons return __blank__ values. After recent time series fix,
this blew up when trying to parse __blank__ as a date.
This fixes the issue and adds a test for a period with __blank__ values
Co-authored-by: RobertJoonas <56999674+RobertJoonas@users.noreply.github.com>
Previously, revenue metrics were reported as 0.0$ when imports were included with
APIv2. This is because the metrics were not properly included/forwarded by the
imports query.
Not sure how long this bug has persisted, but eh.