* 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
- `:verification` flag is no longer needed,
however we'll keep the old "awaiting first pageview" flow
for Community Edition where verification is not available
by default
- `:traffic_drop_notifications` have been tested and should
be enabled for everyone
* Expose current visitors 12h aggregate
* Remove unused site association
* Distinct drop/spike notification factories
* Rename modules accordingly + implement drop handling
* Rename periodic oban service
* Implement drop email
* Rest of the owl
* Update changelog
* Update moduledoc
* Update moduledoc
* Min threshold to 1
* Threshold 1
* Remove merge artifact
* Put panel behind a feature flag
* Format
* 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
* 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
* Allow running browserless.io locally
* Compile tailwind classes based on extra/ too
* Add browserless runtime configuration
* Ignore verification events on ingestion
* Improve extracting HTML text in tests
* Update dependencies
- Floki will be used on production to parse site contents
- Req will be used to handle redundant stuff like retrying etc.
* Add shuttle SVG to generic components
Later on we'll use it to indicate verification errors
* Connect live socket & allow skipping awaiting the first pageview
* Connect live socket in general settings
* Implement verification checks & diagnostics
* Stub remote services with Req for testing
* Change snippet screen copy
* Update tracker script, so that:
1. headless browsers aren't ignored if `window.__plausible` is defined
2. callback optionally supplies the event response HTTP status
This will be later used to check whether the server acknowledged
the verification event.
* Implement LiveView verification UI
* Embed the verification UIs into settings and onboarding
* Implement browserless puppeteer verification script
It:
- tries to visit the site
- defines window.__plausible, so the tracker doesn't ignore test events
- sends a verification event and instruments the callback
- awaits the callback to fire and returns the result
* Improve diagnostics for CSP
Only report CSP error if the snippet is already found
* Put verification behind a feature flag/env setting
* Contact Us hint only for Enterprise Edition
* For headless code, use JS context instead of EEx interpolation
* Update diagnostics test with WordPress scenarios
* Shorten exception/throw interception
* Rename test
* Tidy up
* Bust URL always on headless check
* Update moduledoc
* Detect official Plausible WordPress Plugin
and act accordingly on diagnostics interoperation
* Stop using 'rating' in favour of 'interpretation'
* Only report CSP error if no proxy is likely
* Update CHANGELOG
* Allow event-* attributes on snippet elements
* Improve naive GTM detection, not to confuse it with GA4
* Update lib/plausible/verification.ex
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Update test/plausible/site/verification/checks_test.exs
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* s/perform_wrapped/perform_safe
* Update lib/plausible/verification/checks/installation.ex
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Remove garbage
---------
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Implement `Auth.TOTP.force_disable/1`
* Add "Reset 2FA" action to users CRM
* Add `Purge.reset!/2` variant allowing to set arbitrary cutoff time
* Add ability to set native stats start time from CRM
* Revert "Add `Purge.reset!/2` variant allowing to set arbitrary cutoff time"
This reverts commit 6f294d5d58.
* Add test for CRM site update action
* Reapply "Local CSV exports/imports and S3/UI updates (#3989)" (#3995)
This reverts commit aee69e44c8.
* remove unused functions
* eh, that one was actually used
* ugh, they were both used
---------
Co-authored-by: ruslandoga <67764432+ruslandoga@users.noreply.github.com>
* local CSV exports/imports and S3 updates
* credo
* dialyzer
* refactor input columns
* fix ci minio/clickhouse tests
* Update lib/plausible_web/live/csv_export.ex
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* fix date range filter in export_pages_q and process only pageviews
* remove toTimeZone(zero_timestamp) note
* use SiteImport.pending(), SiteImport.importing()
* escape [SiteImport.pending(), SiteImport.importing()]
* use random s3 keys for imports to avoid collisions (sometimes makes the upload get stuck)
* clamp import date ranges
* site is already in assigns
* recompute cutoff date each time
* use toDate(timestamp[, timezone]) shortcut
* show alreats on export cancel/delete and extract hint into a component
* switch to Imported.clamp_dates/4
* reprocess tables when imports are added
* recompute cutoff_date on each call
* actually use clamped_date_range on submit
* add warning message
* add expiry rules to buckets in make minio
* add site_id to imports notifications and use it in csv_importer
* try/catch safer
* return :ok
* date range is not available when no uploads
* improve ui and warning messages
* use Generic.notice
* fix flaky exports test
* begin tests
* Improve `Importer` notification payload shape
---------
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* encode/decode date range in filenames
* Update lib/plausible/imported/csv_importer.ex
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Update lib/plausible/imported/csv_importer.ex
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* drop unused functions
* send failure email if there is no data to export
* use PlausibleWeb.Email.mailer_email_from()
* ensure we get dates from minmax date query
---------
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* ui
* fix redirect link
* improve make minio
* use implicit button form for csv export
* add exports_bucket helper
* read S3_EXPORTS_BUCKET
* supply s3_bucket in export_csv job args
* make plausible_minio use unprotected port
* move s3_csv_export queue to base queues
* Update lib/plausible_web/controllers/site_controller.ex
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
---------
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Implement LV date input using flatpickr
* Implement basics of GA4 import (very dirty WIP)
* Split Google HTTP API into UA and GA4 specific parts
* Add a quick way to record GA4 API responses
* Add first GA4 import fixtures with GA4 Data API responses
* Extract GA4 and UA specific logic form Google API
* Extract UA and GA4 specific actions to distinct controllers
* Add integration test for GA4 importer
* Update GA4 fixtures
* Test GA4 API
* Add debug logging and fix paginating through API results in in GA4 import
* Revert "Implement LV date input using flatpickr"
This reverts commit c696f8ee39d5702f27015c09a4f079ca124cc7bb.
* Fix note
* wip
* more env, setup user before packages to avoid them picking our uid
* make entrypoint.sh executable by all again
* apparently it's a best practice to have executables be owned by root
* make entrypoint executable in COPY
* stop writing to /app, write to /tmp if needed
* fewer changes
* system user
* keep same style for multiline commands
* fewer changes
* add changelog entry
* fix group assignment for plausible user
* use gid=999
* no home
* no home
* add gecos
* add plausible user to nogroup instead of creating a custom one
* eh
* fewer changes
* fewer changes
* fewer changes
* use PERSISTENT_CACHE_DIR instead of STORAGE_DIR
* ignore more
* cleanup
* remove hex timeout env var
* use ERL_FLAGS=+JMsingle true in public builds
* fallback to /tmp and nest under /tzdata_data/ for tzdata
---------
Co-authored-by: Cenk Kücük <cenk@plausible.io>
This can cause issues as 1 day after a deploy the tzdata list is updated
from 2021 to 2024. Selecting a timezone thats not supported in 2021 can
then break dashboards temporarily following a deploy.
This can be reverted after https://github.com/plausible/analytics/pull/3811
* add csv importer
* make table validation explicit
* update some docs
* improve docs
* add minio container to ci
* more tests
* eh
* continue
* add passing test
* add failing test
* add config test
* add minio to Makefile
* testcontainers
* remove extra whitespace
* explain the implementation a bit
* account for async deletes in tests
* bounces is UInt32
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
---------
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Replace footer text
* add COPYING.txt file
* Add new logos
* Use new logos in all layouts
* New logos
* Check license key on startup
* Bypass license check when Mix.env == :dev
* Use new logos with smaller wordmarks
* Add generic logo_path/1 function
* Use new favicons everywhere
* Bypass license check in test env
* Use sha256 for license key hash
* Mix.env -> config_env()
* Use Mix.evn at compile time rather than runtime
* Mix format
---------
Co-authored-by: Uku Taht <uku.taht@gmail.com>
* Clean up references to no longer active `google_analytics_imports` Oban queue
* Stub CSV importer
* Add SiteImport schema
* Rename `Plausible.Imported` module file to match module name
* Add `import_id` column to `Imported.*` CH schemas
* Implement Importer behavior and manage imports state using new entities
* Implement importer callbacks and maintain site.imported_data for UA
* Keep imports in sync when forgetting all imports
* Scope imported data queries to completed import IDs
* Mark newly imported data with respective import ID
* Clean up Importer implementation a bit
* Test querying legacy and new imported data
* Send Oban notifications on import worker failure too
* Fix checking for forgettable imports and remove redundant function
* Fix UA integration test
* Change site import source to atom enum and add source label
* Add typespecs and reduce repetition in `Plausible.Imported`
* Improve documentation and typespecs
* Add test for purging particular import
* Switch email notification templates depending on import source
* Document running import synchronously
* Fix UA importer args parsing and ensure it's covered by tests
* Clear `site.stats_start_date` on complete import to force recalculation
* Test Oban notifications (h/t @ruslandoga)
* Purge stats on import failure right away to reduce a chance of leaving debris behind
* Fix typos
Co-authored-by: hq1 <hq@mtod.org>
* Fix another typo
* Refactor fetching earliest import and earliest stats start date
* Use `Date.after?` instead of `Timex.after?`
* Cache import data in site virtual fields and limit queried imports to 5
* Ensure always current `stats_start_date` is used
* Work around broken typespec in Timex
* Make `SiteController.forget_imported` action idempotent
* Discard irrecoverably failed import tasks
* Use macros for site import statuses
There's also a fix ensuring only complete imports are considered
where relevant - couldn't isolate it as it was in a common hunk
* Use `import_id` as worker job uniqueness criterion
* Do not load imported stats data in plugins API context
---------
Co-authored-by: hq1 <hq@mtod.org>
* Simplify caches config
The intervals were proven to never change really,
and previous shape made them not very discoverable either.
We'll look into a more declarative setup.
* Aim for more declarative supervision tree setup
* Generalize `Plausible.Cache`
This makes the `Site.Cache` module implement the specifics,
leaving the common bits reusable for upcoming cache processes.
* Generalize `Plausible.Cache` warmers
* Fix typos
* Revert "Remove 0-sized queue"
This reverts commit 6d229b3f70.
* Revert "Temporarily remove notification cron worker (#3732)"
This reverts commit 447e3929cb.
* Revert "Temporarily disable accept_traffic_until actions (#3730)"
This reverts commit 58afe3376f.
* Send accept_traffic_until notifications at 8 UTC rather than 5
* Add option for dry-run
* Expose dry_run in a dedicated function
* Move imported tables schemas to separate modules outside Google ns
* Move buffer for imports to Imported ns
* fix schema newlines
* Extract UA import processing and persistence
* Decouple analytics worker implementation from UA
* Rename env variable for import buffer size
* Preserve old import queue until release
* Update communication
* Remove an unreachable function (mistyped)
* [migration] Make accept_traffic_until a date
* Fix typo
* Set `accept_traffic_until` when creating a site
* Update sites `accept_traffic_until` on subscription change
* Add a note to yearly cancellation notification
* Rephrase annual e-mail for clarity
* Pass the small build test
* Add email notifications
* Fixup
* Implement `accept_traffic_until` notification worker
* Fixup - no need to test this for small build
* Update moduledoc
* Move moduletag
* s/sent_at/sent_on
* Use WHERE NOT EXISTS instead of LEFT JOIN
* Use upsert when tracking notifications sent
* Store sent marker before actually sending notification
* Prefer to keep `accept_traffic_until` on the user record
This gives us a single source of truth, addresses cases like
ownership transparently, simplifies the code and enables CRM toggles.
The only downside is that there's another join performed in the
Sites.Cache full refresh - in this case, small refreshes are
skipped - but this is fine, since the traffic will be let in
anyway.
* Expose `accepted_traffic_until` in the CRM
* Update lib/plausible/auth/user.ex
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* Preload owner in CRM
* Use the offset parameter in trial over e-mail contents
* Format
* Harden cache test
---------
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>