* 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
* Add safeguard against flaky auth rate limit tests
* Fix typo in a log message
* Extract and abstract rate limiting from `AuthController`
* Fix flaky rate limit test tag
* Don't leak prefix from auth rate limit
* Use more compact map syntax
* Remove special tag in favor of `eventually` test util function
* Update Goal schema
* Equip ComboBox with the ability of JS selection callbacks
* Update factory so display_name is always present
* Extend Goals context interface
* Update seeds
Also farming unsuspecting BEAM programmers for better
sample page paths :)
* Update ComboBox test
* Unify error message color class with helpers seen elsewhere
* Use goal.display_name where applicable
* Implement LiveView extensions for editing goals
* Sprinkle display name in external stats controller tests
* Format
* Fix goal list mobile view
* Update lib/plausible_web/live/goal_settings/list.ex
Co-authored-by: Artur Pata <artur.pata@gmail.com>
* Update lib/plausible_web/live/goal_settings/form.ex
Co-authored-by: Artur Pata <artur.pata@gmail.com>
* Update the APIs: plugins and external
* Update test so the intent is clearer
* Format
* Update CHANGELOG
* Simplify form tabs tests
* Revert "Format"
This reverts commit c1647b5307.
* Fixup format commit that went too far
* ComboBox: select the input contents on first focus
* Update lib/plausible/goal/schema.ex
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Update lib/plausible/goals/goals.ex
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Update lib/plausible_web/live/goal_settings/form.ex
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Pass form goal instead of just ID
* Make tab component dumber
* Extract separate render functions for edit and create forms
* Update test to account for extracted forms
* Inline goal get query
* Extract revenue goal settings to a component and avoid computing assigns in flight
* Make LV modal preload optional
* Disable preload for goal settings form modal
* Get rid of phash component ID hack
* For another render after render_submit when testing goal updates
* Fix LV preload option
* Enable preload back for goals modal for now
* Make formatter happy
* Implement support for preopening of LV modal
* Preopen goals modal to avoid feedback gap on loading edited goal
* Remove `console.log` call from modal JS
* Clean up display name input IDs
* Make revenue settings functional on first edit again
* Display names: 2nd stage migration
* Update migration with data backfill
---------
Co-authored-by: Artur Pata <artur.pata@gmail.com>
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* return concatenated browser names and versions directly from the API
* return concatenated os names and versions directly from the API
* add detailed views for all device reports
* extract put_combined_name_with_version function
* return only version under the name key when detailed=true
* update changelog
* add more metrics into detailed views of Devices reports
* split up different devices modals into separate files
* 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>
* 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
* 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
* 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
* 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
* 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
* 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.
* Fix filter ["contains", "visit:country", ["E"]]
This blew up since FixedString columns dont natively support matching functions for some reason
* Dont blow up for 3-letter country codes, instead fail validation
* Allow sending numbers for visit:city along with strings
This simplifies querying as we pass the list of cities as numbers to clients
* use &is_integer/1
* Remove redundancy
* Create a new BreakdownModal component and use it for Entry Pages
* Add search functionality into the new component
* Adjust FilterLink component and use it in BreakdownModal
* pass addSearchFilter fn through props
* pass fn props as useCallback
* add a function doc to BreakdownModal
* refactor: create a Metric class
* Fixup: use Metric class for defining BreakdownModal metrics
* keep revenueAvailable state in the Dashboard component
* move query context into a higher-order component
* fix react key error in BreakdownModal
* use BreakdownModal in PropsModal
* adjust EntryPagesModal to use query context
* fix variable name typo
* fixup: BreakdownModal function doc
* use BreakdownModal in SourcesModal
* use Breakdown modal in ReferrerDrilldownModal
* use BreakdownModal in PagesModal
* use BreakdownModal in ExitPagesModal
* replace ModalTable with LocationsModal and use BreakdownModal in it
* use BreakdownModal in Conversions
* make sure next pages are loaded with 'detailed: true'
* replace loading spinner logic in BreakdownModal
* fix two flaky tests
* unfocus search input element on Escape keyup event
* ignore Escape keyup handling when search disabled
* Review suggestion: remove redundant state
* do not fetch data on every search input change
* use longer variable names
* do not define renderIcon callbacks conditionally
* deconstruct props in function header of BreakdownModal
* refactor searchEnabled being true by default
* Remove a dead method
* Move select_event/session_metrics to within QueryBuilder
* Make a method private
* Move page_regex util around
* Move utc_boundaries helper around
* Fixups for utc_boundaries
* Add legacy notices
* Move Stats.query method around
* include_sentry_replay_info consistently
* Move filters out of select_group_fields
* Collapse conditions under select_group_fields
* Shorten some imported methods
* Use dimension over dim in group_by
* Separate SQL query building from imported.ex
* props.ex -> legacy_dimensions.ex
* Move some query building out of Query.ex
* Remove unneeded method
* put_filter -> add_filter
* Remove some query setters
* Moduledoc
* Split out validations and import tests from query_test
* Move tests around
* Split event:goal tests from query_test
* Remove redundant filters
* Remove dead code
* Split special metrics tests from query_test
* Legacy module
* Move fragments module under Plausible.Stats.SQL
* Introduce select_merge_as macro
This simplifies some select_merge calls
* Simplify select_join_fields
* Remove a needless dynamic
* wrap_select_columns macro
* Move metrics from base.ex to expression.ex
* Move WhereBuilder under Plausible.Stats.SQL
* Moduledoc
* Improved macros
* Wrap more code
* select_merge_as more
* Move defp to the end
* include.time_labels parsing
* include.time_labels in result
Note that the previous implementation of the labels from TimeSeries.ex was broken
* Apply consistent function in imports and timeseries.ex
* Remove boilerplate
* WIP: Limited support for timeseries-with-querybuilder
* time:week dimension
* cleanup: property -> dimension
* Make querying with time series work
* Refactor: Move special metrics (percentage, conversion rate) to own module
* Explicitly format datetimes
* Consistent include_imported in special metrics
* Solve week-related crash
* conversion_rate hacking
* Keep include_imported consistent after splitting the query
* Simplify do_decide_tables
* Handle time dimensions in imports cleaner
* Allow time dimensions in custom property queries
* time:week handling continued
* cast_revenue_metrics_to_money
* fix `full_intervals` support
* Handle minute/realtime graphs
* experimental_session_count? with timeseries
This becomes required as we try to include visits from sessions by default
* Support hourly data in imports
* Update bounce_rate in more csv tests
* Update some time-series query tests
* Fix for meta.warning being included incorrectly
* Simplify imported.ex
* experimental_session_count flag removal
* moduledoc
* Split interval and time modules
* Refactor and unify auth plugs for Stats and Sites APIs
* Expose get site Sites API endpoint to all API keys
* Test the new plug
* Add test for endpoint with modified scope
* Fix typos
Co-authored-by: hq1 <hq@mtod.org>
* Rename plug for consistency (h/t @aerosol)
---------
Co-authored-by: hq1 <hq@mtod.org>
* Revert "Revert "APIv2: Replace breakdown module with QueryBuilder (#4283)" (#4292)"
This reverts commit ef5e0e0382.
* Allow querying events and pageviews from sessions table
This is not strictly accurate, especially with shorter time frames, but
is useful for a fallback mechanism. I'll figure out something around
shorter time frames in the future.
See also: https://github.com/plausible/analytics/pull/4292
* Only query events and pageviews in legacy breakdowns
* WIP: Breakdown using QueryBuilder
* Revert "Remove problematic test"
This reverts commit b442bb5d1f.
* Get more breakdown tests passing
* Preload goals, sort when dealing with time_on_page
* Handle conversion_rate in breakdowns
* Simplify ordering by using selected_as consistently for dimensions
* Get breakdown tests passing
* Strings to atoms in keys for StatsController.transform_keys calls to work
* Handle revenue metrics removal
* Add test for nil-removal case
* Include percentage metric
* Fix and test with imported locations
* Fixup time-on-page
* Fix country/region automatic filters
* Handle multiple imports (os/browser version) in importsv2
* Filter goals
* Default to ordering by page as well
* Calculate conversion rate on sessions if needed
* Order by event dimensions - handles event:page special case
* Update tests
* Update more tests, handle goal=0 case in imports
* Handle event:goal breakdowns correctly with filters
* Revenue to money
* Improved table deciding
* Also update event:page filters on event:page breakdown
* bounce_rate to 0
Previous behavior relied on two queries being made - new query leads to 0 naturally
* Update pagination test
* dont count non-pageviews as path goal completions
* Make revenue logic breakdown-specific
Its hard to fit into the new schema and likely needs a rethink for apiv2
* Retain previous behavior for TimeSeries module
* Get GA4 test passing
Most failures are related to ordering, pageviews shouldnt be read off of sessions
* Clean up old methods
* Simplify imported.ex
* Dont crash on garbage filters
* Reflect ordering-related change in test
* Fix test data
* Update table_decider
* Re-simplify get_revenue_tracking_currency
* Revert revenue changes
* Use Query.set
* Remove a TODO
* csv importer: no pageviews
Pageviews were incorrectly fetched from sessions table before, causing issues
* csv importer tweaking
* Remove use Plausible
* to_existing_atom
* Add some aggregates tests
* Port aggregates tests to do with filtering
* Session metrics can be queried with event: filters
* Solve a typo
* Update a validation message
* Add validations for views_per_visit
* Port an aggregation/imports test
* Optimize time dimension, add tests
* Add first timeseries test, update parsing tests
* Docs for SQL.Expression
* Test timeseries more
* Allow time explicitly in order_by
* Add multiple breakdowns test
* Refactor QueryOptimizer not to care about time dimension placement in dimensions array
* Add test breaking down by event:hostname
* Add hostname filtering logic to QueryOptimizer, unblock some tests
* WIP: Breakdown by goal
* conversion rate logic for query api
* Update more tests
* Set default order_by
* dimension_label
* preloaded_goals in tests
* inline load_goals
* Use Date functions over Timex
* Comments
* is_binary
* Remove special form used in tests
* Fix defmodule
* WIP: Fix memory leak, event:page breakdown logic
* Enable more tests, fix for group_conversion_rate without explicit visitors metric
* Re-enable a partially commented test
* Re-enable a partially commented test
* Get last test passing
* No imports order_by in apiv2
* Add a TODO
* Remove redundant Util call
* Update aggregate.ex
* Remove problematic test
* add notice about pending ownerships counting towards usage
* Refactor feature usage to take site_ids too
* Add option to query usage from pending ownerships
* count pending ownerships towards usage on the choose-plan page
* turn 'eligible_for_upgrade?' into a predicate
* fix variable names on ce
* fix unused alias on ce
* fix ce test
* WIP new querying
* WIP: Move some aggregate code under new command
* WIP: Add joins, handling less metrics
* join events table to sessions if needed
* Merge imported results with built query
* Remove dead code
* WIP: /api/v2/query
* Allow grouping by time
* Use JOIN for main query
* Build query result
* update parse_time
* Make joinless order by work
* First test
* more breakdown tests
* Serialize event:goal filters in an json-encodable way/reflection
* Handle inner vs outer ORDER BY clauses properly
* Handle single conversion_rate metric
* Update more tests
* Get parsing tests passing again
* Validate filtered goal filter is configured
* Enable more validation tests
* Enable more event:name breakdown tests
* Enable more breakdown tests
* Validate site has access to custom props
* Validate conversion_rate metric which is only allowed in some situations
* Validate that empty event:props: is not valid
* handle query.dimensions properly in table_decider
* test more validations on metrics/dimensions
* Validate session metrics in combination with event dimension(s)
* Tests cleanup
* Parse include.imports
* Get imports working with new querying
* Make more imports tests work
* Make event:props:path imports-adjacent test work
* Get query imports warning-related tests running
* Remove dead pagination tests
* Solve dead import
* Solve some warnings
* Update aggregate metrics tests
* credo
* Improve test naming
* Lazy goal loading
* Use datetime methods
* Ecto -> SQL module name
* Remove Expression.dimension mode option
* Make goals accept wildcards in :is queries
* Add support for contains/does_not_contains in the backend
* Support all operations for event custom properties
* Support does_not_contain on the frontend
* Changelog entry
* Render filter operations nicely for does not contain
Found 3 extra pixels for operation dropdown
* Remove multiple_filters feature flag
* Set default selected tab to last cycle when rendering usage
...And never disable this tab.
* rename Ongoing cycle to Upcoming cycle
* fix tests
* mix format
* Implement autoprefill of enterprise plan fields on user change
* Implement sanitizing input attrs in enterprise plan CRM form
* Implement number formatting for monthly pageview limit input in CRM form
* Link subscription status to Paddle profile whenever available
* Display usage info directly in user form in CRM
* Handle pageview limit fallback gracefully when rendering subscription quota
* Remove usage page link from users list view in CRM
* Add tests for usage page
* Apply `raw/1` only to the one (and only) element of the list
* pull last_bill_date from paddle sandbox in mix task
* move cycle usage checks to Quota module
* move quota.ex to a subfolder
* split up Quota module
* set choose-plan pageview slider according to usage
* silence credo
* Start suggesting event names in goal settings form
* Fix tests
* Bump phoenix_live_view to 0.20.12
* Implement a criminal hack to track removal of modal's child live components
* Revert "Implement a criminal hack to track removal of modal's child live components"
This reverts commit f34ceb78f1.
* Remove redundant closing brace from currency combo input
* Hide batch goal add button when tab selection is in progress
* Implement unique modal ID regenerated on every modal close/open cycle
* Use unique modal ID as ID suffix to live components in goal settings form
* Reset suffix on tab selection to reset live components state on switch
* Revert "Bump phoenix_live_view to 0.20.12"
This reverts commit 1b1c801981.
* Make unique IDs more predictable
* Fix tests for `GoalSettings.Form`
* Use unique modal ID in country rule modal
* Use unique modal ID in hostname rule modal
* Use unique modal ID in page rule form modal
* Don't limit detected goals when fetching them for autoconfigure
* Escape interpolated Alpine state function argument
* Exclude goals with whitespace on either end or consisting only of whitespace
* Ensure event name suggestions update after goal deletion
* Avoid showing loading spinner when closing modal
* Don't enable spinner when new combobox selection is identical
* Revert "Don't enable spinner when new combobox selection is identical"
This reverts commit a041ba8542.
* Bootstrap OpenAPI Funnel schemas
* Implement Plugins API Funnel view
* Allow casting funnel step directly from `%Goal{}`
* Check feature availability on funnel creation
just like it's done when inserting goals
* Implement Plugins API context module for Funnels
* Implement GET/PUT funnels via Plugins API
* Fix typo
* A rare event in which dialyzer found an actual bug, wow!
* Format
* Wrap creation request with a root `funnel` key
* Format
* Extract common funnel get query
* Remove redundant tag
* Refactor queries a bit