Commit Graph

61 Commits

Author SHA1 Message Date
Sanne de Vries dfeda94e06
Add report percentages to dashboard and details view (#5923)
* Update report percentages on dashboard and details view

* Add percentages to Countries, Regions, and Cities reports

* Add percentages to Channels, Sources, and UTM reports

* Add percentages to top pages, entry pages, and exit pages reports

* Update tests to include percentages

* Change dashboard copy from title case to sentence case

* Update details modal style

* Make animations snappier

* Introduce max height to modal and make inner content scrollable

* Improve modal mobile design

- Enable horizontal scroll for details modal on mobile
- Add responsive spacing and positioning to modal

* Added mobile tap behavior to external link in list report

* Show tooltips only when in comparison mode or when the number is abbreviated

* remove previously added showTooltip prop

- This isn't needed anymore since we now handle the tooltip logic in the MetricValue component

* Show long format upon hovering detailed view metrics

* Added mobile tapping behaviour to detailed view

* Added percentages to all detailed views

* Add mobile swipe-to-close behavior for modal

* Adjust sensitivity of modal drag to close

* Use hammerjs for swipe-to-close modal behaviour

* Prevent dragging if gesture starts inside table

* Show 2 decimal places for percentages < 0.1% across dashboard

* Adjust dark mode styles

* Add hover effect to external link icon

* Update tests to expect two-decimal percentages

* Undo hammer install and revert to old modal styling

* Remove CR and % columns from goals and custom props reports on dashboard, and show on hover in detailed view

* Remove unused constants

* Undo conversion rate on hover behaviour

- Unlike percentages, CR should show permanently.

* Show percentages permanently in custom props detailed view

* Adjust width of conversion metrics column

* Updated metric-value test

* Update top-bar test

* Added changelog entry

* Fix test expectations for percentages with imported data

- Update tests to expect correct percentages (≤100%) when imported data is included. These tests will fail until the percentage calculation bug is fixed, documenting the expected behavior.

* Add imported_visitors to tests to ensure correct total_visitors calculation

* Correct imported_visitors count in test
2025-12-16 12:43:16 +00:00
Adam Rutkowski 38381195f8
Reapply+bugfix: goals with custom props (#5936) (#5944)
* Reapply "Goals with custom props (Stats API queries, funnels) (#5936)" (#5943)

This reverts commit 45116bda7b.

* Gracefully handle `nil` for existing goal.custom_props

* Revert "Gracefully handle `nil` for existing goal.custom_props"

This reverts commit 8e38748775.

* Migration: make `goals.custom_props` non-null

* Adjust test
2025-12-11 13:09:34 +00:00
Adam Rutkowski 45116bda7b
Revert "Goals with custom props (Stats API queries, funnels) (#5936)" (#5943)
This reverts commit b6b9c2c0bf.
2025-12-11 09:17:33 +00:00
Adam Rutkowski b6b9c2c0bf
Goals with custom props (Stats API queries, funnels) (#5936)
* Migration: add custom propos to goals + revisit unique constraints

* Update constraints in goal schema (and move module)

* Add a comment, not really related but useful?

* Implement querying for goals with custom props

* Optimize goal_join_data (down to one iteration) + include goal custom props

* Test goal custom propos addition + new constraints

* Test querying for goals with custom propos attached

* Test funnels made of goals with custom props

* Format

* Fixup test name

* Fixup migration

* Unified goal join macro

* Remove dupe test

* Clean up user_id usage

* Fixup test to match the description

* Revert "Temporary: make room for pre/post migration constraint names (#5942)"

This reverts commit e4bc6b8715.

---------

Co-authored-by: Uku Taht <uku.taht@gmail.com>
2025-12-11 08:39:46 +00:00
Adrian Gruntkowski 98632aee74
Don't multiply average revenue metric by sampling rate in the query (#5931)
* Don't multiply average revenue metric by sampling rate in the query

* Fix formatting
2025-12-03 14:49:11 +00:00
Adrian Gruntkowski a2ba1256d2
Show revenue data in all breakdowns (#5767)
* Include revenue data for all detailed API responses except entry/exit pages

* Expose revenue data in all breakdown modals except entry/exit pages

* Add revenue metrics to breakdown response only on EE

* Change query builder to enable querying event metrics \w session dimension

* Add revenue metrics to entry and exit pages breakdowns

* Expose revenue data in entry and exit pages breakdowns

* Use `argMax` for `exit_page` and `exit_page_hostname` dimensions (h/t @ukutaht)

* Don't handle event-only dimensions with session-only metrics for now

* Add tests for all breakdowns

* Add clarifying comments in code

* Mark revenue tests as EE-only
2025-11-18 11:24:54 +00:00
Adam Rutkowski bce08903e5
Integrate consolidated view UI (#5798)
* Create static consolidated view UI on `/sites` page

- Improve existing site card layout
- Add static UI for the consolidated view
- Add dismissable upgrade card UI
- Extract favicon fetching logic to function
- Configure configurable fallback icon per route
- Add `/favicon/sources_globe/` route with different icon than `/favicon/sources/` to use on `/sites` page

* Improve the mobile view of the `/sites` page

* Minor query interface UX extension (#5713)

* Minor query interface extension

* !fixup

* !fixup

* Initial implementation of consolidated views on /sites

* Improve loading state

* no need to handle nil in main interface

* Juggle `can_manage_consolidated_view?`

* Require team setup in order to enable consolidated view

* nil catcher

* Fixup test fixture

* Don't show Consolidated View tab in CS if team is not setup

* Reorganize + test

* Remove comment

* Only show consolidated views to superadmins for now

* Remove temporary sleep

* CE unused bindings

* Clean up seeds

* EE

* Fixup test

* Test non-superadmin scenario

* Add a test guarding parity between small plots (consolidated vs individual)

* Move private function so CE won't complain

* See if the graphs are now similar at least :)

* sort

* Map keys are unsorted

* Ensure engagement events aren't counted as visitors on smol graphs

* just try and revert

* Revert "just try and revert"

This reverts commit 7584f59816.

* Simplify globe icon handling

* Remove unnecessary @rest

* Split tests into more focused cases

* Address jumpiness on furious refresh cycle

* Revert "Address jumpiness on furious refresh cycle"

This reverts commit 5c03b36918.

* Another attempt at jumpiness

* Enforce less noticeable lag applying the diff from loading to loaded

* Reduce flashing on stats load

---------

Co-authored-by: Sanne de Vries <sannedv@protonmail.com>
2025-10-22 10:58:26 +00:00
RobertJoonas cc06a351bd
Remove virtual rollups in favour of persisted consolidated sites (#5749)
* virtual rollups -> consolidated sites

* fix queryparser and test

* fix legacy_query_builder and test

* fix typespec

* simple consolidated view query test (Stats API)

* add test util

* skip verification on consolidated sites

* add test for internal (dashboard) stats query

* fix CE

* Fix showing consilidated stats on the dashboard

...by making sure site.native_stats_start_at and stats_start_date are
set.

* fix CE again

* add typespecs and tests for native_stats_start_at

* skip else clause

* use ConsolidatedView.enable in test util

* defensive where builder

* remove redundant cache

* get query.consolidated_site_ids from cache

* fix test

* fix CE

* fix CE again

* eligibility check when enabling cvs

* create cvs with native_stats_start_at assigned already

* fix dialyzer warning
2025-09-25 13:58:32 +00:00
Adrian Gruntkowski 26a6a2e3af
Add ability to filter by substring of "Direct / None" in `contains` (#5738)
* Add ability to filter by substring of "Direct / None" in `contains`

* Add tests
2025-09-23 12:20:53 +00:00
Adam Rutkowski ad46776f9f
Use fragment to bind list of ids as a single param (#5730)
* WIP

* Alternative approach to OG approach (h/t @zoldar)

* Revert "WIP"

This reverts commit 7e3f0c1f8f.
2025-09-16 11:31:20 +00:00
Karl-Aksel Puulmann 1531386b76
FULL join for time:hour as well as time:minute (#5715)
* FULL join for time:hour as well as time:minute

Follow-up to https://github.com/plausible/analytics/pull/5694/files#r2321567271

A session might be active over multiple hours, but not (currently)
reported as such when requesting only specific metrics per hour.
This fixes that problem.

* Handle full join logic correctly

---------

Co-authored-by: Uku Taht <Uku.taht@gmail.com>
2025-09-15 14:14:59 +00:00
RobertJoonas d02636dd07
POC: Rollup view (#5719)
* POC rollup dashboard

* add rollups to stats api

* remove the irrelevant new controller action

* use team_identifier instead of team_id
2025-09-15 11:51:37 +00:00
Karl-Aksel Puulmann db448d7404
Stats: Rebuild session smearing for timeseries (#5694)
* Refactor table_decider#partition_metrics

* Refactor query pipeline to return a list of subqueries after splitting

* Move order_by out of join logic

* Refactor joining logic in query_builder

1. JOIN type is now set in QueryOptimizer
2. JOIN logic is now table and list-size agnostic

* Comment an edge case

* Rebuild session/visit smearing

Previously, whenever graphing any visit metric hourly/realtime, visit_duration and other
visit metrics would be way higher than expected, due to long sessions
dragging each bucket up and up. Now visits/visitors metrics are still
smeared and other visit metrics are counted under last bucket user was
active in.

visits metric was also overcounted (see new tests).

* Remove unneeded case

* Unit test for smearing in tabledecider
2025-09-08 06:21:12 +00:00
RobertJoonas dffb698fa2
Change log level from info to notice on relevant logs (#5585)
* change log level from info to notice on relevant logs

* bump log level to notice for everything except request logger

* format

* fix choose_plan_test.exs for good (starter tier launch)
2025-07-23 08:47:01 +00:00
Adrian Gruntkowski 8da98fb26e
Safeguard sign-dependent metrics from negative values (#5569)
* Safeguard sign-dependent metrics from negative values

* Test graceful visits calculation for invalid sessions data
2025-07-17 12:45:14 +00:00
RobertJoonas 4eb4b68b99
Sort by exit rate (#5289)
* WIP

* Works, maybe

* More tests

* format + slight refactor special_metrics

* implement exit_rate equivalent to current dashboard metric

* add validations to query_parser

* implement comparisons for exit_rate

* merge imported exit rate

* plug in the new metric

* make exit_rate sortable

* changelog

* generate types

* rename tests

* changelog

* maintain order of special metrics

* move exit_rate to the bottom as the less significant special metric

* capitalize null + query assign tweaks

* add comment

* Update lib/plausible/stats/sql/special_metrics.ex

Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>

---------

Co-authored-by: Artur Pata <artur.pata@gmail.com>
Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>
2025-04-09 09:47:12 +00:00
RobertJoonas 8e0f618c91
Increase Conversion Rate precision by one decimal place (#5250)
* change cr and group_cr rounding precision

* fix tests

* changelog
2025-03-31 09:11:47 +00:00
RobertJoonas c7bf54325e
Fix visitors.csv vs main graph discrepancy (#5230)
* fix typo to stop logging error in test output

* add time:minute interval to internal api schema

* always get visitors and visits from sessions table when time:minute dimension used

* query-api generate types

* changelog update
2025-03-25 16:18:48 +00:00
Karl-Aksel Puulmann 0514a6db18
time-on-page: dashboard + timeseries support (#5174)
* Support passing `include` as a query parameter for dashboard APIs

* Mark time-on-page metric sortable

It now is thanks to the changed query

* new-time-on-page flag with cutoff being sent to the frontend

* Add correct tooltip title

* Implement metric warning for when legacy and new time_on_page metrics are mixed

* Send legacy_time_on_page_cutoff to backend

* Make time-on-page graphable with the new metric

* Only show metric warnings for time_on_page if flag is enabled

* Changelog

* Solve an clickhouse error when querying timeseries with only legacy time-on-page

* Add tests for timeseries of new time-on-page

Along the way fix an issue with comparisons not working properly

* Solve a typing issue

* Allow toggling legacy_time_on_page_cutoff off in dashboard

* Slightly better workaround

* Solve typing issue

* Prettier

* Guard against no warning

* Solve warning
2025-03-12 09:51:53 +00:00
Karl-Aksel Puulmann e9b30e0ba5
time-on-page: query (#5159)
* Default to time_on_page

* Add new columns to schema

* Read from new column in legacy query

* Read/write new imported_pages columns

* Remove time_on_page column from imported_pages

* Simple, stupid new_time_on_page metric

* Update csv_importer schema

* Refactor: consistent __internal helpers, this will help with joining the query

* Refactor select_joined_metrics

* Refactor: pass `query` to event_metric

* Refactor: remove needless site argument from various calls

* Legacy joining query attempt

* Move test around

* Add more tests for both legacy and new time_on_page metrics in query API

* time_on_page reported in seconds

* timeseries test for metric

* WIP

* Wrap main query in subquery - without this run into trouble performing the join

* Calculate time_on_page in main query, no more new_time_on_page

* Add some TODOs

* Return NULL over 0 when no visits with time-on-page data

* Update moduledoc

* Update some tests that were not expecting integers

* Add a TODO

* Update tests

* Make graphing time series with combined metrics work.

* Slightly more consistent approach to flag updating in APIv2

* Seeds with engagement data

* Make graphing time series when cutoff is in the middle work

Bakes less assumptions into everything as well.

* Rename to legacy_time_on_page_cutoff

* Fixup lib/plausible_web/controllers/api/external_query_api_controller.ex

* Remove a todo and dead/misleading code

* Remove a resolved todo

* Remove needless rounding

* gen types

* Update pages test

* Remove needless columns from select

* Update tests: timestamps and remove comment

* Flip branches
2025-03-11 11:19:58 +00:00
Karl-Aksel Puulmann 8aad9b1adc
APIv2: Fix `percentage` metric 500s (#5099)
* Refactor: remove metrics argument from merge_imported()

* Support querying percentage without visitors metric

* Fix ordering by special metrics with imports causing a 500

We don't calculate all metrics directly on imports, hence cannot order
the import by them either.

* Changelog
2025-02-26 07:07:17 +00:00
Karl-Aksel Puulmann 53581973d0
Scroll depth: ingestion, query and import/export changes (#5072)
* Revert "Disable scroll depth exports temporarily"

This reverts commit 48ad691f53.

* Remove support for pageleave events being equivelent to engagement in ingestion

* Explicit column ordering inside csv imports

Subtle change, but this ensures that CSVs that contain extra columns or differently named columns do not cause trouble

* Add scale_sample fragment helper

* Update scroll depth queries to be based on visits rather than visitors

* Add test demonstrating session-based results

* Update csv test (session vs user-based difference)

* Attempt to update csv tests

* PR feedback
2025-02-17 10:03:39 +00:00
Karl-Aksel Puulmann 89a6b77132
Scroll depth: Rename imported_pages columns to reflect whats desired (#5071)
* Migration: Rename imported_pages columns to reflect whats desired

* Disable scroll depth exports temporarily

* Migration fix
2025-02-17 11:48:19 +02:00
Karl-Aksel Puulmann 47c095f65b
Remove a dead todo (#5064) 2025-02-13 07:26:54 +00:00
Karl-Aksel Puulmann 3f6c64cf03
Update queries to work off of `engagement` events over pageleaves (#5053)
Note that export pageleave_visitors column has not been updated here.
2025-02-06 11:27:38 +00:00
RobertJoonas 4d05245036
Page Scroll Goals (#5029)
* migration: add scroll_threshold to goals

* update goal schema

* setup simple UI for creating scroll goals

* add ability to filter and breakdown scroll goals

* fix goals form tests

* add valiation for page path exists

* move todo comments to expression.ex

* move tests

* make it clear that scroll_threshold is optional

* avoid calling Plausible.Goal.type() too many times

* do not consider 255 scroll depth a conversion

* migration: add scroll_threshold to goals

* do not drop the old index yet

* More efficient goals join again

* Refactor: move goals stats code explicitly under Stats.Goals module

* Move code under Plausible.Stats.Goals

* 254 -> 100

* add scroll_threshold field to goal schema + new unique constraint

* adjust test to test what it claims to

* mix format

* add migration

* consider imported query unsupported when page scroll goal filter

* add missing tests

* pattern match imported argument

* silence credo

* Update lib/plausible/stats/sql/expression.ex

Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>

* use site_imports populated in test setup

---------

Co-authored-by: Karl-Aksel Puulmann <oxymaccy@gmail.com>
Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>
2025-02-04 10:37:04 +00:00
Karl-Aksel Puulmann 9a4969e105
APIv2: Behavioral filtering (#4980)
* Expose site_id and site_native_stats_start_at via query

This allows to do more query-building without exposing and passing `site` directly.

* Very basic has_done/has_done_not operator support

No event:goal support yet, no validations

* Add validations that only event: dimensions can be used within has_done/has_done_not

* Allow event:goal filters nested within has_done/has_done_not behavioral filters

* Minor fix for do_decide_custom_prop_table

* has_done support for goals

Minor changes along the way:
- preloaded_goals structure changes
- event:goal restrictions were loosened within has_done
- we don't allow nesting has_done anymore

* Dont query imports when behavioral filters are present

* Update callsites of filtering_on_dimension? to work with new behavioral filters

* has_done_not -> has_not_done

* Changelog entry

* Typegen

* credo cleanup

* Fix changelog

* Remove changelog

* Mark has_done as internal-only

* combine two validations into a single loop

* has_done is now session-based not user-based

* Update a test

* Update transform_tree
2025-01-21 12:03:26 +00:00
RobertJoonas 3473910c97
Average Scroll Depth Metric: imported data (#4915)
* include scroll_depth in full pages export

* import scroll_depth from CSV

* query scroll depth from imported data

* fix ordering by scroll depth with imported data

* fix imported scroll depth query + more tests

* enable scroll depth in top stats with imported data

* add main graph test

* fix test and native scroll depth sum select

* Update lib/plausible/exports.ex

Co-authored-by: ruslandoga <doga.ruslan@gmail.com>

* adjust test

* adjust test to catch error

* export/import/count pageleave_visitors

* extract base_q in export_pages_q

* rename total_visitors to pageleave_visitors

---------

Co-authored-by: ruslandoga <doga.ruslan@gmail.com>
2025-01-07 10:59:26 +00:00
RobertJoonas d21d48558a
Average Scroll Depth Metric: handle missing data better (#4889)
* ingest missing pageleave as 255 for pageleave events

* return scroll depth as nil when no valid pageleave data in range

* also set empty comparison value as nil instead of 0

* add data migration
2024-12-10 12:29:13 +00:00
Karl-Aksel Puulmann 0c8fed9570
Fix: Add missing SAMPLE BY to query (#4880)
* Fix: Add missing SAMPLE BY to query

* Update lib/plausible/stats/sql/query_builder.ex
2024-12-09 08:54:39 +00:00
Karl-Aksel Puulmann bec14ee77c
Improve report performance with high-cardinality import joins (#4848)
* Improve report performance in cases where site has a lot of unique pathnames

Ref: https://3.basecamp.com/5308029/buckets/39750953/card_tables/cards/8052057081

JOINs in ClickHouse are slow. In one degenerate case I found a user had
over 20 million unique paths in an import, which resulted in extremely slow
JOINs. This introduces a sort-of hacky solution to it by limiting the
amount of data analyzed.

Query timing without this change:
```
9 rows in set. Elapsed: 11.383 sec. Processed 49.16 million rows, 5.75 GB (4.32 million rows/s., 505.29 MB/s.)
Peak memory usage: 14.75 GiB.
```

After:
```
9 rows in set. Elapsed: 0.572 sec. Processed 49.18 million rows, 5.75 GB (86.03 million rows/s., 10.06 GB/s.)
Peak memory usage: 9.01 GiB.
```

* Splitting should no longer remove pagination. Handle special cases in special_metrics.ex

* select_merge_as in imports

This sets up selected_as aliases which will be used in a subsequent commit

* Add explicit ORDER BY to import

* Rewrite comment

* quoting

* merge conflict

* Split test

* Merge conflict fail fix
2024-12-05 10:05:57 +00:00
Karl-Aksel Puulmann a38eacfed5
APIv2: Case insensitive search (#4863)
* WIP: Optional modifiers to queries

* WIP: Modifiers v2

* Use preloaded_goals when determining whether imports can be included

This was previously broken with conversion_rate totals metrics since it removed event:goal
filters but did not update preloaded_goals

* Preload goals according to modifiers

* Make case_sensitive: false work for is/contains operators

* Make modals send { case_sensitive: false } to backend for search

* CHANGELOG.md

* Typegen

* Prettier

* Refactor: more DRY where_builder for case sensitivity

* Support case_sensitive modifier for is_not/contains_not

* Cleanup

* credo

* remove defaults

* negating a previously set filter
2024-12-03 10:32:16 +00:00
RobertJoonas 6822b29016
Average Scroll Depth Metric: put scroll depth on the dashboard under a feature flag (#4832)
* migration: add scroll_depth to events_v2

* (cherry-pick) ingest scroll depth

* replace convoluted test with more concise ones

* QueryParser: parse internal scroll_depth metric + validation

* turn QueryComparisonsTest into QueryInternalTest

* rename file

* (cherry pick) query scroll depth 15b14d3

...and move the tests into `internal_query_test.exs`

* review feedback

* Get rid of unnecessary separation between aggregate and group scroll depth
* Drop irrelevant other metrics in tests

* add test ensuring scroll depth unavailable in Stats API v1

* Put scroll depth on the dashboard

* Top Stats
* Main Graph
* Top Pages > Details

* feature flag for dashboard scroll depth access

* ignore credo warning

* enable scroll_depth flag in tests

* remove duplication

* write timestamps explicitly in a test

* revert moving tests around

* Add query_comparisons_test back
* Move scroll_depth tests into query_test
* Delete query_internal_test

* rename setup util (got updated on master)

* use pageleave_factory where applicable

* Use the correct generated query-api.d.ts

* npm format
2024-11-20 13:13:04 +00:00
Karl-Aksel Puulmann 3809ebf4ba
Channels: Read from new column, don't write (#4800)
* Read and write channels from `acquisition_channel` column

* Update csv tests
2024-11-12 12:30:11 +00:00
Karl-Aksel Puulmann eed21a0138
APIv2: Remove cruft (v2 flag, experimental_reduced_joins) (#4780)
* Remove query.v2 flag

This was originally used for making sure queries use the right table as
migrating to APIv2. This is no longer needed

* Remove experimental_reduced_joins flag
2024-11-06 12:08:20 +00:00
Karl-Aksel Puulmann 472f4f181c
Comparisons pagination fixes (#4697)
* Add filter clauses for each main result filter

This handles the case where main query has a limit and results change. Doesnt handle metrics like percentage.

* Fix percentage calculations by ignoring breakdown-related filters in totals queries

* Refactor comparisons test suite

* Move comparisons logic to comparisons module

* New route for internal query tests

Only to be used in testing

* Support comparison queries with imports/breakdowns

* time dimension predicate extraction

* Clean up a test

* Update docstring

* Update route test

* fix a typo
2024-10-22 10:23:40 +00:00
RobertJoonas 5c72de0155
Experimental pageleave events (#4624)
* add experimental pageleave script variant

* also send pageleave events on SPA navigation

* disallow goals with 'pageleave' event name

* do not count pageleaves towards the event metric

* remove duplication in test file

* do not update sessions on pageleave events

* ignore pageleaves in the current time_on_page implementation

* make pageleave events not billable

* rename function

* Prevent multiple pageleaves being sent at the same time
2024-09-30 12:52:40 +00:00
Uku Taht 7a77ebf9bf
Add feature-flagged channels UI (#4585)
* Add feature-flagged channels UI

* Implement channels modal

* Channel -> Channels tab
2024-09-18 08:34:12 +00:00
Karl-Aksel Puulmann ef57502854
APIv2: Implement pagination and `include.total_rows` (#4575)
Offset-based pagination is used to make sure Looker integration
is able to work as efficiently as possible. To know how many
requests users need to do `include.total_rows` option was added.
2024-09-12 15:51:18 +03:00
Karl-Aksel Puulmann bd11b4cf67
APIv2: Standard iso8601 timestamps, operate on UTC (#4563)
* query.date_range is now in UTC instead of user timezone

This simplifies things down the line and fixes several bugs where
query.date_range is cast to naivedatetime for ecto purposes

Many places still remain broken:
- comparison queries
- `to_date_range` calls

* Make default_for_date_range not care about time zones

* Make timezone parameter mandatory for to_date_range

* Simplify utc_date_range, update legacy query builder

* Fix more cases where query date range is needed

* query.date_range -> query.utc_time_range

* Query.date_range/1 function

* ensure_include_imported update

* Clean up send_email_report
2024-09-11 09:21:59 +03:00
Adrian Gruntkowski 8ba5f7d32f
Safeguard queries relying on `sign` from faulty old session entries (#4555)
* Safeguard session queries relying on `sign` from faulty old session entries

* Comment updated metric

Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>

* Apply safeguards to `bounce_rate` metric only

* Add note to bounce rate definition in SQL fragments as well

* Add test for graceful bounce rate handling in breakdown

* Make user_id more unique

* Add a note to the test

* Move regression test to APIv2 tests

---------

Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>
2024-09-10 13:22:49 +02:00
Karl-Aksel Puulmann 604dde99fd
APIv2: Regex operations, consistent operators (#4488)
* Rename matches/does_not_match filters internally

These have never been exposed to the frontend/user directly, only via
APIv1 filtering syntax. As such we are free to rename these without
breaking things

* Rename function arguments for consistency, simplify

* Add support for `match`/`not_match` operators for query apiv2

These match the string against a regular expression, as defined in
https://github.com/google/re2/wiki/Syntax

* not_match -> match_not

* does_not_contain -> contains_not

Note that for backwards compatibility:
- Browser handles does_not_contain in URL
- Backend will handle does_not_contain in queries for a day where we will remove it for better autocompletion

* not_matches_wildcard -> matches_wildcard_not

* prettier

* match -> matches

* Fix and test fix for matches_wildcard against prop when prop is missing

* Custom properties support for matches/matches_not

* Restore contains_not

* Test contains and contains_not behavior for custom properties
2024-09-09 10:05:24 +03:00
Karl-Aksel Puulmann 8fa3a83129
APIv2: and/or/not support (#4480)
* First approximation of AND/OR/NOT support

Broken by this:
- Goal filtering
- Table deciding
- Imports

* TableDecider handle nesting

* Query.remove_top_level_filters

* Plausible.Stats.Imported.SQL.Expression

* Handle AND/OR/NOT with imported data, create Plausible.Stats.Imported.SQL.WhereBuilder

* Add parser validations for event:goal, event:hostname and event:props:x filters top level constraints

* Move module around

* Query.get_filter -> Filters.filtering_on_dimension? in some callsites

* Filters.get_toplevel_filter

* TableDecider.sessions_join_events?, remove old method

* Transforming filters in query_optimizer

* Query API tests for and/or/not

* Reorder parser steps

* Post-merge test fixups

* Solve merge issue

* Simplify filtering_on_dimension?

* Update transformer code

* dimensions_used_in_filters min_depth option, simplify parser validations

* rename_dimensions_used_in_filter

* fix rename_dimensions_used_in_filter

* Rename a test
2024-09-04 15:44:03 +03:00
RobertJoonas 93c9061ab2
Proper fix for realtime timeseries queries (#4509)
* enforce same timezones in date_range param

* use query.date_range.first.timezone as query.timezone
2024-09-03 10:12:50 +03:00
RobertJoonas 5e26e2c97d
Fix realtime periods returning wrong date range for non-UTC timezone sites (#4508)
* fix realtime

* mix format
2024-09-02 19:21:17 +03:00
RobertJoonas f04c47f881
Support realtime periods in API v2 (#4469)
* add realtime date_ranges into the private API schema

This commit starts parsing date ranges into a new NaiveDateTimeRange
struct, rather than a simple Date.Range.

* transform realtime labels into negative integers + test

* move schema type argument to last position in helper functions

* allow passing a date param + tests

* Update test/plausible/stats/query_parser_test.exs

Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>

* Update test/plausible/stats/query_parser_test.exs

Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>

* Update test/plausible/stats/query_parser_test.exs

Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>

* Update test/plausible/stats/query_parser_test.exs

Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>

* keep test file structure consistent

* Turn NaiveDateTimeRange into DateTimeRange

* change 'now' field from NaiveDateTime to DateTime in v2 query

* fix minute interval labels + add missing tests

* return query_result.date_range as iso8601 timestamps with timezone

* allow timestamps with tz as date_range arguments in API v2

* delete Plausible.Timezones.to_utc_datetime

* simplify returning comparison periods

* add comment about realtime not supported in comparisons

* pass only now instead of test_opts

* drop redundant else branch

* separate tests

* stick to a single check_date_range function in tests

* fix credo error

---------

Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>
2024-09-02 12:56:58 +03:00
ruslandoga 48dfce7a8b
update ecto_ch and use ecto hints for array joins (#4456) 2024-08-21 06:28:25 +02:00
Karl-Aksel Puulmann ee3d1e770e
APIv2: visit:country_name, visit:region_name, visit:city_name dimensions (#4328)
* Add data migration for creating and syncing location_data table and dictionary

* Migration to populate location data

* Daily cron to refresh location dataset if changed

* Add support for visit:country_name, visit:region_name and visit:city_name dimensions

Under the hood this relies on a `location_data` table in clickhouse being regularly synced with
plausible/location repo and dictionary lookups used in ALIAS columns

* Update queue name

* Update documentation

* Explicit structs

* Improve docs further

* Migration comment

* Add queues

* Add error when already loaded

* Test for filtering by new dimensions

* Update deps

* dimension -> select_dimension

* Update a test
2024-08-13 09:44:58 +03:00
Uku Taht 05b70e37a8
Generate goal filter SQL from postgres goals (#4391)
* 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>
2024-07-30 12:07:23 +03:00
Adrian Gruntkowski e2d1714f90
Make time range filter for sessions not break sample size estimation (#4394) 2024-07-26 16:19:11 +03:00