* Update applications
* Clone community config
* Move modules to experimental dir
* Update runtime config
* Apply first set of compile-time conditionals
* Move funnel schemas to experimental
* Make funnel schema-less build compile
* Use experimental/lib for elixir code
* Move JS funnels to experimental
* Clean up conditional rendering
* Tidy up the pipeline
* Make two builds pass tests without warnings
* Reuse existing dotenvs
* Do a bunch of renames
* Clean up naming
* Run secondary CI
* Update router
* Remove RewriteFunnelDupes migration
Tests were disabled already and it was a one-off shot
* Fixup quota mixins
* Add moduledoc
* Change MIX_ENV for seconary test run
* Skip crm on small
* !fixup
* Exclude flags pipeline
* Update lib/plausible_web/controllers/stats_controller.ex
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
---------
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* refactor asserting plan generation in plans_test.exs
* stop grandfathering old expired trials
For users who registered before the business tiers release, we want to
offer a chance to subscribe to a grandfathered plan. However, if they
let their trial expire and don't subscribe in the next 10 days, they'll
lose that opportunity.
* stop grandfathering expired subscriptions
* remove default title and icon from Generic.notice
* fix bug with dismissable notice
classList is null when dismissable_id is not given
* alias Plausible.Auth.User
* Refactor Generic.notice component
Make it easy to apply different colors
* move subscription_cancelled_notice across the app
And remove from user settings > subscription box. Also, include a note
about losing grandfathered status when letting the subscription expire.
* allow full width in Generic.notice
* use Generic.notice for subscription_past_due_notice
* use Generic.notice for subscription_paused_notice
* prevent two notices clashing into each other with gap-y-2
* define attrs for phx components
* optimize for light mode
* make subscription cancelled notice dismissable
but if it's dismiss, show it in the place where it was before in the
account settings > subscription box
* make function private
* replace function doc with regular comment to avoid compile warning
* use array for classnames
Co-authored-by: Vinicius Brasil <vini@hey.com>
* fix typos in function doc
---------
Co-authored-by: Vinicius Brasil <vini@hey.com>
* use windows in 'time on page' query
* add imported time on page back
* join imported_pages instead of extra query
* don't forget aggregated time on page!
* eh?
* no need for separate window clause
* use dynamic_filter_condition in aggregate_time_on_page
* it's avg, not total
* fix dynamic_filter_condition call
* tests pass
* fewer changes
* fewer changes + feature flag
* base quickfix
* fewer changes
* fewer changes?
* fewer changes!
* replace coalesce with if(empty(),etc)
* make window_aggregate_time_on_page return same result as neighbor_
* breakdown as well
* add failing test
* more info
* more info
* format example
* add failing aggregate.ex test
* fix breakdown.ex windowing time_on_page calculation
* fix aggregate.ex windowing time_on_page calculation
* Revert "Remove site pins for now"
This reverts commit 5eccf4eaf6.
* Implement basic site pin schema level logic within user specific preferences
* Add vertical ellipsis menu markup
* Implement basic changesets for user preferences
* Implement pin toggling
* Try to fix pin sorting
* Implement pin toggling in LV
* Adjust moduledocs for new schema(s)
* Remove unnecessary `distinct` from query
* Use `button` for pin/unpin action
* Generalize preference setting
* Rename schema and fields for clarity
* Rename `list_type` -> `entry_type`
* Safeguard setting options
* Test `set_option/4` and `toggle_pin/2`
* Add test for listing pinned sites via `Sites.list`
* Disallow pinning sites outside page explicitly
* Test pinning in LV
* Test conditional rendering of site settings in /sites
* Remove unnecessary TODO comment
* Safeguard `Sites.set_option/4` against invalid user/site combo
* Handle pinned sites in dashboard site picker
* Clear flashes upon (un)pinning sites
* Update CHANGELOG
* Prevent blinking of hamburger menu items on first paint
* Highlight hamburger handle on hover in /sites
* Start showing hotkeys in site picker again
* Sort pinned sites in the order they were pinned
* Update sites list order immediately after pin/unpin toggle
* Refactor and split `Sites.list/3`, extracting `Sites.list_with_invitations/3`
* Cap number of pinned sites at 9 per user
* First pass on visual indication of site cards (dis)appearing
* Apply ellipsis gradient+shadow on card hover
* Fix responsive padding of site cards
* Sort by invitations first, pinned sites second and then the rest
* Revert "Apply ellipsis gradient+shadow on card hover"
This reverts commit 0608796612639030ccbb12df639709f78edc1434.
* Apply more subtle hover effect on the ellipsis menu
* Make error and success flash LV boxes use separate component containers
* Promote `pinned_at` in table migration to a column
* Switch logic to using `pinned_at` as a standard schema field
* Refactor `Sites.list*` getting rid of subquery (h/t @ukutaht)
* Remove migration which is already merged upstream
---------
Co-authored-by: Adam Rutkowski <hq@mtod.org>
* fix underlined blank space in upgrade link
* Add :if clause to site limit notice
* Change test description
* Move growth? and trial? conditionals to CTA function
* Improve wording in billing notices
---------
Co-authored-by: Vinicius Brasil <vini@hey.com>
* Fix private preview notice typo
* fix link to choose-plan instead of upgrade
* do not display premium feature notice if legacy feature access
* register trial message
* change enterprise contact us copy
* fix test
---------
Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
* price formatting
* fix space underlined
* add a redirect from :upgrade to :choose_plan
* Add premium feature notice to revenue goals
* add the number of API request to plan benefits
* be more explicit about Stats API requests
* start linking to the new upgrade page if FF enabled
* add redirect to :upgrade_to_enterprise_plan from :choose_plan
This commit intends to keep the existing behaviour of redirecting users
directly to the enterprise upgrade page when they click on an upgrade
link in an email and have an enterprise plan configured.
Hence, we can also simplify the /settings template and only link to
'/billing/choose-plan', even for enterprise plans.
* deprecate /billing/change-plan route based on FF
* Move new site template to HEEX
* Move new team member invitation template to HEEX
* Standardize exceeded limits error message
* Fix failing tests
* Limit Stats API access to unlimited trials
---------
Co-authored-by: Vinicius Brasil <vini@hey.com>
* Change limits for trials
* Keep legacy trial limits for users that registered before the business tier
* Change private preview notice for release
* Run formatter
* Add countdown to private preview notice
* allow using Stats API and Props for free_10k subscriptions
* return v3 plans for legacy trials
* do not display grandfathering notice for legacy trials
* set a more accurate BT release date
* fix bug on dev env
Allow the `find/1` function to find sandbox plans
* add error handling and tests for change_plan_preview
* fix feature warning bug
* fix credo warnings
* fix tests
* set BT release date further into the future
* rename function and some vars
* bugfix with limit exceeding
* fix test
* Show loading state for mini plots
* Dark mode
* Don't render no change in green
* Fix loading placeholders for mobile/desktop view
* Fixup test
* Make loading state background color for light theme one step brighter
---------
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Implement complete basics of LV sites
* Reimplement everything in LV except pagination
* Implement basic search capability
* PoC: plot visitors on sites index
* Add rudimentary clipped gradient in minicharts
* Fix clipping gradient, define once
* Format
* Add moduledoc to visitors component
* Move paginator helpers to the top core namespace
* Fix typespec of `Plausible.Sites.list`
* Split sites component into subcomponents
* Add function to uniformly calculate 24h intervals
and visitor totals across multiple sites.
* Integrate batch 24h interval query with plots on sites view
* Don't confuse heex compiler with alpine @ shorthands
* Make linear gradient svg definition truly invisible
* Implement basic pagination
* Extract `site_stats` from site and invitation cards
* Improve pagination
* Tweak css
* Improve filtering on pagination and make WSS fail graceful
* Test `last_24h_visitors_hourly_intervals/2`
* Replace /sites with LV implementation
* Add debounce to search filter
* Fix typespecs
* Fix styling
* Fix mini graph scaling factor calculation
* Fix search consuming itself
* Minimal tweaks to the plots
* Fixup
* Remove magic numbers from the plot
* Create `site_pins` table
* Add `SitePin` schema
* Implement listing invitations, sites and pins in a single query
* Add FIXME note
* Remove site pins for now
* Add tests for `Plausible.Sites.list/3`
* Add a couple more tests to sites dead view
* Remove unnecessary FIXME
* Add LV tests for Sites
* Calculate and display 24h visitors change
* Render the change in bold
* Add clarfying comment on virtual field in `Site` schema
* Remove unnecessary function from Invitations API
* Remove unused list opt from type definition in `Sites`
* Improve joins in list query slightly
* Add comment on manually computing sites list total
* Start searching from a singly character in domain field
* Add typespec to `last_24h_visitors_hourly_intervals`
* Extend moduledoc in visitors component
* Simplify loading sites in LV
* Simplify assigns in LV
* Add missing group for shadow under site card
* Make invitation modal render
* Make HTML in sites LV semantically correct
* Remove autofocus and focus search on `/`
* Remove shadow from search input
* Make search cancel on escape
* Fix tests relying on outdated HTML structure
* Make visitor chart color scheme consistent with dashboard chart
* Update styling of trend labels
* Fix empty state and improve search blur/focus handling
* Use live navigation for pagination
* Implement spinner on load from search
* Remove unused `Plausible.Stats.Clickhouse.last_24h_visitors/1`
* Calculate uniques correctly across hour boundaries
* Swap inlined svg for Heroicons component in invitation modal
* Add order by to base query in 24h hourly intervals
* Revert "Add order by to base query in 24h hourly intervals"
This reverts commit a6be5e3026.
* Query clickhouse 24h visitors only on second mount
* Remove redundant sign from percentage change when negative
* Switch to offset-based pagination
- offset seems easier to deal with for when actions on
paginated list will be performed such as site pinning;
tracking cursor data makes some entries disappear in
edge cases. The data set is still fairly small and
static, even for large customers.
- we're removing Phoenix.Pagination as it doesn't really
fir any use case, and it was only used to limit the number
of sites in the site picker
- site picker is now limited to 9 sites (future: pinned
sites will be prioritized there)
- no need to re-query for total count any more
- BTW, the old /sites template was removed
* Refine the plot queries; Tests pass snapshot
* Add PromEx plugin for LiveView
* Fix tiny plot cut-off at the top
---------
Co-authored-by: Adam Rutkowski <hq@mtod.org>
* fix the styling of the red text notice under checkout link
* avoid some code repetition
* simplify rendering the change_plan_link
* refactor disabling checkout link and showing disabled message
* disable change plan and upgrade link when exceeding pageview limit
* disable checkout when exceeding team member limit
* disable checkout when site limit exceeded
* extract checkout related code in a separate function
* stick to a single order of features
* losing features warning
* fix back link from change-plan-preview
* create Quota.exceeded_limits function
* restrict subscribing with exceeded limits on the API level too
* use with instead of case
Co-authored-by: Vini Brasil <vini@hey.com>
* use :map type instead of :any for user
Co-authored-by: Vini Brasil <vini@hey.com>
* create Quota.usage function
---------
Co-authored-by: Vini Brasil <vini@hey.com>
* Bump deps
* Bump stack
* Fix deprecation warnings
* Fix VCR cassettes mismatch due to OTP-18414
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Format & fix flaky tests
* Handle raw IPv4 hostnames; test public suffix TLD
* Configure locus db cache_dir
So that maxmind unavailability doesn't affect
application startup. PERSISTENT_CACHE_DIR env var is used
to point locus at the GeoIP DB file.
* WIP: Remove ExVCR
* Fix test env config
* Fixup exvcr
* Remove exvcr from deps
* Add convert script
* Remove exvcr cassettes
* Remove convert script
* Rename test
* Update moduledoc
* Update dockerfile
* Bump CI cache
* Tag more slow tests, why not?
* Use charlist for locus cache option
* Pin nodejs
* Merge google tests, make them async
---------
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Read feature status from Billing.Feature instead of %Site{}
This commit changes data attributes passed to React. Previously the
controller read feature statuses directly from the %Site{} schema. The
Billing.Feature context is aware of the user plan and the features
available.
* Limit funnels internal API based on site owner plan
* Limit props internal API based on site owner plan
* Use site factory in QueryTest
* Limit custom property filter based on site owner plan
* Limit revenue goals queries based on site owner plan
* Add SSO link with signed JWT token
* Falls back to Nolt URL without SSO if token cannot be generated
* Add profile image (gravatar) to Nolt SSO link
* Improve navbar dropdown
* Add 'contact support' link to nav dropdown
* Add CSS rule to prevent horizontal jumps
* Dark mode styling
* Close dropdown when link is clicked
* Clarify links in dropdown
* Clarify CSS comment
* Use Alpine.data() over window
* Rename suggestions_dropdown -> combo-box
* Mix format
* Make logout link look good on dark mode
* Use proxy for gravatar
* Do not use Gravatar proxy in self-hosted
* Changelog
* Add Github Repo link to nav dropdown
* Make dialyzer happy
* Add proxy for Gravatar
* Update assets/css/app.css
Co-authored-by: hq1 <hq@mtod.org>
* Update lib/plausible_web/controllers/avatar_controller.ex
Co-authored-by: hq1 <hq@mtod.org>
* Fix alpine <> Liveview integration
---------
Co-authored-by: hq1 <hq@mtod.org>
* Refactor email verification codes generation to avoid predictability
* Improve `Site.Memberships.any?` slightly
* Update tests
* Fix seeds
* Use `expired?` predicate for checking verification code validity in tests
* Store verification code as string in database to avoid unnecessary int casting
* Include ApiKey functions in Auth context
* Make feature notice work without %Site{}
Previously the extra feature notice required a %Site{} in order to check
the owner plan. However, not every feature is scoped by site, for
example the Stats API. For features like this, a %User{} is required,
and not a %Site{}.
This commit replaces the `:site` param with `:billable_user`, which is
common to both site and user-scoped features.
* Add stats_api to the list of extra features
* Limit API Key creation based on user plan
This pull request implements limits to funnels, revenue goals and custom props based on the site owner plan. It extends the current "premium feature" notice to account for the new plans, trials and the on-going private preview. Stats API is not in the context of this pull request, but will be implemented likewise.
* Implement PoC for email reverification flow on update
* Improve user settings form and email change validation
* Expose `previous_email` in Kaffy CRM
* Improve plugs setup and remove dead action from AuthController
* Fix seeds
* Extract predicate query functions from AuthController
* Add tests
* Update CHANGELOG.md
* Rename `has_any_sites?` to `Memberships.any?` and `has_any_memberships?`
* Improve flash message on cancelling email change
* Cover one more test case for email update
* rename enterprise?/1 function
* change link text to Upgrade when subscription deleted
* extract paddle_button and paddle_script components
* create a new upgrade-to-enterprise-plan page
* extract upgrade_link component
* rename function
* link to enterprise plan upgrade page from settings
...if the user has an enterprise plan configured
* fetch enterprise plan price on the new page
* add change_enterprise_plan functionality on the new page
* render existing change_enterprise_plan_contact_us.html
...when subscribed to latest configured enterprise plan
* rename vars and extract resumable? fn
* remove dead billing route
* small test refactor: extract convenience fn
* add tests for...
...restricting paused and past_due subscription access to the new
enterprise plan page.
1. redirect to /settings from the controller action
2. hiding the change-plan link from the user settings
* implement redirect to /settings
* hide the enterprise upgrade/change-plan link
* add tests for a deleted enterprise subscription
* plug in the new controller action and delete dead code
* optimize for dark mode
* fix compile warning
* credo fix
* display N/A instead of crash when price nil
* change subscription.status type to Ecto.Enum
Also, create a new `Subscription.Status` module that exposes macros to
return the used atom values (prevent typos at compiletime).
* fix bug (@conn not available anymore)
* use Routes.billing_path where applicable
* add a status() type
* silence credo
* refactor suggestion from review
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Remove the __using__ macro from Subscription.Status
... instead be explicit about requires and aliases and also order
the use, import, require, and alias clauses according to
https://github.com/christopheradams/elixir_style_guide#module-attribute-ordering
* drop the virtual Enteprise 'price_per_interval' field
* apply review suggestion to make the code more DRY
* use dot syntax to fetch current user in new controller actions
* fix formatting
---------
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
This change addresses two problems:
* controller action crashing missing "token" param - it's handled gracefully
now and will not pollute Sentry anymore with http://sentry.plausible.io/organizations/sentry/issues/4319
* LiveView receives email extracted from token on initial page load instead
of reverifying token on every re-mount (which can happen when somebody
leaves form open for an extended period of time; rare but happens and
needlessly pollutes Sentry as well)
* Make membership creation and role updates more explicit in terms of changesets
* Extract invitation accept flow logic and refactor it slightly
* Improve acceptation logic
* Update moduledoc
* Improve SiteLocker API and add typespecs
* Stop naming function not returning a boolean like a predicate
* Refactor rest of invitation actions and safeguard against rogue requests
* Update code docs slightly
* Extend `Billing.check_needs_update/1` tests
* Parametrize selfhost flag and toggle SiteLocker logic on it
* Add tests for newly extracted services
* Add test case and a fix for locking site on grace period ended
* Make invitation controller tests async as there's no more env patching
* Add test cases for self-invites and fix one bug
* Add and refactor tests for rejecting and removing invitations
* Prevent issuing ownership transfer to existing owner
* Improve name of the test
* Improve `Billing.check_needs_to_upgrade/1` return value
* Improve `Billing.SiteLocker.update_sites_for/1` and its tests
* Fix typos
Co-authored-by: hq1 <hq@mtod.org>
* Make invitation removal and rejection resilient to races
---------
Co-authored-by: hq1 <hq@mtod.org>
* Add zxcvbn dependency
* Change password length range requirement from 6-64 to 12-128
* Reimplement register form in LV
* Implement server-side check for password strength
* Add rudimentary strength meter
* Make password input with strength a separate component and improve it
* Fix existing tests to provide strong enough password
* Apply formatting
* Replace existing registration form with new one
* Hide built-in label in `.input` component when none provided
* Crop password to first 32 chars for analysis by zxcvbn
* Add tests for new form components
* Integrate hCaptcha into LV
* Fix existing AuthController tests
* Add tests for Live.RegisterForm
* Hide strength meter when password input is empty
* Randomize client IP in headers during tests to avoid hitting rate limit
* Apply auxilliary formatting fixes to AuthController
* Integrate registration from invitation into LV registration logic
* Fix existing password set and reset forms
* Make `password_length_hint` component more customizable
* Optimize `Auth.User.set_password/2`
* Remove unnecessary attribute from registration form
* Move password set and reset forms to LV
* Add tests for SetPasswordForm LV component
* Add tests for password checks in `Auth.User`
* Document code a bit
* Implement simpler approach to hCaptcha integration
* Update CHANGELOG.md
* Improve consistency of color scheme
* Introduce debounce across all text inputs in registration and password forms
* Fix email input background in register form
* Ensure only single error is rendered for empty password confirmation case
* Remove `/password` form entirely in favor of preferred password reset
* Remove unnecessary `router` option from `live_render` calls
* Make expensive assigns in LV with `assign_new` (h/t @aerosol)
* Accept passwords longer than 32 bytes uniformly as very strong
* Avoid displaying blank error side by side with weak password error
* Make register actions handle errors gracefully
* Render only a single piece of feedback to reduce noise
* Make register and password reset forms pw manager friendly (h/t @cnkk)
* Move registration forms to live routes
* Delete no longer used deadviews
* Adjust registration form in accordance to changes in #3290
* Reintroduce dogfood page path for invitation form from #3290
* Use alternative approach to submitting plausible metrics from LV form
* Rename metrics events and extend tests to account for them
* Filter out empty entries when listing stats for UTM props
* Update test fixtures removing noref entries in UTM CSV stat exports
* Update external API tests to account for lack of noref records for UTM stats
* Filter out entries with empty UTM props from imported GA stats
* Remove unreachable GA utm_source dim clause in imported stats logic
* Refactor MembershipController.invite_member/2
This commit refactors the controller action used for creating new
invitations. It moves the code to Plausible.Sites.invite/4 and replaces
`ifs` and `cases` with `with`.
* Add team_member_limit to plan definition
* Create usage and limits functions for team members
* Apply team member limit when inviting new users
* Add team members to Usage & Limits section
* Change invite function to receive email address instead of %User{}
* Wrap invite function in a DB transaction
* Remove unnecessary joins from team member usage query
* Replace UNION ALL with UNION to remove duplicates
* Add Heroicons dependency
* Add name_of/1 html helper
Currently with Floki there's no way to query for
`[name=foo[some]]` selector
* Update changelog
* Make goal deletion possible with only goal id
* Remove stale goal controllers
* Improve ComboBox component
- make sure the list options are always of the parent input width
- allow passing a suggestion function instead of a module
* Stale fixup
* Update routes
* Use the new goals route in funnel settings
* Use a function in the funnel combo
* Use function in the props combo
* Remove old goals form
* Implement new goal settings
* Update moduledoc
* Fix revenue switch in dark mode
* Connect live socket on goal settings page
* Fixup
* Use Heroicons.trash icon
* Tweak goals search input
* Remove unused alias
* Fix search/button alignment
* Fix backspace icon alignment
* Delegate :superadmin check to get_for_user/3
I'll do props settings separately, it's work in progress
in a branch on top of this one already. cc @ukutaht
* Rename socket assigns
* Fixup to 5c9f58e
* Fixup
* Render ComboBox suggestions asynchronously
This commit:
- prevents redundant work by checking the socket connection
- allows passing no options to the ComboBox component,
so that when combined with the `async` option, the options
are asynchronously initialized post-render
- allows updating the suggestions asynchronously with the
`async` option set to `true` - helpful in case of DB
queries used for suggestions
* Update tests
* Throttle comboboxes
* Update tests
* Dim the search input
* Use debounce=200 in ComboBox component
* Move creatable option to the top
* Ensure there's always a leading slash for goals
* Test pageview goals with leading / missing
* Make the modal scrollable on small viewports
This pull request introduces a series of improvements to Plausible.Billing.Plans, including:
* Tag the JSON file with the plan version
* Rename the JSON field limit to monthly_pageview_limit
* Move site_limit function to Billing.Plans
* Refactor subscription_interval, allowance and site_limit functions
* Remove unused AnalyzePlans task
* Remove `Plausible.Sites.set_allowed_event_props/2` function
This commit removes the `Plausible.Sites.set_allowed_event_props/2`
function in favor of `Plausible.Props.allow/2`.
* Allow internal prop keys in queries
This commit allows internal prop keys by default in queries. I decided
not to include internal keys in the database, because they might change
and we'd need to migrate it again.
* remove redundant 'props.' from behaviours/index.js
---------
Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
* extract add_exit_rate function
* Change internal API metric names for /entry-pages & /exit-pages
* `unique_entrances` -> `visitors`,
* `total_entrances` -> `visits`,
* `unique_exits` -> `visitors`,
* `total_exits` -> `visits`,
This is just a consistency improvement - the `visitors` metric always means
one thing and there's no need to call it different for entry pages internally.
This commit does not change any noticable behavior. The UI labels are kept
the same and the column headers in the CSV export will also remain the same.
* Change internal API metric names for /conversions
* `unique_conversions` -> `visitors`,
* `total_conversions` -> `events`,
* return revenue metrics from /custom-prop-values (backend)
* be more explicit about which metric is plotted with Bar
* validate that ListReport input metrics actually exist in the API response
* display revenue metrics in the dashboard Properties section
* limit the number of columns shown on mobile
* add revenue metrics to Properties > Details
* review suggestions
* define hiddenOnMobile per metric instead of keeping the first 3
* rewrite if-else block
---------
Co-authored-by: Vini Brasil <vini@hey.com>
* extract add_exit_rate function
* Change internal API metric names for /entry-pages & /exit-pages
* `unique_entrances` -> `visitors`,
* `total_entrances` -> `visits`,
* `unique_exits` -> `visitors`,
* `total_exits` -> `visits`,
This is just a consistency improvement - the `visitors` metric always means
one thing and there's no need to call it different for entry pages internally.
This commit does not change any noticable behavior. The UI labels are kept
the same and the column headers in the CSV export will also remain the same.
* Change internal API metric names for /conversions
* `unique_conversions` -> `visitors`,
* `total_conversions` -> `events`,
* make (none) value in custom prop breakdown add +1 to pagination limit
This is needed because the (none) value is always added to the
breakdown_results **after** fetching those from ClickHouse.
* only include (none) values on the first page of results
* fix percentage metric calculation for paginated results
Instead of summing up the number of visitors from the breakdown results
to get the total, we have to make a separate query to `Stats.aggregate`.
Otherwise, the percentages for each results page will wrongly add up to 100%.
Since imported data for aggregated visitors and other properties (such as
browsers, OSs, etc) live in different tables, we have to tweak the tests to
also include the same number of visitors in the `imported_visitors` table.
* add details view for props
* changelog
* exclude imported data from total
* move set_allowed_event_props into context module
* extract parse_csv fn
* add custom_props.csv to CSV export (under FF)
* add test for custom prop export with a prop filter
* add test for goal filtered scenario
* mix format
* fix flaky test
* extract breakdown_custom_prop_values function
* Revert "fix flaky test"
This reverts commit 256b9bb2e7. The flaky
test was already fixed in 86557b1878
* make set_allowed_event_props a bang function
* test that all files are included in the CSV export
* refactor SourceList to use ListReport
* refactor SourceList into a fn comp
* change referrer-drilldown API response format and remove dead code
* use ListReport in referrer-list
* fix CI
* fix flaky test
* remove IO.inspect
* copy prop_breakdown tests into a separate file
* add a new endpoint for custom props
Duplicate existing goal prop breakdown as a building base for the
new endpoint
* stick to original metric names + CR definitions
We currently use CR with two different definitions, which is inconsistent
and should be changed. This commit just documents the difference for the
time being.
* basic prop breakdown without goal filter
* increase % metric precision to one decimal place
* add some tests without goal filter
* silence credo for TODO comment
* use events metric instead of pageviews
* review feedback
* inline add_cr_a instead
* Move money cast function to Stats.Util
* Add revenue metrics to main graph API
* Plot revenue metrics on the main graph
* Return plain numbers instead of a map
* Fix Credo issues
* Fix canMetricBeGraphed function
* Revert canMetricBeGraphed function changes
* Add noindex,nofollow to dashboard pages
* Implement NoRobots plug
* Enable NoRobots plug in the router
* Fixup internal route
* Fix double slash in the router
* Add special bot treatment to plausible.io live demo page
* Revert aggressive protection with agent detection
* PoC: evaluate funnel on step selection
* Adjust test to actually _select_ steps
* Throttle and test ephemeral funnel evaluation
* Format compact percentages server-side
At this point it's pointless to duplicate this;
all the primitives exist in the API in case the client
wants a different representation.
* Add Funnel react component
assets/js/dashboard/stats/behaviours/funnel.js - restored from:
98a76cbd Remove console.info calls
d94db99d Convert Funnel class component into a functional one
028036ad Review comments
3067a940 Stop doing maths in react
73407cc3 Fix error handling when local storage gets corrupted
e8c6fc52 Format numbers on funnel labels
c815709f Reorganize component responsibility
7a88fe44 Outline basic error handling
94caed7c Chart styling updates
4514608a Add percentages to funnel
d622c32d Add funnel picker
Co-authored-by: Uku Taht <uku.taht@gmail.com>
* Pass funnels list to react via data-funnels
* Implement Funnels react API
lib/plausible_web/controllers/api/stats_controller.ex - restored from:
f36ad234 Adjust to Plausible.Stats interface
9b532273 Test funnel stats controller
028036ad Review comments
bea3725f Remove IO.inspect
7a88fe44 Outline basic error handling
c8ae3eaf Move Funnels to StatsController and use base query
667cf222 Put private functions at the bottom
* Tweak funnel presentation
* Handle errors at the top
* Do not register DataLabels plugin globally
or else all the existing charts are affected
* Calculate drop-off percentage evaluating funnels
* Tweak dark mode + implement nicer tooltips
* Make currently selected funnel bold in the picker
* Count user_ids not session_ids when evaluating funnels
So if a visitor goes:
1. Start session
2. Complete funnel step 1
3. Inactive for 30 minutes
4. Complete funnel step 2
We would not be able to track this funnel completion because of the session timeout.
We like to o measure this as funnel completion even though the session expired in the middle.
cc @ukutaht
* Add extra properties to the funnels API
cc @ukutaht
* Improve tooltips so that step to data is rendered
* Change tooltip number formatting
* Remove debugging remnants
* Quick & dirty mobile view
* Fix mobile view: tweak dark mode & funnel switching
* Ignore DOMException: the operation was aborted
Otherwise this sometimes flashes the space shuttle
screen when navigating quickly via a keyboard.
* Format percentages on the main chart
* Close missing tag 🙈
* Revert "Close missing tag 🙈"
This reverts commit 9c2f970e22fd7e2980503242b414f42ce8bce1d2.
* Use jsx to render funnel tooltip
To get markup validated via lsp mostly...
* Fixup: s/class/className
* Fix className interpolation
* Add a ruler to the tooltip
* Tweak funnel chart style
* Fix font distortion issue on chart/canvas labels
* s/class/className
* Put "Set up funnels" link behind a feature flag
* Refactor internal selection storage
Getting ready for live funnel evaluation
* Don't try to connect LV socket if there's no CRSF token set up
This is perfectly okay for some of the templates/layouts.
* Fix up funnel creation typespecs
Unfortunately we can't define a type with literal string keys,
hence this must suffice.
* Use uniq over count/distinct
* Revert JSX in tooltips
Ref: https://github.com/plausible/analytics/pull/3066#discussion_r1241891155
* Remove the extra query for counting all visitors
cc @ukutaht
* Add premium notice
---------
Co-authored-by: Uku Taht <uku.taht@gmail.com>
This commit adds revenue data to top stats. Average and total are displayed when filtering by a revenue goal (or many if they have the same currency set).
* Update formatter config
* Install LiveView JS integration & hooks
* Temporarily update endpoint/session config
* Optionally allow preloading funnels for goals
* Site controller
* Implement funnel settings
lib/plausible_web/live/funnel_settings/combo_box.ex - restored from:
054de6e2 Fix the tab/blur bug again
20da4c89 Rename InputPicker to ComboBox
lib/plausible_web/live/funnel_settings/form.ex - restored from:
9bedda3b Remove potential FIXME
20da4c89 Rename InputPicker to ComboBox
028036ad Review comments
aea4ebc4 Access Funnel min/max steps via the __using__/1 macro
0dde27fd Remove inspect call
eed588a7 Start testing the funnel editor
0e95228b Extract funnel settings test module
7b16ace5 Leverage aplinejs to deal with the tyranny
8dc6a3e7 wip
cf228630 wip
30a43fd1 wip
89f10ecb wip
950a18d9 Dirty funnel save
298a6a53 wip
7690d50f wip
639c6238 fixup
aa59adeb wip
ff75c00b wip
lib/plausible_web/live/funnel_settings/list.ex - restored from:
4eae122c Fix data-confirm attr interpolation
51f0397d Implement deleting funnels
1f6fe25d Add number of steps to funnels list
298a6a53 wip
ff75c00b wip
test/plausible_web/live/funnel_settings/funnel_settings/combo_box_test.exs - restored from:
20da4c89 Rename InputPicker to ComboBox
test/plausible_web/live/funnel_settings/funnel_settings_test.exs - restored from:
34822ff4 Bootstrap InputPicker tests
lib/plausible_web/live/funnel_settings.ex - restored from:
028036ad Review comments
acd9c4f2 Prepare ephemeral funnel definitions so that users can test funnels
51f0397d Implement deleting funnels
0e95228b Extract funnel settings test module
8dc6a3e7 wip
89f10ecb wip
950a18d9 Dirty funnel save
298a6a53 wip
aa59adeb wip
ff75c00b wip
test/plausible_web/controllers/error_report_controller_test.exs - restored from:
34822ff4 Bootstrap InputPicker tests
test/support/html.ex - restored from:
0a53979d Improve InputPicker tests - include AlpineJS assertions
34822ff4 Bootstrap InputPicker tests
lib/plausible_web/views/layout_view.ex - restored from:
b490403b !ifxup
lib/plausible_web/templates/site/settings_funnels.html.eex - restored from:
51f0397d Implement deleting funnels
ea1315f3 Test funnels list in settings
7b16ace5 Leverage aplinejs to deal with the tyranny
ff75c00b wip
4da25c35 Fixup
lib/plausible_web/templates/layout/app.html.eex - restored from:
ff75c00b wip
* Add funnel settings route
* Warn about funnels deletion when deleting goals
lib/plausible_web/templates/site/settings_goals.html.eex - restored from:
fdd9bcd0 Fixup
f1e6364d Merge remote-tracking branch 'origin/master' into funnels-rebase
9d0b7c6d Fix markup error
4a4ddbdc Optionally preload funnels for goals and stub funnel-goal deletion
ebdc4333 Extend the prompt in case of funnel-goal deletion
639c6238 fixup
aa59adeb wip
* Split new JS LiveView additions
* Put funnels behind a feature flag
* Integrate dashboard feature toggle
* Update signing salt for live view
* Update moduledocs
* Update live reloader config
* Use Phoenix.HTML.Safe for goal names
* Workaround to get flashes working in embedded liveview
* Keep feature toggles idempotent, rename property to setting
We'll still retain the ability to flip bools on a lower level.
* Update moduledocs
* Make live flash disappear after 5s
* Tailwind: purge .heex files too
* Update docs link
* Add live components to tailwind purge config
* Update another flaky test
Ref f0bdf872
cc @vinibrsl
* Fix combobox input length w/ WebKit
* Intoduce generic notice component
* Revert "Fix combobox input length w/ WebKit"
This reverts commit 3c653a6d85d5000167631e10ef45a93c13b41ed1.
* Fix combobox input length on webkit
* Make whole combobox item clickable, not only text
* Fix glitch moving Save button on activation
* Tweak dark mode
* Show funnel form without waiting for funnel name input
* Tweak dark mode
* Include static Phoenix components in tailwind purge
* Tune funnels form into a liveview of its own
This is so that ComboBoxes can publish their selections
and unavailable choices can be propagated to other siblings.
* Push less data over websocket
* Undo Lsp/formatter race condition
* Fixup typespecs
* Bust CI cache
This commit fixes a bug where performing a breakdown by goal with
revenue metrics would return data for both event goals and pageview
goals. However, revenue data is only applicable for event goals as they
hold currency data.
To fix the bug, this commit removes revenue metrics from the pageview
breakdown query.
This commit fixes a bug where timeseries queries - such as the main
graph - would fail with imported data in realtime mode. Realtime mode
`date` field is not actually a date, but minutes from now. This would
cause the imported tables join to fail with this error:
```
(Ch.Error Code: 53. DB::Exception: Can't infer common type for joined
columns: date: Int64 at left, s1.date: Date at right. There is no
supertype for types Int64, Date because some of them are
Date/Date32/DateTime/DateTime64 and some of them are not.
(TYPE_MISMATCH)
```
This commit removes imported data from realtime queries, as it doesn't
make sense to include it. Imported data does not have time precision,
and would only appear in the first day the data was imported anyways.
* copy relevant files from b2ace16540
* make it work and set site.funnels to empty list
* make Behaviours a functional component
* add UI for a setup hint and always display conversions by default
* cherry-pick migration commit
* update site schema with new fields
* backend: implement disable-feature action
* switch between tabs in the behaviors section
Introduces template components to build props and funnels on. Both
only show a setup notice atm, and both are behind feature flags.
* extend API for disabling props and funnels
* render feature setup note directly from the Behaviours component
* fix UI behavior when features are hidden
* update setup notices
* add conversions feature switch to Site Settings > Goals
* mix format
* remove IO.inspect
* change setup notice - use buttons + popup confirmation
* optimize for light mode
* restrict access to setup notices
* some styling improvements
* allow super-admins to enable/disable features
* only show conversions (last 30min) in realtime mode
* use shorter display names for tabs
* optimize for mobile screens
* note about sending custom events
* changelog update + fix CI
* change HTTP verb for the disable-feature action
* change UI label for show/hide goals
* Add revenue fields to ClickHouse events
This commit adds 4 fields to the ClickHouse events_v2 table:
* `revenue_source_amount` and `revenue_source_currency` store revenue in
the original currency sent during ingestion
* `revenue_reporting_amount` and `revenue_reporting_currency` store
revenue in a common currency to perform calculations, and this
currency is defined by the user when setting up the goal
The type of amount fields is `Nullable(Decimal64(3))`. That covers all
fiat currencies and allows us to store huge amounts. Even though
ClickHouse does not suggest using `Nullable`, this is a good use case,
because otherwise additional work would have to be done to
differentiate missing values from real zeroes.
I ran a benchmark with the data pattern we expect in production, where
we have more missing values than real decimals. I created 100 million
records where 90% of decimals are missing. The difference between the
tables in storage is just 0.4Mb.
* Add revenue parameter to Events API
This commit adds support for sending revenue data in ingestion using the
`revenue` parameter - aliased to `$`.
* Add revenue parameter to mix send_pageview
* Add average and total revenue to breakdown queries
* Add revenue goal option to goal creation
This commit adds a currency field to the goals form. Goals that have a
currency set are now revenue goals, and are cached with sites to later
be used during ingestion.
Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
* Enable feature flag in tests
---------
Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
* default to source_query.include_imported before true
This fixes a bug where a Stats API aggregate query was trying
to query current period *without imported data* but previous
period *with imported data*.
* remove __internal_visits at a better time
As soon as we have made the db query, we don't need it anymore
* disallow events metric with imported data
* update changelog
* keep default in a better place
* remove unused option
* update test description
Co-authored-by: Vini Brasil <vini@hey.com>
---------
Co-authored-by: Vini Brasil <vini@hey.com>
* add migration
* add not null constraint
* remove not null constraint and default value
* add site schema change
* filter garbage props for prop_key suggestions
* filter garbage props returned by StatsController.conversions/2
* add crm action to set prop allowlist
* use nullable allowed_event_props field instead
* filter garbage props in db query instead
* implement suggestion dealing with string input
* refactor the allowlist condition in db query
* improve test
* upgrade phoenix
Co-authored-by: Vini Brasil <vini@hey.com>
* fix a test (flash message)
The flash message in focus.html.eex was not covered by any test. This
commit fixes also fixes that.
* change function name
* remove unnecessary formatter and format
* update CI cache
* fix dialyzer error
---------
Co-authored-by: Vini Brasil <vini@hey.com>
* Reject invalid country codes early
* Validate all date parameters early
* Ensure request JSON parses to a map
* Re-arrange function calls
* Extend malicious filter validation
* add entry page filter condition to bounce rate
* Fix select_merge with dynamic
* fix tests and add one test
* generalize page_filter_condition function
* use dynamic_filter_condition for session filters too
* disable views_per_visit with a page filter
* update changelog
* disable credo for complex function
---------
Co-authored-by: Uku Taht <uku.taht@gmail.com>
* Add PropFilterModal (only UI)
* small variable refactor
* allow selecting prop value filter type
* allow selecting only one prop_key
* allow selecting many prop_values only when prop_key selected
* handle submitting filter
* get applied filters from query + remove option
* change prop filter label format
* support member and not_member filter types for pageview props
* show (none) value in filter suggestions
* refactor zip_results/4 and remove unused code
* fix displaying (none) values in goals section prop breakdown
* remove unnecessary functionality
* fix bug: returning prop names for goal :member filter
* fix bug: submitting regular filter modal with Enter key
* bugfix: disallow opening prop filter modal when feature flag disabled
* mix format
* break selected combobox values into multiple lines
* fix useEffect behavior for focusing on prop_key field
* support submitting prop filter with Enter key
* refactor getFormState in PropFilterModal
* separate fetchPropKey and fetchPropValue functions
* Allow querying props for pageview goals
* Make the internal props API only return a list of props (not map)
* Separate function for fetching all props in Stats API goal breakdown (this returns a map as before)
* ditch state for keeping search bar visible
* group by event_name in db query
This pull request removes the comparisons feature flag, making it visible to all users. It also removes percentages from top stats in default view, leaving those for the comparison view only.
This commit fixes a bug where comparisons would not work with imported data. This is because comparisons copies the source query and modifies the dates only, where it should reevaluate if there is imported data for the new comparison date range.
Closes#2870
Co-authored-by: Adam <hq@mtod.org>
* Pass comparison_query as argument to top stats functions
* Add comparison values and dates to top stats API
* Display comparison dates and values in top stats
* Rename function to renderPercentageComparison
* Create component to do conditional rendering
* DRY date range formatting function
---------
Co-authored-by: Uku Taht <uku.taht@gmail.com>
* Full migration (to be submitted separately)
* Do not remove `Goal.domain` just yet
* Do not make Goal.site not nullable just yet
* Temporarily disable goal creation
* Rephrase error message
* Add down migration
* Migration (PR: https://github.com/plausible/analytics/pull/2802)
* Implement Site.Domain interface allowing change and expiry
* Fixup seeds so they work with V2_MIGRATION_DONE=1
* Update Sites.Cache so it's capable of multi-keyed lookups
* Implement worker handling domain change expiration
* Implement domain change UI
* Implement transition period for public APIs
* Exclude v2 tests in primary test run
* Update lib/plausible_web/controllers/site_controller.ex
Co-authored-by: Vini Brasil <vini@hey.com>
* Update lib/plausible_web/controllers/site_controller.ex
Co-authored-by: Vini Brasil <vini@hey.com>
* Update moduledoc
* Update changelog
* Remove remnant from previous implementation attempt
* !fixup
* !fixup
* Implement domain change via Sites API
cc @ukutaht
* Update CHANGELOG
* Credo
* !fixup commit missing tests
* Allow continuous domain change within the same site
---------
Co-authored-by: Vini Brasil <vini@hey.com>
* Wrap Plausible.Stats.Filters with unit tests
* Parse `member` filter type
* Support for `member` filter in `aggregate_time_on_page`
* Support `not_member` filter type
* Support `matches_member` and `not_matches_member` filters
* Extract util module for React filters
* Implement Combobox from scratch with no libs
* Support multple filter clauses in combobox
* Don't use browser / os in version label
* Show highlighted option in combobox
* WIP
* Fix location filters outside filter modal
* Align open/close behaviour with react-select
* Styling updates for combobox
* Add support for wildcards in Combobox
* Implement keybindings for combobox
* Allow free choice inputs in combobox
* Rename 'Save filter' -> Apply filter
* Remove TODO comment
* Clean up some rebase mistakes
* Rename `allowWildcard` -> `freeChoice`
* Dark mode fixes
* Remove hint from filter modal
* Escape pipe character in filter modal
* Do not allow selecting duplicate options in combobox
* Escape brackets in `page_regex/1`
* Fix disabled style in dark mode
* Add regex fallback for safari
* Show no matches found when visibleOptions is empty
* Disable enter key when no visible options
* Do not submit empty form fields
* Remove unnecessary setOpen(true)
* Remove ClickhouseSetup module
This has been an implicit point of contact to many
tests. From now on the goal is for each test to maintain
its own, isolated setup so that no accidental clashes
and implicit assumptions are relied upon.
* Implement v2 schema check
An environment variable V2_MIGRATION_DONE acts like
a feature flag, switching plausible from using old events/sessions
schemas to v2 schemas introduced by NumericIDs migration.
* Run both test suites sequentially
While the code for v1 and v2 schemas must be kept still,
we will from now on run tests against both code paths.
Secondary test run will set V2_MIGRATION_DONE=1 variable,
thus making all `Plausible.v2?()` checks return `true'.
* Remove unused function
This is a remnant from the short period when
we would check for existing events before allowing
creating a new site.
* Update test setups/factories with v2 migration check
* Make GateKeeper return site id along with :allow
* Make Billing module check for v2 schema
* Make ingestion aware of v2 schema
* Disable site transfers for when v2 is live
In a separate changeset we will implement simplified
site transfer for when v2 migration is complete.
The new transfer will only rename the site domain in postgres
and keep track of the original site prior to the transfer
so we keep an ingestion grace period until the customers
redeploy their scripting.
* Make Stats base queries aware of v2 schema switch
* Update breakdown with v2 conditionals
* Update pageview local start with v2 check
* Update current visitoris with v2 check
* Update stats controller with v2 checks
* Update external controller with v2 checks
* Update remaining tests with proper fixtures
* Rewrite redundant assignment
* Remove unused alias
* Mute credo, this is not the right time
* Add test_helper prompt
* Fetch priv dir so it works with a release
* Fetch distinct partitions only
* Don't limit inspect output for partitions
* Ensure SQL is printed to IO
* Remove redundant domain fixture