mirror of
https://github.com/plausible/analytics.git
synced 2024-12-25 10:33:01 +03:00
1 line
374 KiB
JavaScript
1 line
374 KiB
JavaScript
searchNodes=[{"doc":"","ref":"Mix.Tasks.AnalyzePlans.html","title":"Mix.Tasks.AnalyzePlans","type":"task"},{"doc":"Callback implementation for Mix.Task.run/1 .","ref":"Mix.Tasks.AnalyzePlans.html#run/1","title":"Mix.Tasks.AnalyzePlans.run/1","type":"function"},{"doc":"","ref":"Mix.Tasks.CleanClickhouse.html","title":"Mix.Tasks.CleanClickhouse","type":"task"},{"doc":"Callback implementation for Mix.Task.run/1 .","ref":"Mix.Tasks.CleanClickhouse.html#run/1","title":"Mix.Tasks.CleanClickhouse.run/1","type":"function"},{"doc":"","ref":"Mix.Tasks.CreateFreeSubscription.html","title":"Mix.Tasks.CreateFreeSubscription","type":"task"},{"doc":"","ref":"Mix.Tasks.CreateFreeSubscription.html#execute/1","title":"Mix.Tasks.CreateFreeSubscription.execute/1","type":"function"},{"doc":"Callback implementation for Mix.Task.run/1 .","ref":"Mix.Tasks.CreateFreeSubscription.html#run/1","title":"Mix.Tasks.CreateFreeSubscription.run/1","type":"function"},{"doc":"This task downloads the Country Lite database from DB-IP for self-hosted or development purposes. Plausible Cloud runs a paid version of DB-IP with more detailed geolocation data.","ref":"Mix.Tasks.DownloadCountryDatabase.html","title":"Mix.Tasks.DownloadCountryDatabase","type":"task"},{"doc":"Callback implementation for Mix.Task.run/1 .","ref":"Mix.Tasks.DownloadCountryDatabase.html#run/1","title":"Mix.Tasks.DownloadCountryDatabase.run/1","type":"function"},{"doc":"","ref":"Mix.Tasks.GenerateReferrerFavicons.html","title":"Mix.Tasks.GenerateReferrerFavicons","type":"task"},{"doc":"Callback implementation for Mix.Task.run/1 .","ref":"Mix.Tasks.GenerateReferrerFavicons.html#run/1","title":"Mix.Tasks.GenerateReferrerFavicons.run/1","type":"function"},{"doc":"","ref":"Mix.Tasks.PullSandboxSubscription.html","title":"Mix.Tasks.PullSandboxSubscription","type":"task"},{"doc":"Callback implementation for Mix.Task.run/1 .","ref":"Mix.Tasks.PullSandboxSubscription.html#run/1","title":"Mix.Tasks.PullSandboxSubscription.run/1","type":"function"},{"doc":"It's often necessary to generate fake events for development and testing purposes. This Mix Task provides a quick and easy way to generate a pageview or custom event, either in your development environment or a remote Plausible instance. See Mix.Tasks.SendPageview.usage/1 for more detailed documentation.","ref":"Mix.Tasks.SendPageview.html","title":"Mix.Tasks.SendPageview","type":"task"},{"doc":"Callback implementation for Mix.Task.run/1 .","ref":"Mix.Tasks.SendPageview.html#run/1","title":"Mix.Tasks.SendPageview.run/1","type":"function"},{"doc":"","ref":"ObanErrorReporter.html","title":"ObanErrorReporter","type":"module"},{"doc":"","ref":"ObanErrorReporter.html#handle_event/4","title":"ObanErrorReporter.handle_event/4","type":"function"},{"doc":"Plausible keeps the contexts that define your domain and business logic. Contexts are also responsible for managing your data, regardless if it comes from the database, an external API or others.","ref":"Plausible.html","title":"Plausible","type":"module"},{"doc":"Clickhouse access with async inserts enabled","ref":"Plausible.AsyncInsertRepo.html","title":"Plausible.AsyncInsertRepo","type":"module"},{"doc":"Callback implementation for Ecto.Repo.aggregate/3 .","ref":"Plausible.AsyncInsertRepo.html#aggregate/3","title":"Plausible.AsyncInsertRepo.aggregate/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.aggregate/4 .","ref":"Plausible.AsyncInsertRepo.html#aggregate/4","title":"Plausible.AsyncInsertRepo.aggregate/4","type":"function"},{"doc":"Callback implementation for Ecto.Repo.all/2 .","ref":"Plausible.AsyncInsertRepo.html#all/2","title":"Plausible.AsyncInsertRepo.all/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.checked_out?/0 .","ref":"Plausible.AsyncInsertRepo.html#checked_out?/0","title":"Plausible.AsyncInsertRepo.checked_out?/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.checkout/2 .","ref":"Plausible.AsyncInsertRepo.html#checkout/2","title":"Plausible.AsyncInsertRepo.checkout/2","type":"function"},{"doc":"","ref":"Plausible.AsyncInsertRepo.html#child_spec/1","title":"Plausible.AsyncInsertRepo.child_spec/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.config/0 .","ref":"Plausible.AsyncInsertRepo.html#config/0","title":"Plausible.AsyncInsertRepo.config/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.default_options/1 .","ref":"Plausible.AsyncInsertRepo.html#default_options/1","title":"Plausible.AsyncInsertRepo.default_options/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete/2 .","ref":"Plausible.AsyncInsertRepo.html#delete/2","title":"Plausible.AsyncInsertRepo.delete/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete!/2 .","ref":"Plausible.AsyncInsertRepo.html#delete!/2","title":"Plausible.AsyncInsertRepo.delete!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete_all/2 .","ref":"Plausible.AsyncInsertRepo.html#delete_all/2","title":"Plausible.AsyncInsertRepo.delete_all/2","type":"function"},{"doc":"A convenience function for SQL-based repositories that forces all connections in the pool to disconnect within the given interval. See Ecto.Adapters.SQL.disconnect_all/3 for more information.","ref":"Plausible.AsyncInsertRepo.html#disconnect_all/2","title":"Plausible.AsyncInsertRepo.disconnect_all/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.exists?/2 .","ref":"Plausible.AsyncInsertRepo.html#exists?/2","title":"Plausible.AsyncInsertRepo.exists?/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get/3 .","ref":"Plausible.AsyncInsertRepo.html#get/3","title":"Plausible.AsyncInsertRepo.get/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get!/3 .","ref":"Plausible.AsyncInsertRepo.html#get!/3","title":"Plausible.AsyncInsertRepo.get!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_by/3 .","ref":"Plausible.AsyncInsertRepo.html#get_by/3","title":"Plausible.AsyncInsertRepo.get_by/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_by!/3 .","ref":"Plausible.AsyncInsertRepo.html#get_by!/3","title":"Plausible.AsyncInsertRepo.get_by!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_dynamic_repo/0 .","ref":"Plausible.AsyncInsertRepo.html#get_dynamic_repo/0","title":"Plausible.AsyncInsertRepo.get_dynamic_repo/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert/2 .","ref":"Plausible.AsyncInsertRepo.html#insert/2","title":"Plausible.AsyncInsertRepo.insert/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert!/2 .","ref":"Plausible.AsyncInsertRepo.html#insert!/2","title":"Plausible.AsyncInsertRepo.insert!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_all/3 .","ref":"Plausible.AsyncInsertRepo.html#insert_all/3","title":"Plausible.AsyncInsertRepo.insert_all/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_or_update/2 .","ref":"Plausible.AsyncInsertRepo.html#insert_or_update/2","title":"Plausible.AsyncInsertRepo.insert_or_update/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_or_update!/2 .","ref":"Plausible.AsyncInsertRepo.html#insert_or_update!/2","title":"Plausible.AsyncInsertRepo.insert_or_update!/2","type":"function"},{"doc":"Similar to insert_all/2 but with the following differences: accepts rows as streams or lists sends rows as a chunked request doesn't autogenerate ids or does any other preprocessing Example: Repo . query! ( "create table ecto_ch_demo(a UInt64, b String) engine Null" ) defmodule Demo do use Ecto.Schema @primary_key false schema "ecto_ch_demo" do field :a , Ch , type : "UInt64" field :b , :string end end rows = Stream . map ( 1 .. 100_000 , fn i -> %{ a : i , b : to_string ( i ) } end ) { 100_000 , nil } = Repo . insert_stream ( Demo , rows ) # schemaless { 100_000 , nil } = Repo . insert_stream ( "ecto_ch_demo" , rows , types : [ a : Ch.Types . u64 ( ) , b : :string ] )","ref":"Plausible.AsyncInsertRepo.html#insert_stream/3","title":"Plausible.AsyncInsertRepo.insert_stream/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.load/2 .","ref":"Plausible.AsyncInsertRepo.html#load/2","title":"Plausible.AsyncInsertRepo.load/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.one/2 .","ref":"Plausible.AsyncInsertRepo.html#one/2","title":"Plausible.AsyncInsertRepo.one/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.one!/2 .","ref":"Plausible.AsyncInsertRepo.html#one!/2","title":"Plausible.AsyncInsertRepo.one!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.preload/3 .","ref":"Plausible.AsyncInsertRepo.html#preload/3","title":"Plausible.AsyncInsertRepo.preload/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.prepare_query/3 .","ref":"Plausible.AsyncInsertRepo.html#prepare_query/3","title":"Plausible.AsyncInsertRepo.prepare_query/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.put_dynamic_repo/1 .","ref":"Plausible.AsyncInsertRepo.html#put_dynamic_repo/1","title":"Plausible.AsyncInsertRepo.put_dynamic_repo/1","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given query. See Ecto.Adapters.SQL.query/4 for more information.","ref":"Plausible.AsyncInsertRepo.html#query/3","title":"Plausible.AsyncInsertRepo.query/3","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given query. See Ecto.Adapters.SQL.query!/4 for more information.","ref":"Plausible.AsyncInsertRepo.html#query!/3","title":"Plausible.AsyncInsertRepo.query!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.reload/2 .","ref":"Plausible.AsyncInsertRepo.html#reload/2","title":"Plausible.AsyncInsertRepo.reload/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.reload!/2 .","ref":"Plausible.AsyncInsertRepo.html#reload!/2","title":"Plausible.AsyncInsertRepo.reload!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.start_link/1 .","ref":"Plausible.AsyncInsertRepo.html#start_link/1","title":"Plausible.AsyncInsertRepo.start_link/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.stop/1 .","ref":"Plausible.AsyncInsertRepo.html#stop/1","title":"Plausible.AsyncInsertRepo.stop/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.stream/2 .","ref":"Plausible.AsyncInsertRepo.html#stream/2","title":"Plausible.AsyncInsertRepo.stream/2","type":"function"},{"doc":"A convenience function for SQL-based repositories that translates the given query to SQL. See Ecto.Adapters.SQL.to_sql/3 for more information.","ref":"Plausible.AsyncInsertRepo.html#to_sql/2","title":"Plausible.AsyncInsertRepo.to_sql/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update/2 .","ref":"Plausible.AsyncInsertRepo.html#update/2","title":"Plausible.AsyncInsertRepo.update/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update!/2 .","ref":"Plausible.AsyncInsertRepo.html#update!/2","title":"Plausible.AsyncInsertRepo.update!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update_all/3 .","ref":"Plausible.AsyncInsertRepo.html#update_all/3","title":"Plausible.AsyncInsertRepo.update_all/3","type":"function"},{"doc":"","ref":"Plausible.Auth.html","title":"Plausible.Auth","type":"module"},{"doc":"","ref":"Plausible.Auth.html#create_user/3","title":"Plausible.Auth.create_user/3","type":"function"},{"doc":"","ref":"Plausible.Auth.html#delete_user/1","title":"Plausible.Auth.delete_user/1","type":"function"},{"doc":"","ref":"Plausible.Auth.html#enterprise?/1","title":"Plausible.Auth.enterprise?/1","type":"function"},{"doc":"","ref":"Plausible.Auth.html#find_user_by/1","title":"Plausible.Auth.find_user_by/1","type":"function"},{"doc":"","ref":"Plausible.Auth.html#has_active_sites?/2","title":"Plausible.Auth.has_active_sites?/2","type":"function"},{"doc":"","ref":"Plausible.Auth.html#is_super_admin?/1","title":"Plausible.Auth.is_super_admin?/1","type":"function"},{"doc":"","ref":"Plausible.Auth.html#issue_email_verification/1","title":"Plausible.Auth.issue_email_verification/1","type":"function"},{"doc":"","ref":"Plausible.Auth.html#user_owns_sites?/1","title":"Plausible.Auth.user_owns_sites?/1","type":"function"},{"doc":"","ref":"Plausible.Auth.html#verify_email/2","title":"Plausible.Auth.verify_email/2","type":"function"},{"doc":"","ref":"Plausible.Auth.ApiKey.html","title":"Plausible.Auth.ApiKey","type":"module"},{"doc":"","ref":"Plausible.Auth.ApiKey.html#changeset/2","title":"Plausible.Auth.ApiKey.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Auth.ApiKey.html#do_hash/1","title":"Plausible.Auth.ApiKey.do_hash/1","type":"function"},{"doc":"","ref":"Plausible.Auth.ApiKey.html#process_key/1","title":"Plausible.Auth.ApiKey.process_key/1","type":"function"},{"doc":"","ref":"Plausible.Auth.ApiKey.html#update/2","title":"Plausible.Auth.ApiKey.update/2","type":"function"},{"doc":"","ref":"Plausible.Auth.ApiKeyAdmin.html","title":"Plausible.Auth.ApiKeyAdmin","type":"module"},{"doc":"","ref":"Plausible.Auth.ApiKeyAdmin.html#create_changeset/2","title":"Plausible.Auth.ApiKeyAdmin.create_changeset/2","type":"function"},{"doc":"","ref":"Plausible.Auth.ApiKeyAdmin.html#custom_index_query/3","title":"Plausible.Auth.ApiKeyAdmin.custom_index_query/3","type":"function"},{"doc":"","ref":"Plausible.Auth.ApiKeyAdmin.html#form_fields/1","title":"Plausible.Auth.ApiKeyAdmin.form_fields/1","type":"function"},{"doc":"","ref":"Plausible.Auth.ApiKeyAdmin.html#index/1","title":"Plausible.Auth.ApiKeyAdmin.index/1","type":"function"},{"doc":"","ref":"Plausible.Auth.ApiKeyAdmin.html#search_fields/1","title":"Plausible.Auth.ApiKeyAdmin.search_fields/1","type":"function"},{"doc":"","ref":"Plausible.Auth.ApiKeyAdmin.html#update_changeset/2","title":"Plausible.Auth.ApiKeyAdmin.update_changeset/2","type":"function"},{"doc":"This embedded schema stores information about the account locking grace period. Users are given this 7-day grace period to upgrade their account after outgrowing their subscriptions. The actual account locking happens in background with Plausible.Workers.LockSites . The grace period can also be manual, without an end date, being controlled manually from the CRM, and not by the background site locker job. This is useful for enterprise subscriptions.","ref":"Plausible.Auth.GracePeriod.html","title":"Plausible.Auth.GracePeriod","type":"module"},{"doc":"Returns whether the grace period is still active for a User. Defaults to false if the user is nil or there is no grace period.","ref":"Plausible.Auth.GracePeriod.html#active?/1","title":"Plausible.Auth.GracePeriod.active?/1","type":"function"},{"doc":"Ends an existing grace period by setting users.grace_period.is_over to true. This means the grace period has expired.","ref":"Plausible.Auth.GracePeriod.html#end_changeset/1","title":"Plausible.Auth.GracePeriod.end_changeset/1","type":"function"},{"doc":"Returns whether the grace period has already expired for a User. Defaults to false if the user is nil or there is no grace period.","ref":"Plausible.Auth.GracePeriod.html#expired?/1","title":"Plausible.Auth.GracePeriod.expired?/1","type":"function"},{"doc":"Removes the grace period from the User completely.","ref":"Plausible.Auth.GracePeriod.html#remove_changeset/1","title":"Plausible.Auth.GracePeriod.remove_changeset/1","type":"function"},{"doc":"Starts a account locking grace period of 7 days by changing the User struct.","ref":"Plausible.Auth.GracePeriod.html#start_changeset/2","title":"Plausible.Auth.GracePeriod.start_changeset/2","type":"function"},{"doc":"Starts a manual account locking grace period by changing the User struct. Manual locking means the grace period can only be removed manually from the CRM.","ref":"Plausible.Auth.GracePeriod.html#start_manual_lock_changeset/2","title":"Plausible.Auth.GracePeriod.start_manual_lock_changeset/2","type":"function"},{"doc":"","ref":"Plausible.Auth.GracePeriod.html#t:t/0","title":"Plausible.Auth.GracePeriod.t/0","type":"type"},{"doc":"","ref":"Plausible.Auth.Invitation.html","title":"Plausible.Auth.Invitation","type":"module"},{"doc":"","ref":"Plausible.Auth.Invitation.html#new/1","title":"Plausible.Auth.Invitation.new/1","type":"function"},{"doc":"","ref":"Plausible.Auth.Password.html","title":"Plausible.Auth.Password","type":"module"},{"doc":"","ref":"Plausible.Auth.Password.html#dummy_calculation/0","title":"Plausible.Auth.Password.dummy_calculation/0","type":"function"},{"doc":"","ref":"Plausible.Auth.Password.html#hash/1","title":"Plausible.Auth.Password.hash/1","type":"function"},{"doc":"","ref":"Plausible.Auth.Password.html#match?/2","title":"Plausible.Auth.Password.match?/2","type":"function"},{"doc":"","ref":"Plausible.Auth.Token.html","title":"Plausible.Auth.Token","type":"module"},{"doc":"","ref":"Plausible.Auth.Token.html#sign_password_reset/1","title":"Plausible.Auth.Token.sign_password_reset/1","type":"function"},{"doc":"","ref":"Plausible.Auth.Token.html#sign_shared_link/1","title":"Plausible.Auth.Token.sign_shared_link/1","type":"function"},{"doc":"","ref":"Plausible.Auth.Token.html#verify_password_reset/1","title":"Plausible.Auth.Token.verify_password_reset/1","type":"function"},{"doc":"","ref":"Plausible.Auth.Token.html#verify_shared_link/1","title":"Plausible.Auth.Token.verify_shared_link/1","type":"function"},{"doc":"","ref":"Plausible.Auth.User.html","title":"Plausible.Auth.User","type":"module"},{"doc":"","ref":"Plausible.Auth.User.html#changeset/2","title":"Plausible.Auth.User.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Auth.User.html#end_trial/1","title":"Plausible.Auth.User.end_trial/1","type":"function"},{"doc":"","ref":"Plausible.Auth.User.html#hash_password/1","title":"Plausible.Auth.User.hash_password/1","type":"function"},{"doc":"","ref":"Plausible.Auth.User.html#new/1","title":"Plausible.Auth.User.new/1","type":"function"},{"doc":"","ref":"Plausible.Auth.User.html#remove_trial_expiry/1","title":"Plausible.Auth.User.remove_trial_expiry/1","type":"function"},{"doc":"","ref":"Plausible.Auth.User.html#set_password/2","title":"Plausible.Auth.User.set_password/2","type":"function"},{"doc":"","ref":"Plausible.Auth.User.html#start_trial/1","title":"Plausible.Auth.User.start_trial/1","type":"function"},{"doc":"","ref":"Plausible.Auth.User.html#t:t/0","title":"Plausible.Auth.User.t/0","type":"type"},{"doc":"","ref":"Plausible.Auth.UserAdmin.html","title":"Plausible.Auth.UserAdmin","type":"module"},{"doc":"","ref":"Plausible.Auth.UserAdmin.html#custom_index_query/3","title":"Plausible.Auth.UserAdmin.custom_index_query/3","type":"function"},{"doc":"","ref":"Plausible.Auth.UserAdmin.html#form_fields/1","title":"Plausible.Auth.UserAdmin.form_fields/1","type":"function"},{"doc":"","ref":"Plausible.Auth.UserAdmin.html#index/1","title":"Plausible.Auth.UserAdmin.index/1","type":"function"},{"doc":"","ref":"Plausible.Auth.UserAdmin.html#resource_actions/1","title":"Plausible.Auth.UserAdmin.resource_actions/1","type":"function"},{"doc":"","ref":"Plausible.Billing.html","title":"Plausible.Billing","type":"module"},{"doc":"","ref":"Plausible.Billing.html#active_subscription_for/1","title":"Plausible.Billing.active_subscription_for/1","type":"function"},{"doc":"","ref":"Plausible.Billing.html#change_plan/2","title":"Plausible.Billing.change_plan/2","type":"function"},{"doc":"","ref":"Plausible.Billing.html#change_plan_preview/2","title":"Plausible.Billing.change_plan_preview/2","type":"function"},{"doc":"","ref":"Plausible.Billing.html#has_active_subscription?/1","title":"Plausible.Billing.has_active_subscription?/1","type":"function"},{"doc":"","ref":"Plausible.Billing.html#last_two_billing_cycles/2","title":"Plausible.Billing.last_two_billing_cycles/2","type":"function"},{"doc":"","ref":"Plausible.Billing.html#last_two_billing_months_usage/2","title":"Plausible.Billing.last_two_billing_months_usage/2","type":"function"},{"doc":"","ref":"Plausible.Billing.html#needs_to_upgrade?/1","title":"Plausible.Billing.needs_to_upgrade?/1","type":"function"},{"doc":"","ref":"Plausible.Billing.html#on_trial?/1","title":"Plausible.Billing.on_trial?/1","type":"function"},{"doc":"","ref":"Plausible.Billing.html#paddle_api/0","title":"Plausible.Billing.paddle_api/0","type":"function"},{"doc":"Returns the number of sites that an account is allowed to have. Accounts for grandfathering old accounts to unlimited websites and ignores site limit on self-hosted installations.","ref":"Plausible.Billing.html#sites_limit/1","title":"Plausible.Billing.sites_limit/1","type":"function"},{"doc":"","ref":"Plausible.Billing.html#subscription_cancelled/1","title":"Plausible.Billing.subscription_cancelled/1","type":"function"},{"doc":"","ref":"Plausible.Billing.html#subscription_created/1","title":"Plausible.Billing.subscription_created/1","type":"function"},{"doc":"","ref":"Plausible.Billing.html#subscription_payment_succeeded/1","title":"Plausible.Billing.subscription_payment_succeeded/1","type":"function"},{"doc":"","ref":"Plausible.Billing.html#subscription_updated/1","title":"Plausible.Billing.subscription_updated/1","type":"function"},{"doc":"","ref":"Plausible.Billing.html#trial_days_left/1","title":"Plausible.Billing.trial_days_left/1","type":"function"},{"doc":"","ref":"Plausible.Billing.html#usage/1","title":"Plausible.Billing.usage/1","type":"function"},{"doc":"","ref":"Plausible.Billing.html#usage_breakdown/1","title":"Plausible.Billing.usage_breakdown/1","type":"function"},{"doc":"","ref":"Plausible.Billing.EnterprisePlan.html","title":"Plausible.Billing.EnterprisePlan","type":"module"},{"doc":"","ref":"Plausible.Billing.EnterprisePlan.html#changeset/2","title":"Plausible.Billing.EnterprisePlan.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Billing.EnterprisePlanAdmin.html","title":"Plausible.Billing.EnterprisePlanAdmin","type":"module"},{"doc":"","ref":"Plausible.Billing.EnterprisePlanAdmin.html#custom_index_query/3","title":"Plausible.Billing.EnterprisePlanAdmin.custom_index_query/3","type":"function"},{"doc":"","ref":"Plausible.Billing.EnterprisePlanAdmin.html#form_fields/1","title":"Plausible.Billing.EnterprisePlanAdmin.form_fields/1","type":"function"},{"doc":"","ref":"Plausible.Billing.EnterprisePlanAdmin.html#index/1","title":"Plausible.Billing.EnterprisePlanAdmin.index/1","type":"function"},{"doc":"","ref":"Plausible.Billing.EnterprisePlanAdmin.html#search_fields/1","title":"Plausible.Billing.EnterprisePlanAdmin.search_fields/1","type":"function"},{"doc":"","ref":"Plausible.Billing.PaddleApi.html","title":"Plausible.Billing.PaddleApi","type":"module"},{"doc":"","ref":"Plausible.Billing.PaddleApi.html#checkout_domain/0","title":"Plausible.Billing.PaddleApi.checkout_domain/0","type":"function"},{"doc":"","ref":"Plausible.Billing.PaddleApi.html#get_invoices/1","title":"Plausible.Billing.PaddleApi.get_invoices/1","type":"function"},{"doc":"","ref":"Plausible.Billing.PaddleApi.html#get_subscription/1","title":"Plausible.Billing.PaddleApi.get_subscription/1","type":"function"},{"doc":"","ref":"Plausible.Billing.PaddleApi.html#update_subscription/2","title":"Plausible.Billing.PaddleApi.update_subscription/2","type":"function"},{"doc":"","ref":"Plausible.Billing.PaddleApi.html#update_subscription_preview/2","title":"Plausible.Billing.PaddleApi.update_subscription_preview/2","type":"function"},{"doc":"","ref":"Plausible.Billing.PaddleApi.html#vendors_domain/0","title":"Plausible.Billing.PaddleApi.vendors_domain/0","type":"function"},{"doc":"","ref":"Plausible.Billing.Plans.html","title":"Plausible.Billing.Plans","type":"module"},{"doc":"","ref":"Plausible.Billing.Plans.html#all_yearly_plan_ids/0","title":"Plausible.Billing.Plans.all_yearly_plan_ids/0","type":"function"},{"doc":"","ref":"Plausible.Billing.Plans.html#allowance/1","title":"Plausible.Billing.Plans.allowance/1","type":"function"},{"doc":"","ref":"Plausible.Billing.Plans.html#for_product_id/1","title":"Plausible.Billing.Plans.for_product_id/1","type":"function"},{"doc":"","ref":"Plausible.Billing.Plans.html#plans_for/1","title":"Plausible.Billing.Plans.plans_for/1","type":"function"},{"doc":"","ref":"Plausible.Billing.Plans.html#subscription_interval/1","title":"Plausible.Billing.Plans.subscription_interval/1","type":"function"},{"doc":"","ref":"Plausible.Billing.Plans.html#suggested_plan/2","title":"Plausible.Billing.Plans.suggested_plan/2","type":"function"},{"doc":"","ref":"Plausible.Billing.Plans.html#t:plan/0","title":"Plausible.Billing.Plans.plan/0","type":"type"},{"doc":"","ref":"Plausible.Billing.SiteLocker.html","title":"Plausible.Billing.SiteLocker","type":"module"},{"doc":"","ref":"Plausible.Billing.SiteLocker.html#check_sites_for/1","title":"Plausible.Billing.SiteLocker.check_sites_for/1","type":"function"},{"doc":"","ref":"Plausible.Billing.SiteLocker.html#set_lock_status_for/2","title":"Plausible.Billing.SiteLocker.set_lock_status_for/2","type":"function"},{"doc":"Helper function for working with Ecto changesets","ref":"Plausible.ChangesetHelpers.html","title":"Plausible.ChangesetHelpers","type":"module"},{"doc":"","ref":"Plausible.ChangesetHelpers.html#traverse_errors/1","title":"Plausible.ChangesetHelpers.traverse_errors/1","type":"function"},{"doc":"Provides the core functions to retrieve and manage the CLDR data that supports formatting and localisation. It provides the core functions to access formatted CLDR data, set and retrieve a current locale and validate certain core data types such as locales, currencies and territories.","ref":"Plausible.Cldr.html","title":"Plausible.Cldr","type":"module"},{"doc":"See Cldr.available_locale_name?/1 .","ref":"Plausible.Cldr.html#available_locale_name?/1","title":"Plausible.Cldr.available_locale_name?/1","type":"function"},{"doc":"Returns the default locale . Example iex> Plausible.Cldr . default_locale ( ) % Cldr.LanguageTag { backend : Plausible.Cldr , canonical_locale_name : "en-001" , cldr_locale_name : :"en-001" , language_subtags : [ ] , extensions : %{ } , gettext_locale_name : "en" , language : "en" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :en , requested_locale_name : "en-001" , script : :Latn , territory : :"001" , transform : %{ } , language_variants : [ ] }","ref":"Plausible.Cldr.html#default_locale/0","title":"Plausible.Cldr.default_locale/0","type":"function"},{"doc":"Returns the default territory when a locale does not specify one and none can be inferred. Example iex> Plausible.Cldr . default_territory ( ) :"001"","ref":"Plausible.Cldr.html#default_territory/0","title":"Plausible.Cldr.default_territory/0","type":"function"},{"doc":"Add locale-specific ellipsis to a string. Arguments string is any String.t or a 2-element list of String.t between which the ellipsis is inserted. backend is any module that includes use Cldr and therefore is a Cldr backend module. The default is Cldr.default_backend!/0 . Note that Cldr.default_backend!/0 will raise an exception if no :default_backend is configured under the :ex_cldr key in config.exs . options is a keyword list of options Options :locale is any valid locale name returned by Cldr.known_locale_names/1 . The default is Cldr.get_locale/0 . :location determines where to place the ellipsis. The options are :after (the default for a single string argument), :between (the default and only valid location for an argument that is a list of two strings) and :before . :format formats based upon whether the ellipsis is inserted between words or sentences. The valid options are :word or :sentence . The default is :sentence . Examples iex> Plausible.Cldr . ellipsis "And furthermore" "And furthermore…" iex> Plausible.Cldr . ellipsis [ "And furthermore" , "there is much to be done" ] , locale : :ja "And furthermore…there is much to be done" iex> Plausible.Cldr . ellipsis "And furthermore" , format : :word "And furthermore …" iex> Plausible.Cldr . ellipsis [ "And furthermore" , "there is much to be done" ] , locale : :ja , format : :word "And furthermore … there is much to be done"","ref":"Plausible.Cldr.html#ellipsis/2","title":"Plausible.Cldr.ellipsis/2","type":"function"},{"doc":"Return the current locale to be used for Cldr functions that take an optional locale parameter for which a locale is not supplied. Example iex> Plausible.Cldr . put_locale ( "pl" ) iex> Plausible.Cldr . get_locale % Cldr.LanguageTag { backend : Elixir.Plausible.Cldr , canonical_locale_name : "pl" , cldr_locale_name : :pl , extensions : %{ } , language : "pl" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :pl , territory : :PL , requested_locale_name : "pl" , script : :Latn , transform : %{ } , language_variants : [ ] }","ref":"Plausible.Cldr.html#get_locale/0","title":"Plausible.Cldr.get_locale/0","type":"function"},{"doc":"See Cldr.known_calendars/0 .","ref":"Plausible.Cldr.html#known_calendars/0","title":"Plausible.Cldr.known_calendars/0","type":"function"},{"doc":"See Cldr.known_currencies/0 .","ref":"Plausible.Cldr.html#known_currencies/0","title":"Plausible.Cldr.known_currencies/0","type":"function"},{"doc":"Returns either the Gettext locale_name in Cldr format or false based upon whether the locale name is configured in Gettext . Arguments locale is any valid locale name returned by Plausible.Cldr.known_gettext_locale_names/0 Examples iex> Plausible.Cldr . known_gettext_locale_name "en" "en" iex> Plausible.Cldr . known_gettext_locale_name "en-SA" false","ref":"Plausible.Cldr.html#known_gettext_locale_name/1","title":"Plausible.Cldr.known_gettext_locale_name/1","type":"function"},{"doc":"Returns a boolean indicating if the specified locale name is configured and available in Gettext. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 Examples iex> Plausible.Cldr . known_gettext_locale_name? ( "en" ) true iex> Plausible.Cldr . known_gettext_locale_name? ( "!!" ) false","ref":"Plausible.Cldr.html#known_gettext_locale_name?/1","title":"Plausible.Cldr.known_gettext_locale_name?/1","type":"function"},{"doc":"Returns a list of Gettext locale names but in CLDR format with underscore replaced by hyphen in order to facilitate comparisons with Cldr locale names.","ref":"Plausible.Cldr.html#known_gettext_locale_names/0","title":"Plausible.Cldr.known_gettext_locale_names/0","type":"function"},{"doc":"Returns either the locale_name or false based upon whether the locale name is configured in Cldr . This is helpful when building a list of or expressions to return the first known locale name from a list. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 Examples iex> Plausible.Cldr . known_locale_name :"en-AU" :"en-AU" iex> Plausible.Cldr . known_locale_name :"en-SA" false","ref":"Plausible.Cldr.html#known_locale_name/1","title":"Plausible.Cldr.known_locale_name/1","type":"function"},{"doc":"Returns a boolean indicating if the specified locale name is configured and available in Cldr. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 Examples iex> Plausible.Cldr . known_locale_name? ( :en ) true iex> Plausible.Cldr . known_locale_name? ( :"!!" ) false","ref":"Plausible.Cldr.html#known_locale_name?/1","title":"Plausible.Cldr.known_locale_name?/1","type":"function"},{"doc":"Returns a list of the known locale names. Known locales are those locales which are the subset of all CLDR locales that have been configured for use either in this module or in Gettext .","ref":"Plausible.Cldr.html#known_locale_names/0","title":"Plausible.Cldr.known_locale_names/0","type":"function"},{"doc":"Returns a list of atoms representing the number systems types known to Cldr . Example iex> Plausible.Cldr . known_number_system_types [ :default , :finance , :native , :traditional ]","ref":"Plausible.Cldr.html#known_number_system_types/0","title":"Plausible.Cldr.known_number_system_types/0","type":"function"},{"doc":"See Cldr.known_number_systems/0 .","ref":"Plausible.Cldr.html#known_number_systems/0","title":"Plausible.Cldr.known_number_systems/0","type":"function"},{"doc":"Returns either the RBNF locale_name or false based upon whether the locale name is configured in Cldr and has RBNF rules defined. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 Examples iex> Plausible.Cldr . known_rbnf_locale_name :en :en iex> Plausible.Cldr . known_rbnf_locale_name :"en-SA" false","ref":"Plausible.Cldr.html#known_rbnf_locale_name/1","title":"Plausible.Cldr.known_rbnf_locale_name/1","type":"function"},{"doc":"Returns a boolean indicating if the specified locale name is configured and available in Cldr and supports rules based number formats (RBNF). Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 Examples iex> Plausible.Cldr . known_rbnf_locale_name? ( :en ) true iex> Plausible.Cldr . known_rbnf_locale_name? ( :"!!" ) false","ref":"Plausible.Cldr.html#known_rbnf_locale_name?/1","title":"Plausible.Cldr.known_rbnf_locale_name?/1","type":"function"},{"doc":"Returns a list of locale names which have rules-based number formats (RBNF).","ref":"Plausible.Cldr.html#known_rbnf_locale_names/0","title":"Plausible.Cldr.known_rbnf_locale_names/0","type":"function"},{"doc":"See Cldr.known_territories/0 .","ref":"Plausible.Cldr.html#known_territories/0","title":"Plausible.Cldr.known_territories/0","type":"function"},{"doc":"Normalizes a string by applying transliteration of common symbols in numbers, currencies and dates","ref":"Plausible.Cldr.html#normalize_lenient_parse/3","title":"Plausible.Cldr.normalize_lenient_parse/3","type":"function"},{"doc":"Set the current locale to be used for Cldr functions that take an optional locale parameter for which a locale is not supplied. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a t:Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 See rfc5646 for the specification of a language tag. Examples iex> Plausible.Cldr . put_locale ( "en" ) { :ok , % Cldr.LanguageTag { backend : Plausible.Cldr , canonical_locale_name : "en" , cldr_locale_name : :en , language_subtags : [ ] , extensions : %{ } , gettext_locale_name : "en" , language : "en" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :en , requested_locale_name : "en" , script : :Latn , territory : :US , transform : %{ } , language_variants : [ ] } } iex> Plausible.Cldr . put_locale ( "invalid-locale!" ) { :error , { Cldr.LanguageTag.ParseError , "Expected a BCP47 language tag. Could not parse the remaining \\" ! \\" starting at position 15" } }","ref":"Plausible.Cldr.html#put_locale/1","title":"Plausible.Cldr.put_locale/1","type":"function"},{"doc":"Add locale-specific quotation marks around a string. Arguments string is any valid Elixir string options is a keyword list of options Options locale is any valid locale name returned by Cldr.known_locale_names/1 . The default is Cldr.get_locale/0 Examples iex> Plausible.Cldr . quote "Quoted String" "“Quoted String”" iex> Plausible.Cldr . quote "Quoted String" , locale : :ja "「Quoted String」"","ref":"Plausible.Cldr.html#quote/2","title":"Plausible.Cldr.quote/2","type":"function"},{"doc":"Returns a list of the locales names that are configured, but not known in CLDR. Since there is a compile-time exception raised if there are any unknown locales this function should always return an empty list.","ref":"Plausible.Cldr.html#unknown_locale_names/0","title":"Plausible.Cldr.unknown_locale_names/0","type":"function"},{"doc":"See Cldr.validate_calendar/1 .","ref":"Plausible.Cldr.html#validate_calendar/1","title":"Plausible.Cldr.validate_calendar/1","type":"function"},{"doc":"See Cldr.validate_currency/1 .","ref":"Plausible.Cldr.html#validate_currency/1","title":"Plausible.Cldr.validate_currency/1","type":"function"},{"doc":"Normalise and validate a locale name. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 Returns {:ok, language_tag} {:error, reason} Notes See rfc5646 for the specification of a language tag. Examples iex> Plausible.Cldr . validate_locale ( :en ) { :ok , % Cldr.LanguageTag { backend : Plausible.Cldr , canonical_locale_name : "en" , cldr_locale_name : :en , extensions : %{ } , gettext_locale_name : "en" , language : "en" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :en , requested_locale_name : "en" , script : :Latn , territory : :US , transform : %{ } , language_variants : [ ] } } iex> Plausible.Cldr . validate_locale Plausible.Cldr . default_locale ( ) { :ok , % Cldr.LanguageTag { backend : Plausible.Cldr , canonical_locale_name : "en-001" , cldr_locale_name : :"en-001" , extensions : %{ } , gettext_locale_name : "en" , language : "en" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :en , requested_locale_name : "en-001" , script : :Latn , territory : :"001" , transform : %{ } , language_variants : [ ] } } iex> Plausible.Cldr . validate_locale ( "zzz" ) { :error , { Cldr.InvalidLanguageError , "The language \\" zzz \\" is invalid" } }","ref":"Plausible.Cldr.html#validate_locale/1","title":"Plausible.Cldr.validate_locale/1","type":"function"},{"doc":"See Cldr.validate_number_system/1 .","ref":"Plausible.Cldr.html#validate_number_system/1","title":"Plausible.Cldr.validate_number_system/1","type":"function"},{"doc":"Normalise and validate a number system type. Arguments number_system_type is any number system type returned by Cldr.known_number_system_types/1 Returns {:ok, normalized_number_system_type} or {:error, {exception, message}} Examples iex> Plausible.Cldr . validate_number_system_type :default { :ok , :default } iex> Plausible.Cldr . validate_number_system_type :traditional { :ok , :traditional } iex> Plausible.Cldr . validate_number_system_type :latn { :error , { Cldr.UnknownNumberSystemTypeError , "The number system type :latn is unknown" } } iex> Plausible.Cldr . validate_number_system_type "bork" { :error , { Cldr.UnknownNumberSystemTypeError , "The number system type \\" bork \\" is invalid" } }","ref":"Plausible.Cldr.html#validate_number_system_type/1","title":"Plausible.Cldr.validate_number_system_type/1","type":"function"},{"doc":"See Cldr.validate_territory/1 .","ref":"Plausible.Cldr.html#validate_territory/1","title":"Plausible.Cldr.validate_territory/1","type":"function"},{"doc":"Execute a function with a locale ensuring that the current locale is restored after the function. Arguments locale is any valid locale name returned by Cldr.known_locale_names/1 . fun is any 0-arity function or function capture. Returns The value returned by the function fun/0 or {:error, {exception, reason}} if the locale is invalid or raises an exception if the current locale cannot be identified.","ref":"Plausible.Cldr.html#with_locale/2","title":"Plausible.Cldr.with_locale/2","type":"function"},{"doc":"Parses HTTP Accept-Language header values as defined in rfc2616 . The Accept-Language request-header field is similar to Accept, but restricts the set of natural languages that are preferred as a response to the request. Language tags function are provided in Cldr.LanguageTag . The format of an Accept-Language header is as follows in ABNF format: Accept - Language = "Accept-Language" ":" 1 #( language-range [ ";" "q" "=" qvalue ] ) language - range = ( ( 1 * 8 ALPHA * ( "-" 1 * 8 ALPHA ) ) | "*" ) Each language-range MAY be given an associated quality value which represents an estimate of the user's preference for the languages specified by that range. The quality value defaults to "q=1". For example, Accept - Language : da , en - gb ; q = 0.8 , en ; q = 0.7 would mean: "I prefer Danish, but will accept British English and other types of English."","ref":"Plausible.Cldr.AcceptLanguage.html","title":"Plausible.Cldr.AcceptLanguage","type":"module"},{"doc":"Parse an Accept-Language string and return the best match for a configured Cldr locale. Arguments accept_langauge is a string representing an accept language header Returns {:ok, language_tag} or {:error, reason} Examples iex> Plausible.Cldr.AcceptLanguage . best_match ( "da;q=0.1,zh-TW;q=0.3" , TestBackend.Cldr ) { :ok , % Cldr.LanguageTag { backend : TestBackend.Cldr , canonical_locale_name : "zh-TW" , cldr_locale_name : :"zh-Hant" , language_subtags : [ ] , extensions : %{ } , gettext_locale_name : nil , language : "zh" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :"zh-Hant" , requested_locale_name : "zh-TW" , script : :Hant , territory : :TW , transform : %{ } , language_variants : [ ] } } iex> Plausible.Cldr.AcceptLanguage . best_match ( "da;q=0.1,zh-TW;q=0.3" , TestBackend.Cldr ) { :ok , % Cldr.LanguageTag { backend : TestBackend.Cldr , canonical_locale_name : "zh-TW" , cldr_locale_name : :"zh-Hant" , language_subtags : [ ] , extensions : %{ } , gettext_locale_name : nil , language : "zh" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :"zh-Hant" , requested_locale_name : "zh-TW" , script : :Hant , territory : :TW , transform : %{ } , language_variants : [ ] } } iex> Plausible.Cldr.AcceptLanguage . best_match ( "xx,yy;q=0.3" ) { :error , { Cldr.NoMatchingLocale , "No configured locale could be matched to \\" xx,yy;q=0.3 \\" " } } iex> Plausible.Cldr.AcceptLanguage . best_match ( "invalid_tag" ) { :error , { Cldr.LanguageTag.ParseError , "Expected a BCP47 language tag. Could not parse the remaining \\" g \\" starting at position 11" } }","ref":"Plausible.Cldr.AcceptLanguage.html#best_match/1","title":"Plausible.Cldr.AcceptLanguage.best_match/1","type":"function"},{"doc":"Parses an Accept-Language header value in its string or tokenized form to return a tuple of the form {:ok, [{quality, %Cldr.LanguageTag{}}, ...]} sorted by quality. Arguments accept-language is any string in the format defined by rfc2616 backend is any module that includes use Cldr and therefore is a Cldr backend module Returns {:ok, [{quality, language_tag}, ...]} or {:error, {Cldr.AcceptLanguageError, String.t}} If at least one valid language tag is found but errors are also detected on one more more tags, an {ok, list} tuple is returned wuth an error tuple for each invalid tag added at the end of the list. Example iex> Cldr.AcceptLanguage . parse ( "da,zh-TW;q=0.3" , TestBackend.Cldr ) { :ok , [ { 1.0 , % Cldr.LanguageTag { backend : TestBackend.Cldr , canonical_locale_name : "da" , cldr_locale_name : :da , language_subtags : [ ] , extensions : %{ } , gettext_locale_name : nil , language : "da" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :da , requested_locale_name : "da" , script : :Latn , territory : :DK , transform : %{ } , language_variants : [ ] } } , { 0.3 , % Cldr.LanguageTag { backend : TestBackend.Cldr , canonical_locale_name : "zh-TW" , cldr_locale_name : :"zh-Hant" , language_subtags : [ ] , extensions : %{ } , gettext_locale_name : nil , language : "zh" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :"zh-Hant" , requested_locale_name : "zh-TW" , script : :Hant , territory : :TW , transform : %{ } , language_variants : [ ] } } ] } iex> Plausible.Cldr.AcceptLanguage . parse ( "invalid_tag" ) { :error , { Cldr.LanguageTag.ParseError , "Expected a BCP47 language tag. Could not parse the remaining \\" g \\" starting at position 11" } } iex> Plausible.Cldr.AcceptLanguage . parse ( "da,zh-TW;q=0.3,invalid_tag" ) { :ok , [ { 1.0 , % Cldr.LanguageTag { backend : TestBackend.Cldr , canonical_locale_name : "da" , cldr_locale_name : :da , language_subtags : [ ] , extensions : %{ } , gettext_locale_name : nil , language : "da" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :da , requested_locale_name : "da" , script : :Latn , territory : :DK , transform : %{ } , language_variants : [ ] } } , { 0.3 , % Cldr.LanguageTag { backend : TestBackend.Cldr , canonical_locale_name : "zh-TW" , cldr_locale_name : :"zh-Hant" , language_subtags : [ ] , extensions : %{ } , gettext_locale_name : nil , language : "zh" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :"zh-Hant" , requested_locale_name : "zh-TW" , script : :Hant , territory : :TW , transform : %{ } , language_variants : [ ] } } , { :error , { Cldr.LanguageTag.ParseError , "Expected a BCP47 language tag. Could not parse the remaining \\" g \\" starting at position 11" } } ] }","ref":"Plausible.Cldr.AcceptLanguage.html#parse/1","title":"Plausible.Cldr.AcceptLanguage.parse/1","type":"function"},{"doc":"Parses an Accept-Language header value in its string or tokenized form to produce a list of tuples of the form [{quality, %Cldr.LanguageTag{}}, ...] sorted by quality in descending order. Arguments accept-language is any string in the format defined by rfc2616 Returns {:ok, [{quality, language_tag}, ...]} or raises a Cldr.AcceptLanguageError exception If at least one valid language tag is found but errors are also detected on one more more tags, an {ok, list} tuple is returned wuth an error tuple for each invalid tag added at the end of the list. Example iex> Plausible.Cldr.AcceptLanguage . parse! ( "da,zh-TW;q=0.3" ) [ { 1.0 , % Cldr.LanguageTag { backend : TestBackend.Cldr , canonical_locale_name : "da" , cldr_locale_name : :da , language_subtags : [ ] , extensions : %{ } , gettext_locale_name : nil , language : "da" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :da , requested_locale_name : "da" , script : :Latn , territory : :DK , transform : %{ } , language_variants : [ ] } } , { 0.3 , % Cldr.LanguageTag { backend : TestBackend.Cldr , canonical_locale_name : "zh-TW" , cldr_locale_name : :"zh-Hant" , language_subtags : [ ] , extensions : %{ } , gettext_locale_name : nil , language : "zh" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :"zh-Hant" , requested_locale_name : "zh-TW" , script : :Hant , territory : :TW , transform : %{ } , language_variants : [ ] } } ] Plausible.Cldr.AcceptLanguage . parse! "invalid_tag" ** (Cldr.AcceptLanguageError) "Expected a BCP47 language tag. Could not parse the remaining "g" starting at position 11 (ex_cldr) lib/cldr/accept_language.ex:304: Cldr.AcceptLanguage.parse!/1 iex> Plausible.Cldr.AcceptLanguage . parse! ( "da,zh-TW;q=0.3,invalid_tag" ) [ { 1.0 , % Cldr.LanguageTag { backend : TestBackend.Cldr , canonical_locale_name : "da" , cldr_locale_name : :da , language_subtags : [ ] , extensions : %{ } , gettext_locale_name : nil , language : "da" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :da , requested_locale_name : "da" , script : :Latn , territory : :DK , transform : %{ } , language_variants : [ ] } } , { 0.3 , % Cldr.LanguageTag { backend : TestBackend.Cldr , canonical_locale_name : "zh-TW" , cldr_locale_name : :"zh-Hant" , language_subtags : [ ] , extensions : %{ } , gettext_locale_name : nil , language : "zh" , locale : %{ } , private_use : [ ] , rbnf_locale_name : :"zh-Hant" , requested_locale_name : "zh-TW" , script : :Hant , territory : :TW , transform : %{ } , language_variants : [ ] } } , { :error , { Cldr.LanguageTag.ParseError , "Expected a BCP47 language tag. Could not parse the remaining \\" g \\" starting at position 11" } } ]","ref":"Plausible.Cldr.AcceptLanguage.html#parse!/1","title":"Plausible.Cldr.AcceptLanguage.parse!/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Currency.html","title":"Plausible.Cldr.Currency","type":"module"},{"doc":"Returns a map of the metadata for all currencies for a given locale. Arguments locale is any valid locale name returned by MyApp.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by MyApp.Cldr.Locale.new!/1 currency_status is :all , :current , :historic , unannotated or :tender ; or a list of one or more status. The default is :all . See Cldr.Currency.currency_filter/2 . Returns {:ok, currency_map} or {:error, {exception, reason}} Example MyApp.Cldr.Currency.currencies_for_locale "en" => {:ok, %{ FJD : % Cldr.Currency { cash_digits : 2 , cash_rounding : 0 , code : "FJD" , count : %{ one : "Fijian dollar" , other : "Fijian dollars" } , digits : 2 , from : nil , iso_digits : 2 , name : "Fijian Dollar" , narrow_symbol : "$" , rounding : 0 , symbol : "FJD" , tender : true , to : nil } , SUR : % Cldr.Currency { cash_digits : 2 , cash_rounding : 0 , code : "SUR" , count : %{ one : "Soviet rouble" , other : "Soviet roubles" } , digits : 2 , from : nil , iso_digits : nil , name : "Soviet Rouble" , narrow_symbol : nil , rounding : 0 , symbol : "SUR" , tender : true , to : nil } , ... } }","ref":"Plausible.Cldr.Currency.html#currencies_for_locale/3","title":"Plausible.Cldr.Currency.currencies_for_locale/3","type":"function"},{"doc":"Returns a map of the metadata for all currencies for a given locale and raises on error. Arguments locale is any valid locale name returned by MyApp.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by MyApp.Cldr.Locale.new!/1 currency_status is :all , :current , :historic , unannotated or :tender ; or a list of one or more status. The default is :all . See Cldr.Currency.currency_filter/2 . Returns {:ok, currency_map} or raises an exception Example MyApp.Cldr.Currency.currencies_for_locale! "en" => %{ FJD : % Cldr.Currency { cash_digits : 2 , cash_rounding : 0 , code : "FJD" , count : %{ one : "Fijian dollar" , other : "Fijian dollars" } , digits : 2 , from : nil , iso_digits : 2 , name : "Fijian Dollar" , narrow_symbol : "$" , rounding : 0 , symbol : "FJD" , tender : true , to : nil } , SUR : % Cldr.Currency { cash_digits : 2 , cash_rounding : 0 , code : "SUR" , count : %{ one : "Soviet rouble" , other : "Soviet roubles" } , digits : 2 , from : nil , iso_digits : nil , name : "Soviet Rouble" , narrow_symbol : nil , rounding : 0 , symbol : "SUR" , tender : true , to : nil } , ... }","ref":"Plausible.Cldr.Currency.html#currencies_for_locale!/3","title":"Plausible.Cldr.Currency.currencies_for_locale!/3","type":"function"},{"doc":"Returns the currency metadata for the requested currency code. Arguments currency_or_currency_code is a binary or atom representation of an ISO 4217 currency code, or a %Cldr.Currency{} struct. Options :locale is any valid locale name returned by Cldr.known_locale_names/1 or a Cldr.LanguageTag struct returned by Cldr.Locale.new!/2 Returns A {:ok, currency} or {:error, {exception, reason}} Examples iex> Plausible.Cldr.Currency . currency_for_code ( "AUD" ) { :ok , % Cldr.Currency { cash_digits : 2 , cash_rounding : 0 , code : "AUD" , count : %{ one : "Australian dollar" , other : "Australian dollars" } , digits : 2 , iso_digits : 2 , name : "Australian Dollar" , narrow_symbol : "$" , rounding : 0 , symbol : "A$" , tender : true } } iex> Plausible.Cldr.Currency . currency_for_code ( "THB" ) { :ok , % Cldr.Currency { cash_digits : 2 , cash_rounding : 0 , code : "THB" , count : %{ one : "Thai baht" , other : "Thai baht" } , digits : 2 , iso_digits : 2 , name : "Thai Baht" , narrow_symbol : "฿" , rounding : 0 , symbol : "THB" , tender : true } }","ref":"Plausible.Cldr.Currency.html#currency_for_code/2","title":"Plausible.Cldr.Currency.currency_for_code/2","type":"function"},{"doc":"Returns the currency metadata for the requested currency code. Arguments currency_or_currency_code is a binary or atom representation of an ISO 4217 currency code, or a %Cldr.Currency{} struct. Options :locale is any valid locale name returned by Cldr.known_locale_names/1 or a Cldr.LanguageTag struct returned by Cldr.Locale.new!/2 Returns A t:Cldr.Current.t/0 or raises an exception Examples iex> Plausible.Cldr.Currency . currency_for_code! ( "AUD" ) % Cldr.Currency { cash_digits : 2 , cash_rounding : 0 , code : "AUD" , count : %{ one : "Australian dollar" , other : "Australian dollars" } , digits : 2 , iso_digits : 2 , name : "Australian Dollar" , narrow_symbol : "$" , rounding : 0 , symbol : "A$" , tender : true } iex> Plausible.Cldr.Currency . currency_for_code! ( "THB" ) % Cldr.Currency { cash_digits : 2 , cash_rounding : 0 , code : "THB" , count : %{ one : "Thai baht" , other : "Thai baht" } , digits : 2 , iso_digits : 2 , name : "Thai Baht" , narrow_symbol : "฿" , rounding : 0 , symbol : "THB" , tender : true }","ref":"Plausible.Cldr.Currency.html#currency_for_code!/2","title":"Plausible.Cldr.Currency.currency_for_code!/2","type":"function"},{"doc":"Returns the effective currency for a given locale Arguments locale is a Cldr.LanguageTag struct returned by Cldr.Locale.new!/2 Returns A ISO 4217 currency code as an upcased atom Examples iex> { :ok , locale } = Plausible.Cldr . validate_locale "en" iex> Plausible.Cldr.Currency . currency_from_locale locale :USD iex> { :ok , locale } = Plausible.Cldr . validate_locale "en-AU" iex> Plausible.Cldr.Currency . currency_from_locale locale :AUD iex> Plausible.Cldr.Currency . currency_from_locale "en-GB" :GBP","ref":"Plausible.Cldr.Currency.html#currency_from_locale/1","title":"Plausible.Cldr.Currency.currency_from_locale/1","type":"function"},{"doc":"Returns a list of historic and the current currency for a given locale. Arguments locale is any valid locale name returned by MyApp.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by MyApp.Cldr.Locale.new!/1 Example iex> MyApp.Cldr.Currency . currency_history_for_locale "en" { :ok , %{ USD : %{ from : ~D[1792-01-01] , to : nil } , USN : %{ tender : false } , USS : %{ from : nil , tender : false , to : ~D[2014-03-01] } } }","ref":"Plausible.Cldr.Currency.html#currency_history_for_locale/1","title":"Plausible.Cldr.Currency.currency_history_for_locale/1","type":"function"},{"doc":"Returns a map that matches a currency string to a currency code. A currency string is a localised name or symbol representing a currency in a locale-specific manner. Arguments locale is any valid locale name returned by MyApp.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by MyApp.Cldr.Locale.new!/1 currency_status is :all , :current , :historic , unannotated or :tender ; or a list of one or more status. The default is :all . See Cldr.Currency.currency_filter/2 . Returns {:ok, currency_string_map} or {:error, {exception, reason}} Example MyApp.Cldr.Currency . currency_strings "en" => { :ok , %{ "mexican silver pesos" => :MXP , "sudanese dinar" => :SDD , "bad" => :BAD , "rsd" => :RSD , "swazi lilangeni" => :SZL , "zairean new zaire" => :ZRN , "guyanaese dollars" => :GYD , "equatorial guinean ekwele" => :GQE , ... } }","ref":"Plausible.Cldr.Currency.html#currency_strings/3","title":"Plausible.Cldr.Currency.currency_strings/3","type":"function"},{"doc":"Returns a map that matches a currency string to a currency code or raises an exception. A currency string is a localised name or symbol representing a currency in a locale-specific manner. Arguments locale is any valid locale name returned by MyApp.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by MyApp.Cldr.Locale.new!/1 currency_status is :all , :current , :historic , unannotated or :tender ; or a list of one or more status. The default is :all . See Cldr.Currency.currency_filter/2 . Returns {:ok, currency_string_map} or raises an exception Example MyApp.Cldr.Currency . currency_strings! "en" => %{ "mexican silver pesos" => :MXP , "sudanese dinar" => :SDD , "bad" => :BAD , "rsd" => :RSD , "swazi lilangeni" => :SZL , "zairean new zaire" => :ZRN , "guyanaese dollars" => :GYD , "equatorial guinean ekwele" => :GQE , ... }","ref":"Plausible.Cldr.Currency.html#currency_strings!/3","title":"Plausible.Cldr.Currency.currency_strings!/3","type":"function"},{"doc":"Returns the current currency for a given locale. This function does not consider the U extenion parameters cu or rg . It is recommended to us Cldr.Currency.currency_from_locale/1 in most circumstances. Arguments locale is any valid locale name returned by MyApp.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by MyApp.Cldr.Locale.new!/1 Example iex> MyApp.Cldr.Currency . current_currency_from_locale "en" :USD iex> MyApp.Cldr.Currency . current_currency_from_locale "en-AU" :AUD","ref":"Plausible.Cldr.Currency.html#current_currency_from_locale/1","title":"Plausible.Cldr.Currency.current_currency_from_locale/1","type":"function"},{"doc":"Returns a mapping from a territory code to its current currency code. If a territory has no current currency (like Antartica, territory code :AQ ) then no mapping is returned for that territory. Returns A map of {territory_code => Cldr.Currency.t} Example iex> Plausible.Cldr.Currency . current_territory_currencies ( )","ref":"Plausible.Cldr.Currency.html#current_territory_currencies/0","title":"Plausible.Cldr.Currency.current_territory_currencies/0","type":"function"},{"doc":"See Plausible.Cldr.Currency.known_currency_codes/0 .","ref":"Plausible.Cldr.Currency.html#known_currencies/0","title":"Plausible.Cldr.Currency.known_currencies/0","type":"function"},{"doc":"See Plausible.Cldr.Currency.known_currency_code?/1 .","ref":"Plausible.Cldr.Currency.html#known_currency?/1","title":"Plausible.Cldr.Currency.known_currency?/1","type":"function"},{"doc":"Returns a 2-tuple indicating if the supplied currency code is known. Arguments currency_code is a binary or atom representing an ISO4217 currency code Returns {:ok, currency_code} or {:error, {exception, reason}} Examples iex> Plausible.Cldr.Currency . known_currency_code "AUD" { :ok , :AUD } iex> Plausible.Cldr.Currency . known_currency_code "GGG" { :error , { Cldr.UnknownCurrencyError , "The currency \\" GGG \\" is invalid" } }","ref":"Plausible.Cldr.Currency.html#known_currency_code/1","title":"Plausible.Cldr.Currency.known_currency_code/1","type":"function"},{"doc":"Returns a boolean indicating if the supplied currency code is known. Arguments currency_code is a binary or atom representing an ISO4217 currency code Returns true or false Examples iex> Plausible.Cldr.Currency . known_currency_code? "AUD" true iex> Plausible.Cldr.Currency . known_currency_code? "GGG" false iex> Plausible.Cldr.Currency . known_currency_code? :XCV false","ref":"Plausible.Cldr.Currency.html#known_currency_code?/1","title":"Plausible.Cldr.Currency.known_currency_code?/1","type":"function"},{"doc":"Returns a list of all known currency codes. Example iex> Plausible.Cldr.Currency . known_currency_codes","ref":"Plausible.Cldr.Currency.html#known_currency_codes/0","title":"Plausible.Cldr.Currency.known_currency_codes/0","type":"function"},{"doc":"Returns a Currency struct created from the arguments. Arguments currency is a private use currency code in a format defined by ISO4217 which is X followed by two alphanumeric characters. options is a map of options representing the optional elements of the Cldr.Currency.t struct. Options :name is the name of the currency. Required. :digits is the precision of the currency. Required. :symbol is the currency symbol. Optional. :narrow_symbol is an alternative narrow symbol. Optional. :round_nearest is the rounding precision such as 0.05 . Optional. :alt_code is an alternative currency code for application use. :cash_digits is the precision of the currency when used as cash. Optional. :cash_rounding_nearest is the rounding precision when used as cash such as 0.05 . Optional. Returns {:ok, Cldr.Currency.t} or {:error, {exception, message}} Example iex> Plausible.Cldr.Currency . new ( :XAE , name : "Custom Name" , digits : 0 ) { :ok , % Cldr.Currency { alt_code : :XAE , cash_digits : 0 , cash_rounding : nil , code : :XAE , count : %{ other : "Custom Name" } , digits : 0 , from : nil , iso_digits : 0 , name : "Custom Name" , narrow_symbol : nil , rounding : 0 , symbol : "XAE" , tender : false , to : nil } } iex> MyApp.Cldr.Currency . new ( :XAH , name : "Custom Name" ) { :error , "Required options are missing. Required options are [:name, :digits]" } iex> Plausible.Cldr.Currency . new ( :XAE , name : "XAE" , digits : 0 ) { :error , { Cldr.CurrencyAlreadyDefined , "Currency :XAE is already defined." } }","ref":"Plausible.Cldr.Currency.html#new/2","title":"Plausible.Cldr.Currency.new/2","type":"function"},{"doc":"Returns the appropriate currency display name for the currency , based on the plural rules in effect for the locale . Arguments number is an integer, float or Decimal currency is any currency returned by Cldr.Currency.known_currencies/0 options is a keyword list of options Options locale is any valid locale name returned by MyApp.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by MyApp.Cldr.Locale.new!/1 . The default is Plausible.Cldr.get_locale/0 Returns {:ok, plural_string} or {:error, {exception, message}} Examples iex> Plausible.Cldr.Currency . pluralize 1 , :USD { :ok , "US dollar" } iex> Plausible.Cldr.Currency . pluralize 3 , :USD { :ok , "US dollars" } iex> Plausible.Cldr.Currency . pluralize 12 , :USD , locale : "zh" { :ok , "美元" } iex> Plausible.Cldr.Currency . pluralize 12 , :USD , locale : "fr" { :ok , "dollars des États-Unis" } iex> Plausible.Cldr.Currency . pluralize 1 , :USD , locale : "fr" { :ok , "dollar des États-Unis" }","ref":"Plausible.Cldr.Currency.html#pluralize/3","title":"Plausible.Cldr.Currency.pluralize/3","type":"function"},{"doc":"Returns the strings associated with a currency in a given locale. Arguments currency is an ISO4217 currency code locale is any valid locale name returned by MyApp.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by MyApp.Cldr.Locale.new!/1 Returns A list of strings or {:error, {exception, reason}} Example iex> MyApp.Cldr.Currency . strings_for_currency :AUD , "en" [ "a$" , "australian dollars" , "aud" , "australian dollar" ]","ref":"Plausible.Cldr.Currency.html#strings_for_currency/2","title":"Plausible.Cldr.Currency.strings_for_currency/2","type":"function"},{"doc":"Backend module that provides functions to define new locales and display human-readable locale names for presentation purposes.","ref":"Plausible.Cldr.Locale.html","title":"Plausible.Cldr.Locale","type":"module"},{"doc":"Returns the list of fallback locale names, starting with the provided locale name. Fallbacks are a list of locate names which can be used to resolve translation or other localization data if such localised data does not exist for this specific locale. After locale-specific fallbacks are determined, the the default locale and its fallbacks are added to the chain. Arguments locale_name is any locale name returned by Plausible.Cldr.known_locale_names/0 Returns {:ok, list_of_locale_names} or {:error, {exception, reason}} Examples In these examples the default locale is :"en-001" . iex> Plausible.Cldr.Locale . fallback_locale_names ( :"fr-CA" ) { :ok , [ :"fr-CA" , :fr , :"en-001" , :en ] } # Fallbacks are typically formed by progressively # stripping variant, territory and script from the # given locale name. But not always - there are # certain fallbacks that take a different path. iex> Plausible.Cldr.Locale . fallback_locale_names ( :nb ) { :ok , [ :nb , :no , :"en-001" , :en ] }","ref":"Plausible.Cldr.Locale.html#fallback_locale_names/1","title":"Plausible.Cldr.Locale.fallback_locale_names/1","type":"function"},{"doc":"Returns the list of fallback locales, starting with the provided locale name. Fallbacks are a list of locate names which can be used to resolve translation or other localization data if such localised data does not exist for this specific locale. After locale-specific fallbacks are determined, the the default locale and its fallbacks are added to the chain. Arguments locale_name is any locale name returned by Plausible.Cldr.known_locale_names/0 Returns {:ok, list_of_locales} or {:error, {exception, reason}} Examples In these examples the default locale is :"en-001" . Plausible.Cldr.Locale . fallback_locales ( :"fr-CA" ) => { :ok , [ # Cldr.LanguageTag < fr - CA [ validated ] > , # Cldr.LanguageTag < fr [ validated ] > , # Cldr.LanguageTag < en [ validated ] > ] } # Fallbacks are typically formed by progressively # stripping variant, territory and script from the # given locale name. But not always - there are # certain fallbacks that take a different path. Plausible.Cldr.Locale . fallback_locales ( :nb ) ) => { :ok , [ # Cldr.LanguageTag < nb [ validated ] > , # Cldr.LanguageTag < no [ validated ] > , # Cldr.LanguageTag < en [ validated ] > ] }","ref":"Plausible.Cldr.Locale.html#fallback_locales/1","title":"Plausible.Cldr.Locale.fallback_locales/1","type":"function"},{"doc":"Returns the "best fit" locale for a given territory. Using the population percentage data from CLDR, the language most commonly spoken in the given territory is used to form a locale name which is then validated against the given backend. First a territory-specific locale is validated and if that fails, the base language only is validate. For example, if the territory is AU then then the language most spoken is "en". First, the locale "en-AU" is validated and if that fails, "en" is validated. Arguments territory is any ISO 3166 Alpha-2 territory code that can be validated by Cldr.validate_territory/1 Returns {:ok, language_tag} or {:error, {exception, reason}} Examples iex> Plausible.Cldr.Locale.locale_for_territory(:AU) Elixir.Plausible.Cldr.validate_locale(:"en-AU") iex> Plausible.Cldr.Locale.locale_for_territory(:US) Elixir.Plausible.Cldr.validate_locale(:"en-US") iex> Plausible.Cldr.Locale.locale_for_territory(:ZZ) {:error, {Cldr.UnknownTerritoryError, "The territory :ZZ is unknown"}}","ref":"Plausible.Cldr.Locale.html#locale_for_territory/1","title":"Plausible.Cldr.Locale.locale_for_territory/1","type":"function"},{"doc":"Returns a "best fit" locale for a host name. Arguments host is any valid host name options is a keyword list of options. The default is [] . Options :tlds is a list of territory codes as upper-cased atoms that are to be considered as top-level domains. See Cldr.Locale.locale_from_host/2 for the default list. Returns {:ok, langauge_tag} or {:error, {exception, reason}} Notes Certain top-level domains have become associated with content underlated to the territory for who the domain is registered. Therefore Google (and perhaps others) do not associate these TLDs as belonging to the territory but rather are considered generic top-level domain names. Examples iex> Plausible.Cldr.Locale . locale_from_host "a.b.com.au" Elixir.Plausible.Cldr . validate_locale ( :"en-AU" ) iex> Plausible.Cldr.Locale . locale_from_host ( "a.b.com.tv" ) { :error , { Cldr.UnknownLocaleError , "No locale was identified for territory \\" tv \\" " } } iex> Plausible.Cldr.Locale . locale_from_host ( "a.b.com" ) { :error , { Cldr.UnknownLocaleError , "No locale was identified for territory \\" com \\" " } }","ref":"Plausible.Cldr.Locale.html#locale_from_host/2","title":"Plausible.Cldr.Locale.locale_from_host/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Locale.html#new/1","title":"Plausible.Cldr.Locale.new/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Locale.html#new!/1","title":"Plausible.Cldr.Locale.new!/1","type":"function"},{"doc":"Returns the last segment of a host that might be a territory. Arguments host is any valid host name Returns {:ok, territory} or {:error, {exception, reason}} Examples iex> Cldr.Locale . territory_from_host ( "a.b.com.au" ) { :ok , :AU } iex> Cldr.Locale . territory_from_host ( "a.b.com" ) { :error , { Cldr.UnknownLocaleError , "No locale was identified for territory \\" com \\" " } }","ref":"Plausible.Cldr.Locale.html#territory_from_host/1","title":"Plausible.Cldr.Locale.territory_from_host/1","type":"function"},{"doc":"Returns the territory from a language tag or locale name. Arguments locale is any language tag returned by Plausible.Cldr.Locale.new/1 or a locale name in the list returned by Plausible.Cldr.known_locale_names/0 Returns A territory code as an atom Examples iex> Plausible.Cldr.Locale . territory_from_locale "en-US" :US iex> Plausible.Cldr.Locale . territory_from_locale "en-US-u-rg-GBzzzz" :GB","ref":"Plausible.Cldr.Locale.html#territory_from_locale/1","title":"Plausible.Cldr.Locale.territory_from_locale/1","type":"function"},{"doc":"Returns the time zone from a language tag or locale name. Arguments locale is any language tag returned by Plausible.Cldr.Locale.new/1 or a locale name in the list returned by Plausible.Cldr.known_locale_names/0 Returns A time zone ID as a string or :error if no time zone can be determined Examples iex> Plausible.Cldr.Locale . timezone_from_locale "en-US-u-tz-ausyd" "Australia/Sydney"","ref":"Plausible.Cldr.Locale.html#timezone_from_locale/1","title":"Plausible.Cldr.Locale.timezone_from_locale/1","type":"function"},{"doc":"Formats numbers and currencies based upon CLDR's decimal formats specification. The format specification is documentated in Unicode TR35 . There are several classes of formatting including non-scientific, scientific, rules based (for spelling and ordinal formats), compact formats that display 1k rather than 1,000 and so on. See Cldr.Number.to_string/2 for specific formatting options. Non-Scientific Notation Formatting The following description applies to formats that do not use scientific notation or significant digits: If the number of actual integer digits exceeds the maximum integer digits, then only the least significant digits are shown. For example, 1997 is formatted as "97" if the maximum integer digits is set to 2. If the number of actual integer digits is less than the minimum integer digits, then leading zeros are added. For example, 1997 is formatted as "01997" if the minimum integer digits is set to 5. If the number of actual fraction digits exceeds the maximum fraction digits, then half-even rounding it performed to the maximum fraction digits. For example, 0.125 is formatted as "0.12" if the maximum fraction digits is 2. This behavior can be changed by specifying a rounding increment and a rounding mode. If the number of actual fraction digits is less than the minimum fraction digits, then trailing zeros are added. For example, 0.125 is formatted as "0.1250" if the minimum fraction digits is set to 4. Trailing fractional zeros are not displayed if they occur j positions after the decimal, where j is less than the maximum fraction digits. For example, 0.10004 is formatted as "0.1" if the maximum fraction digits is four or less. Scientific Notation Formatting Numbers in scientific notation are expressed as the product of a mantissa and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3. The mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0), but it need not be. In a pattern, the exponent character immediately followed by one or more digit characters indicates scientific notation. Example: "0.###E0" formats the number 1234 as "1.234E3". The number of digit characters after the exponent character gives the minimum exponent digit count. There is no maximum. Negative exponents are formatted using the localized minus sign, not the prefix and suffix from the pattern. This allows patterns such as "0.###E0 m/s". To prefix positive exponents with a localized plus sign, specify '+' between the exponent and the digits: "0.###E+0" will produce formats "1E+1", "1E+0", "1E-1", and so on. (In localized patterns, use the localized plus sign rather than '+'.) The minimum number of integer digits is achieved by adjusting the exponent. Example: 0.00123 formatted with "00.###E0" yields "12.3E-4". This only happens if there is no maximum number of integer digits. If there is a maximum, then the minimum number of integer digits is fixed at one. The maximum number of integer digits, if present, specifies the exponent grouping. The most common use of this is to generate engineering notation, in which the exponent is a multiple of three, for example, "##0.###E0". The number 12345 is formatted using "##0.####E0" as "12.345E3". When using scientific notation, the formatter controls the digit counts using significant digits logic. The maximum number of significant digits limits the total number of integer and fraction digits that will be shown in the mantissa; it does not affect parsing. For example, 12345 formatted with "##0.##E0" is "12.3E3". Exponential patterns may not contain grouping separators. Significant Digits There are two ways of controlling how many digits are shows: (a) significant digits counts, or (b) integer and fraction digit counts. Integer and fraction digit counts are described above. When a formatter is using significant digits counts, it uses however many integer and fraction digits are required to display the specified number of significant digits. It may ignore min/max integer/fraction digits, or it may use them to the extent possible.","ref":"Plausible.Cldr.Number.html","title":"Plausible.Cldr.Number","type":"module"},{"doc":"Parse a string locale-aware manner and return a number. Arguments string is any String.t options is a keyword list of options Options :number is one of :integer , :float , :decimal or nil . The default is nil meaning that the type auto-detected as either an integer or a float . :locale is any locale returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag.t . The default is Plausible.Cldr.get_locale/0 . Returns A number of the requested or default type or {:error, {exception, error}} if no number could be determined Notes This function parses a string to return a number but in a locale-aware manner. It will normalise grouping characters and decimal separators, different forms of the + and - symbols that appear in Unicode and strips any _ characters that might be used for formatting in a string. It then parses the number using the Elixir standard library functions. Examples iex> Plausible.Cldr.Number . parse ( "+1.000,34" , locale : "de" ) { :ok , 1000.34 } iex> Plausible.Cldr.Number . parse ( "-1_000_000.34" ) { :ok , - 1000000.34 } iex> Plausible.Cldr.Number . parse ( "1.000" , locale : "de" , number : :integer ) { :ok , 1000 } iex> Plausible.Cldr.Number . parse ( "+1.000,34" , locale : "de" , number : :integer ) { :error , { Cldr.Number.ParseError , "The string \\" +1.000,34 \\" could not be parsed as a number" } }","ref":"Plausible.Cldr.Number.html#parse/2","title":"Plausible.Cldr.Number.parse/2","type":"function"},{"doc":"Resolve curencies from strings within a list. Arguments list is any list in which currency names and symbols are expected options is a keyword list of options Options :locale is any valid locale returned by Cldr.known_locale_names/1 or a Cldr.LanguageTag struct returned by Cldr.Locale.new!/2 The default is Plausible.Cldr.get_locale() :only is an atom or list of atoms representing the currencies or currency types to be considered for a match. The equates to a list of acceptable currencies for parsing. See the notes below for currency types. :except is an atom or list of atoms representing the currencies or currency types to be not considered for a match. This equates to a list of unacceptable currencies for parsing. See the notes below for currency types. :fuzzy is a float greater than 0.0 and less than or equal to 1.0 which is used as input to String.jaro_distance/2 to determine is the provided currency string is close enough to a known currency string for it to identify definitively a currency code. It is recommended to use numbers greater than 0.8 in order to reduce false positives. Notes The :only and :except options accept a list of currency codes and/or currency types. The following types are recognised. If both :only and :except are specified, the :except entries take priority - that means any entries in :except are removed from the :only entries. :all , the default, considers all currencies :current considers those currencies that have a :to date of nil and which also is a known ISO4217 currency :historic is the opposite of :current :tender considers currencies that are legal tender :unannotated considers currencies that don't have "(some string)" in their names. These are usually financial instruments. Examples iex> Plausible.Cldr.Number . scan ( "100 US dollars" ) ...> |> Plausible.Cldr.Number . resolve_currencies [ 100 , :USD ] iex> Plausible.Cldr.Number . scan ( "100 eurosports" ) ...> |> Plausible.Cldr.Number . resolve_currencies ( fuzzy : 0.75 ) [ 100 , :EUR ] iex> Plausible.Cldr.Number . scan ( "100 dollars des États-Unis" ) ...> |> Plausible.Cldr.Number . resolve_currencies ( locale : "fr" ) [ 100 , :USD ]","ref":"Plausible.Cldr.Number.html#resolve_currencies/2","title":"Plausible.Cldr.Number.resolve_currencies/2","type":"function"},{"doc":"Resolve a currency from a string Arguments list is any list in which currency names and symbols are expected options is a keyword list of options Options :locale is any valid locale returned by Cldr.known_locale_names/1 or a Cldr.LanguageTag struct returned by Cldr.Locale.new!/2 The default is Plausible.Cldr.get_locale() :only is an atom or list of atoms representing the currencies or currency types to be considered for a match. The equates to a list of acceptable currencies for parsing. See the notes below for currency types. :except is an atom or list of atoms representing the currencies or currency types to be not considered for a match. This equates to a list of unacceptable currencies for parsing. See the notes below for currency types. :fuzzy is a float greater than 0.0 and less than or equal to 1.0 which is used as input to String.jaro_distance/2 to determine is the provided currency string is close enough to a known currency string for it to identify definitively a currency code. It is recommended to use numbers greater than 0.8 in order to reduce false positives. Returns An ISO4217 currency code as an atom or {:error, {exception, message}} Notes The :only and :except options accept a list of currency codes and/or currency types. The following types are recognised. If both :only and :except are specified, the :except entries take priority - that means any entries in :except are removed from the :only entries. :all , the default, considers all currencies :current considers those currencies that have a :to date of nil and which also is a known ISO4217 currency :historic is the opposite of :current :tender considers currencies that are legal tender :unannotated considers currencies that don't have "(some string)" in their names. These are usually financial instruments. Examples iex> Plausible.Cldr.Number . resolve_currency ( "US dollars" ) [ :USD ] iex> Plausible.Cldr.Number . resolve_currency ( "100 eurosports" , fuzzy : 0.75 ) [ :EUR ] iex> Plausible.Cldr.Number . resolve_currency ( "dollars des États-Unis" , locale : "fr" ) [ :USD ] iex> Plausible.Cldr.Number . resolve_currency ( "not a known currency" , locale : "fr" ) { :error , { Cldr.UnknownCurrencyError , "The currency \\" not a known currency \\" is unknown or not supported" } }","ref":"Plausible.Cldr.Number.html#resolve_currency/2","title":"Plausible.Cldr.Number.resolve_currency/2","type":"function"},{"doc":"Resolve and tokenize percent or permille from the beginning and/or the end of a string Arguments list is any list in which percent and permille symbols are expected options is a keyword list of options Options :locale is any valid locale returned by Cldr.known_locale_names/1 or a Cldr.LanguageTag struct returned by Cldr.Locale.new!/2 The default is options[:backend].get_locale() Returns An :percent or permille or {:error, {exception, message}} Examples iex> Plausible.Cldr.Number . resolve_per "11%" [ "11" , :percent ] iex> Plausible.Cldr.Number . resolve_per "% of linguists" [ :percent , " of linguists" ] iex> Plausible.Cldr.Number . resolve_per "% of linguists %" [ :percent , " of linguists " , :percent ]","ref":"Plausible.Cldr.Number.html#resolve_per/2","title":"Plausible.Cldr.Number.resolve_per/2","type":"function"},{"doc":"Resolve and tokenize percent and permille sybols from strings within a list. Percent and permille symbols can be identified at the beginning and/or the end of a string. Arguments list is any list in which percent and permille symbols are expected options is a keyword list of options Options :locale is any valid locale returned by Cldr.known_locale_names/1 or a t:Cldr.LanguageTag struct returned by Cldr.Locale.new!/2 The default is options[:backend].get_locale() Examples iex> Plausible.Cldr.Number . scan ( "100%" ) ...> |> Plausible.Cldr.Number . resolve_pers ( ) [ 100 , :percent ]","ref":"Plausible.Cldr.Number.html#resolve_pers/2","title":"Plausible.Cldr.Number.resolve_pers/2","type":"function"},{"doc":"Scans a string locale-aware manner and returns a list of strings and numbers. Arguments string is any String.t options is a keyword list of options Options :number is one of :integer , :float , :decimal or nil . The default is nil meaning that the type auto-detected as either an integer or a float . :locale is any locale returned by Cldr.known_locale_names/1 or a Cldr.LanguageTag.t . The default is Plausible.Cldr.get_locale/0 . Returns A list of strings and numbers Notes Number parsing is performed by Cldr.Number.Parser.parse/2 and any options provided are passed to that function. Examples iex> Plausible.Cldr.Number . scan ( "£1_000_000.34" ) [ "£" , 1000000.34 ] iex> Plausible.Cldr.Number . scan ( "I want £1_000_000 dollars" ) [ "I want £" , 1000000 , " dollars" ] iex> Plausible.Cldr.Number . scan ( "The prize is 23" ) [ "The prize is " , 23 ] iex> Plausible.Cldr.Number . scan ( "The lottery number is 23 for the next draw" ) [ "The lottery number is " , 23 , " for the next draw" ] iex> Plausible.Cldr.Number . scan ( "The loss is -1.000 euros" , locale : "de" , number : :integer ) [ "The loss is " , - 1000 , " euros" ]","ref":"Plausible.Cldr.Number.html#scan/2","title":"Plausible.Cldr.Number.scan/2","type":"function"},{"doc":"Formats a number and applies the :approximately format for a locale and number system. Arguments number is an integer, float or Decimal to be formatted options is a keyword list defining how the number is to be formatted. See Cldr.Number.to_string/3 for a description of the available options. Example iex> Plausible.Cldr.Number . to_approx_string 1234 { :ok , "~1,234" }","ref":"Plausible.Cldr.Number.html#to_approx_string/2","title":"Plausible.Cldr.Number.to_approx_string/2","type":"function"},{"doc":"Formats a number and applies the :at_least format for a locale and number system. Arguments number is an integer, float or Decimal to be formatted options is a keyword list defining how the number is to be formatted. See Plausible.Cldr.Number.to_string/2 for a description of the available options. Example iex> Plausible.Cldr.Number . to_at_least_string 1234 { :ok , "1,234+" }","ref":"Plausible.Cldr.Number.html#to_at_least_string/2","title":"Plausible.Cldr.Number.to_at_least_string/2","type":"function"},{"doc":"Formats a number and applies the :at_most format for a locale and number system. Arguments number is an integer, float or Decimal to be formatted options is a keyword list defining how the number is to be formatted. See Cldr.Number.to_string/3 for a description of the available options. Example iex> Plausible.Cldr.Number . to_at_most_string 1234 { :ok , "≤1,234" }","ref":"Plausible.Cldr.Number.html#to_at_most_string/2","title":"Plausible.Cldr.Number.to_at_most_string/2","type":"function"},{"doc":"Formats the first and last numbers of a range and applies the :range format for a locale and number system. Arguments number is an integer, float or Decimal to be formatted options is a keyword list defining how the number is to be formatted. See Cldr.Number.to_string/3 for a description of the available options. Example iex> Plausible.Cldr.Number . to_range_string 1234 .. 5678 { :ok , "1,234–5,678" }","ref":"Plausible.Cldr.Number.html#to_range_string/2","title":"Plausible.Cldr.Number.to_range_string/2","type":"function"},{"doc":"Returns a number formatted into a string according to a format pattern and options. Arguments number is an integer, float or Decimal to be formatted options is a keyword list defining how the number is to be formatted. Options format : the format style or a format string defining how the number is formatted. See Cldr.Number.Format for how format strings can be constructed. See Cldr.Number.Format.format_styles_for/3 to return available format styles for a locale. The default format is :standard . If :format is set to :long or :short then the formatting depends on whether :currency is specified. If not specified then the number is formatted as :decimal_long or :decimal_short . If :currency is specified the number is formatted as :currency_long or :currency_short and :fractional_digits is set to 0 as a default. :format may also be a format defined by CLDR's Rules Based Number Formats (RBNF). Further information is found in the module Cldr.Rbnf . The most commonly used formats in this category are to spell out the number in a the locales language. The applicable formats are :spellout , :spellout_year , :ordinal . A number can also be formatted as roman numbers by using the format :roman or :roman_lower . currency : is the currency for which the number is formatted. For available currencies see Cldr.Currency.known_currencies/0 . This option is required if :format is set to :currency . If currency is set and no :format is set, :format will be set to :currency as well. currency_symbol : Allows overriding a currency symbol. The alternatives are: :iso the ISO currency code will be used instead of the default currency symbol. :narrow uses the narrow symbol defined for the locale. The same narrow symbol can be defined for more than one currency and therefore this should be used with care. If no narrow symbol is defined, the standard symbol is used. :symbol uses the standard symbol defined in CLDR. A symbol is unique for each currency and can be safely used. "string" uses string as the currency symbol :standard (the default and recommended) uses the CLDR-defined symbol based upon the currency format for the locale. :cash : a boolean which indicates whether a number being formatted as a :currency is to be considered a cash value or not. Currencies can be rounded differently depending on whether :cash is true or false . *This option is deprecated in favour of currency_digits: :cash . :currency_digits indicates which of the rounding and digits should be used. The options are :accounting which is the default, :cash or :iso :rounding_mode : determines how a number is rounded to meet the precision of the format requested. The available rounding modes are :down , :half_up, :half_even, :ceiling, :floor, :half_down, :up. The default is :half_even . :number_system : determines which of the number systems for a locale should be used to define the separators and digits for the formatted number. If number_system is an atom then number_system is interpreted as a number system. If the :number_system is binary then it is interpreted as a number system name. See Cldr.Number.System.number_system_names_for/2 . The default is :default . :locale : determines the locale in which the number is formatted. See Cldr.known_locale_names/0 . The default is Cldr.get_locale/0 which is the locale currently in affect for this Process and which is set by Cldr.put_locale/1 . If :fractional_digits is set to a positive integer value then the number will be rounded to that number of digits and displayed accordingly - overriding settings that would be applied by default. For example, currencies have fractional digits defined reflecting each currencies minor unit. Setting :fractional_digits will override that setting. If :maximum_integer_digits is set to a positive integer value then the number is left truncated before formatting. For example if the number 1234 is formatted with the option maximum_integer_digits: 2 , the number is truncated to 34 and formatted. If :round_nearest is set to a positive integer value then the number will be rounded to nearest increment of that value - overriding settings that would be applied by default. :minimum_grouping_digits overrides the CLDR definition of minimum grouping digits. For example in the locale es the number 1234 is formatted by default as 1345 because the locale defines the minimium_grouping_digits as 2 . If minimum_grouping_digits: 1 is set as an option the number is formatting as 1.345 . The :minimum_grouping_digits is added to the grouping defined by the number format. If the sum of these two digits is greater than the number of digits in the integer (or fractional) part of the number then no grouping is performed. :wrapper is a 2-arity function that will be called for each number component with parameters string and tag where tag is one of :number , :currency_symbol , :currency_space , :literal , :quote , :percent , :permille , :minus or :plus . The function must return a string. The function can be used to wrap format elements in HTML or other tags. Locale extensions affecting formatting A locale identifier can specify options that affect number formatting. These options are: nu : defines the number system to be used if none is specified by the :number_system option to to_string/2 This key is part of the u extension and that document should be consulted for details on how to construct a locale identifier with these extensions. Wrapping format elements Wrapping elements is particularly useful when formatting a number with a currency symbol and the requirement is to have different HTML formatting applied to the symbol than the number. For example: iex> Cldr.Number . to_string ( 100 , format : :currency , currency : :USD , wrapper : fn ...> string , :currency_symbol -> "<span class= \\" symbol \\" >" <> string <> "</span>" ...> string , :number -> "<span class= \\" number \\" >" <> string <> "</span>" ...> string , :currency_space -> "<span>" <> string <> "</span>" ...> string , _other -> string ...> end ) { :ok , "<span class= \\" symbol \\" >$</span><span class= \\" number \\" >100.00</span>" } It is also possible and recommended to use the Phoenix.HTML.Tag.content_tag/3 function if wrapping HTML tags since these will ensure HTML entities are correctly encoded. For example: iex> Cldr.Number . to_string ( 100 , format : :currency , currency : :USD , wrapper : fn ...> string , :currency_symbol -> Phoenix.HTML.Tag . content_tag ( :span , string , class : "symbol" ) ...> string , :number -> Phoenix.HTML.Tag . content_tag ( :span , string , class : "number" ) ...> string , :currency_space -> Phoenix.HTML.Tag . content_tag ( :span , string ) ...> string , _other -> string ...> end ) { :ok , "<span class= \\" symbol \\" >$</span><span class= \\" number \\" >100.00</span>" } When formatting a number the format is parsed into format elements that might include a currency symbol, a literal string, inserted text between a currency symbol and the currency amount, a percent sign, the number itself and several other elements. In some cases it is helpful to be apply specific formatting to each element. This can be achieved by specifying a :wrapper option. This option takes a 2-arity function as an argument. For each element of the format the wrapper function is called with two parameters: the format element as a string and an atom representing the element type. The wrapper function is required to return a string that is then inserted in the final formatted number. Returns {:ok, string} or {:error, {exception, message}} Examples iex> Plausible.Cldr.Number . to_string 12345 { :ok , "12,345" } iex> Plausible.Cldr.Number . to_string 12345 , locale : "fr" { :ok , "12 345" } iex> Plausible.Cldr.Number . to_string 1345.32 , currency : :EUR , locale : "es" , minimum_grouping_digits : 1 { :ok , "1.345,32 €" } iex> Plausible.Cldr.Number . to_string 1345.32 , currency : :EUR , locale : "es" { :ok , "1345,32 €" } iex> Plausible.Cldr.Number . to_string 12345 , locale : "fr" , currency : "USD" { :ok , "12 345,00 $US" } iex> Plausible.Cldr.Number . to_string 12345 , format : "#E0" { :ok , "1.2345E4" } iex> Plausible.Cldr.Number . to_string 12345 , format : :accounting , currency : "THB" { :ok , "THB 12,345.00" } iex> Plausible.Cldr.Number . to_string - 12345 , format : :accounting , currency : "THB" { :ok , "(THB 12,345.00)" } iex> Plausible.Cldr.Number . to_string 12345 , format : :accounting , currency : "THB" , ...> locale : "th" { :ok , "฿12,345.00" } iex> Plausible.Cldr.Number . to_string 12345 , format : :accounting , currency : "THB" , ...> locale : "th" , number_system : :native { :ok , "฿๑๒,๓๔๕.๐๐" } iex> Plausible.Cldr.Number . to_string 1244.30 , format : :long { :ok , "1 thousand" } iex> Plausible.Cldr.Number . to_string 1244.30 , format : :long , currency : "USD" { :ok , "1,244 US dollars" } iex> Plausible.Cldr.Number . to_string 1244.30 , format : :short { :ok , "1K" } iex> Plausible.Cldr.Number . to_string 1244.30 , format : :short , currency : "EUR" { :ok , "€1K" } iex> Plausible.Cldr.Number . to_string 1234 , format : :spellout { :ok , "one thousand two hundred thirty-four" } iex> Plausible.Cldr.Number . to_string 1234 , format : :spellout_verbose { :ok , "one thousand two hundred and thirty-four" } iex> Plausible.Cldr.Number . to_string 1989 , format : :spellout_year { :ok , "nineteen eighty-nine" } iex> Plausible.Cldr.Number . to_string 123 , format : :ordinal { :ok , "123rd" } iex> Plausible.Cldr.Number . to_string 123 , format : :roman { :ok , "CXXIII" } iex> Plausible.Cldr.Number . to_string 123 , locale : "th-u-nu-thai" { :ok , "๑๒๓" } Errors An error tuple {:error, reason} will be returned if an error is detected. The two most likely causes of an error return are: A format cannot be compiled. In this case the error tuple will look like: iex> Plausible.Cldr.Number . to_string ( 12345 , format : "0#" ) { :error , { Cldr.FormatCompileError , "Decimal format compiler: syntax error before: \\" # \\" " } } The format style requested is not defined for the locale and number_system . This happens typically when the number system is :algorithmic rather than the more common :numeric . In this case the error return looks like: iex> Plausible.Cldr.Number . to_string ( 1234 , locale : "he" , number_system : "hebr" ) { :error , { Cldr.UnknownFormatError , "The locale :he with number system :hebr does not define a format :standard" } }","ref":"Plausible.Cldr.Number.html#to_string/2","title":"Plausible.Cldr.Number.to_string/2","type":"function"},{"doc":"Same as the execution of to_string/2 but raises an exception if an error would be returned. Arguments number is an integer, float or Decimal to be formatted options is a keyword list defining how the number is to be formatted. See Plausible.Cldr.Number.to_string/2 Returns a formatted number as a string or raises an exception Examples iex> Plausible.Cldr.Number . to_string! 12345 "12,345" iex> Plausible.Cldr.Number . to_string! 12345 , locale : "fr" "12 345"","ref":"Plausible.Cldr.Number.html#to_string!/2","title":"Plausible.Cldr.Number.to_string!/2","type":"function"},{"doc":"Return a valid number system from a provided locale and number system name or type. The number system or number system type must be valid for the given locale. If a number system type is provided, the underlying number system is returned. Arguments locale is any valid locale name returned by Cldr.known_locale_names/1 or a Cldr.LanguageTag struct returned by Cldr.Locale.new!/2 system_name is any number system name returned by Cldr.known_number_systems/0 or a number system type returned by Cldr.known_number_system_types/0 Examples iex> Plausible.Cldr.Number . validate_number_system "en" , :latn { :ok , :latn } iex> Plausible.Cldr.Number . validate_number_system "en" , :default { :ok , :latn } iex> Plausible.Cldr.Number . validate_number_system "en" , :unknown { :error , { Cldr.UnknownNumberSystemError , "The number system :unknown is unknown" } } iex> Plausible.Cldr.Number . validate_number_system "zz" , :default { :error , { Cldr.InvalidLanguageError , "The language \\" zz \\" is invalid" } }","ref":"Plausible.Cldr.Number.html#validate_number_system/2","title":"Plausible.Cldr.Number.validate_number_system/2","type":"function"},{"doc":"Implements cardinal plural rules for numbers.","ref":"Plausible.Cldr.Number.Cardinal.html","title":"Plausible.Cldr.Number.Cardinal","type":"module"},{"doc":"The locale names for which plural rules are defined.","ref":"Plausible.Cldr.Number.Cardinal.html#available_locale_names/0","title":"Plausible.Cldr.Number.Cardinal.available_locale_names/0","type":"function"},{"doc":"The configured locales for which plural rules are defined. Returns the intersection of Plausible.Cldr.known_locale_names/0 and the locales for which Cardinal plural rules are defined. There are many Cldr locales which don't have their own plural rules so this list is the intersection of Cldr 's configured locales and those that have rules.","ref":"Plausible.Cldr.Number.Cardinal.html#known_locale_names/0","title":"Plausible.Cldr.Number.Cardinal.known_locale_names/0","type":"function"},{"doc":"Return the plural key for a given number in a given locale Returns which plural key ( :zero , :one , :two , :few , :many or :other ) a given number fits into within the context of a given locale. Note that these key names should not be interpreted literally. For example, the key returned from Cldr.Number.Ordinal.plural_rule(0, "en") is actually :other , not :zero . This key can then be used to format a number, date, time, unit, list or other content in a plural-sensitive way. Arguments number is any integer , float or Decimal locale is any locale returned by Cldr.Locale.new!/2 or any locale_name returned by Plausible.Cldr.known_locale_names/0 rounding is one of [:down, :up, :ceiling, :floor, :half_even, :half_up, :half_down] . The default is :half_even . Examples iex> Plausible.Cldr.Number.Cardinal . plural_rule 0 , "fr" :one iex> Plausible.Cldr.Number.Cardinal . plural_rule 0 , "en" :other","ref":"Plausible.Cldr.Number.Cardinal.html#plural_rule/3","title":"Plausible.Cldr.Number.Cardinal.plural_rule/3","type":"function"},{"doc":"Returns all the plural rules defined in CLDR.","ref":"Plausible.Cldr.Number.Cardinal.html#plural_rules/0","title":"Plausible.Cldr.Number.Cardinal.plural_rules/0","type":"function"},{"doc":"Return the plural rules for a locale. Arguments locale is any locale returned by Plausible.Cldr.Locale.new!/1 or any locale_name returned by Plausible.Cldr.known_locale_names/0 The rules are returned in AST form after parsing.","ref":"Plausible.Cldr.Number.Cardinal.html#plural_rules_for/1","title":"Plausible.Cldr.Number.Cardinal.plural_rules_for/1","type":"function"},{"doc":"Pluralize a number using cardinal plural rules and a substitution map. Arguments number is an integer, float or Decimal locale is any locale returned by Plausible.Cldr.Locale.new!/1 or any locale_name returned by Plausible.Cldr.known_locale_names/0 substitutions is a map that maps plural keys to a string. The valid substitution keys are :zero , :one , :two , :few , :many and :other . See also Plausible.Cldr.Number.Cardinal.Cardinal.plural_rule/3 . Examples iex> Plausible.Cldr.Number.Cardinal . pluralize 1 , "en" , %{ one : "one" } "one" iex> Plausible.Cldr.Number.Cardinal . pluralize 2 , "en" , %{ one : "one" } nil iex> Plausible.Cldr.Number.Cardinal . pluralize 2 , "en" , %{ one : "one" , two : "two" , other : "other" } "other" iex> Plausible.Cldr.Number.Cardinal . pluralize 22 , "en" , %{ one : "one" , two : "two" , other : "other" } "other" iex> Plausible.Cldr.Number.Cardinal . pluralize Decimal . new ( 1 ) , "en" , %{ one : "one" } "one" iex> Plausible.Cldr.Number.Cardinal . pluralize Decimal . new ( 2 ) , "en" , %{ one : "one" } nil iex> Plausible.Cldr.Number.Cardinal . pluralize Decimal . new ( 2 ) , "en" , %{ one : "one" , two : "two" } nil iex> Plausible.Cldr.Number.Cardinal . pluralize 1 .. 10 , "ar" , %{ one : "one" , few : "few" , other : "other" } "few" iex> Plausible.Cldr.Number.Cardinal . pluralize 1 .. 10 , "en" , %{ one : "one" , few : "few" , other : "other" } "other"","ref":"Plausible.Cldr.Number.Cardinal.html#pluralize/3","title":"Plausible.Cldr.Number.Cardinal.pluralize/3","type":"function"},{"doc":"Functions to manage the collection of number patterns defined in Cldr. Number patterns affect how numbers are interpreted in a localized context. Here are some examples, based on the French locale. The "." shows where the decimal point should go. The "," shows where the thousands separator should go. A "0" indicates zero-padding: if the number is too short, a zero (in the locale's numeric set) will go there. A "#" indicates no padding: if the number is too short, nothing goes there. A "¤" shows where the currency sign will go. The following illustrates the effects of different patterns for the French locale, with the number "1234.567". Notice how the pattern characters ',' and '.' are replaced by the characters appropriate for the locale. Number Pattern Examples Pattern Currency Text #,##0.## n/a 1 234,57 #,##0.### n/a 1 234,567 ###0.##### n/a 1234,567 ###0.0000# n/a 1234,5670 00000.0000 n/a 01234,5670 #,##0.00 ¤ EUR 1 234,57 € The number of # placeholder characters before the decimal do not matter, since no limit is placed on the maximum number of digits. There should, however, be at least one zero some place in the pattern. In currency formats, the number of digits after the decimal also do not matter, since the information in the supplemental data (see Supplemental Currency Data) is used to override the number of decimal places — and the rounding — according to the currency that is being formatted. That can be seen in the above chart, with the difference between Yen and Euro formatting. Details of the number formats are described in the Unicode documentation","ref":"Plausible.Cldr.Number.Format.html","title":"Plausible.Cldr.Number.Format","type":"module"},{"doc":"Returns the decimal formats defined for a given locale. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 . The default is Plausible.Cldr.get_locale/0 . Returns {:ok, map} where map is a map of decimal formats keyed by number system or {:error, {exception, message}}","ref":"Plausible.Cldr.Number.Format.html#all_formats_for/1","title":"Plausible.Cldr.Number.Format.all_formats_for/1","type":"function"},{"doc":"Returns the decimal formats defined for a given locale. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 . The default is Plausible.Cldr.get_locale/0 . Returns {:ok, map} where map is a map of decimal formats keyed by number system or raises an exception See Plausible.Cldr.Number.Format.Number.Format.all_formats_for/1 for further information.","ref":"Plausible.Cldr.Number.Format.html#all_formats_for!/1","title":"Plausible.Cldr.Number.Format.all_formats_for!/1","type":"function"},{"doc":"Returns the currency space for a given locale and number system.","ref":"Plausible.Cldr.Number.Format.html#currency_spacing/2","title":"Plausible.Cldr.Number.Format.currency_spacing/2","type":"function"},{"doc":"Returns the list of decimal formats in the configured locales including the list of locales configured for precompilation in config.exs . This function exists to allow the decimal formatter to precompile all the known formats at compile time. Example #=> Plausible.Cldr.Number.Format.Format.decimal_format_list [ "#" , "#,##,##0%" , "#,##,##0.###" , "#,##,##0.00¤" , "#,##,##0.00¤;(#,##,##0.00¤)" , "#,##,##0 %" , "#,##0%" , "#,##0.###" , "#,##0.00 ¤" , "#,##0.00 ¤;(#,##0.00 ¤)" , "#,##0.00¤" , "#,##0.00¤;(#,##0.00¤)" , "#,##0 %" , "#0%" , "#0.######" , "#0.00 ¤" , "#E0" , "%#,##0" , "% #,##0" , "0" , "0.000000E+000" , "0000 M ¤" , "0000¤" , "000G ¤" , "000K ¤" , "000M ¤" , "000T ¤" , "000mM ¤" , "000m ¤" , "000 Bio'.' ¤" , "000 Bln ¤" , "000 Bn ¤" , "000 B ¤" , "000 E ¤" , "000 K ¤" , "000 MRD ¤" , "000 Md ¤" , "000 Mio'.' ¤" , "000 Mio ¤" , "000 Mld ¤" , "000 Mln ¤" , "000 Mn ¤" , "000 Mrd'.' ¤" , "000 Mrd ¤" , "000 Mr ¤" , "000 M ¤" , "000 NT ¤" , "000 N ¤" , "000 Tn ¤" , "000 Tr ¤" , ... ]","ref":"Plausible.Cldr.Number.Format.html#decimal_format_list/0","title":"Plausible.Cldr.Number.Format.decimal_format_list/0","type":"function"},{"doc":"Returns the list of decimal formats for a configured locale. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 . The default is Plausible.Cldr.get_locale/0 . This function exists to allow the decimal formatter to precompile all the known formats at compile time. Its use is not otherwise recommended. Example iex> Plausible.Cldr.Number.Format . decimal_format_list_for ( :en ) { :ok , [ "#,##0%" , "#,##0.###" , "#,##0.00" , "#,##0.00;(#,##0.00)" , "#E0" , "0 billion" , "0 million" , "0 thousand" , "0 trillion" , "00 billion" , "00 million" , "00 thousand" , "00 trillion" , "000 billion" , "000 million" , "000 thousand" , "000 trillion" , "000B" , "000K" , "000M" , "000T" , "00B" , "00K" , "00M" , "00T" , "0B" , "0K" , "0M" , "0T" , "¤#,##0.00" , "¤#,##0.00;(¤#,##0.00)" , "¤000B" , "¤000K" , "¤000M" , "¤000T" , "¤00B" , "¤00K" , "¤00M" , "¤00T" , "¤0B" , "¤0K" , "¤0M" , "¤0T" , "¤ #,##0.00" , "¤ #,##0.00;(¤ #,##0.00)" , "¤ 000B" , "¤ 000K" , "¤ 000M" , "¤ 000T" , "¤ 00B" , "¤ 00K" , "¤ 00M" , "¤ 00T" , "¤ 0B" , "¤ 0K" , "¤ 0M" , "¤ 0T" ] }","ref":"Plausible.Cldr.Number.Format.html#decimal_format_list_for/1","title":"Plausible.Cldr.Number.Format.decimal_format_list_for/1","type":"function"},{"doc":"Returns the default grouping for a locale as a map. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 . The default is Plausible.Cldr.get_locale/0 . Returns {:ok, grouping} or {:error, {exception, message}} Examples iex> Plausible.Cldr.Number.Format . default_grouping_for ( :en ) { :ok , %{ fraction : %{ first : 0 , rest : 0 } , integer : %{ first : 3 , rest : 3 } } }","ref":"Plausible.Cldr.Number.Format.html#default_grouping_for/1","title":"Plausible.Cldr.Number.Format.default_grouping_for/1","type":"function"},{"doc":"Returns the default grouping for a locale or raises on error. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 . The default is Plausible.Cldr.get_locale/0 . Returns grouping as a map or raises an exception Examples iex> Plausible.Cldr.Number.Format . default_grouping_for! ( :en ) %{ fraction : %{ first : 0 , rest : 0 } , integer : %{ first : 3 , rest : 3 } }","ref":"Plausible.Cldr.Number.Format.html#default_grouping_for!/1","title":"Plausible.Cldr.Number.Format.default_grouping_for!/1","type":"function"},{"doc":"Return the predfined formats for a given locale and number_system . Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 . The default is Plausible.Cldr.get_locale/0 . number_system is any valid number system or number system type returned by Plausible.Cldr.Number.System.number_systems_for/1 . Example Plausible.Cldr.Number.Format . formats_for :fr , :native #=> %Cldr.Number.Format{ accounting : "#,##0.00 ¤;(#,##0.00 ¤)" , currency : "#,##0.00 ¤" , percent : "#,##0 %" , scientific : "#E0" , standard : "#,##0.###" currency_short : [ { "1000" , [ one : "0 k ¤" , other : "0 k ¤" ] } , { "10000" , [ one : "00 k ¤" , other : "00 k ¤" ] } , { "100000" , [ one : "000 k ¤" , other : "000 k ¤" ] } , { "1000000" , [ one : "0 M ¤" , other : "0 M ¤" ] } , { "10000000" , [ one : "00 M ¤" , other : "00 M ¤" ] } , { "100000000" , [ one : "000 M ¤" , other : "000 M ¤" ] } , { "1000000000" , [ one : "0 Md ¤" , other : "0 Md ¤" ] } , { "10000000000" , [ one : "00 Md ¤" , other : "00 Md ¤" ] } , { "100000000000" , [ one : "000 Md ¤" , other : "000 Md ¤" ] } , { "1000000000000" , [ one : "0 Bn ¤" , other : "0 Bn ¤" ] } , { "10000000000000" , [ one : "00 Bn ¤" , other : "00 Bn ¤" ] } , { "100000000000000" , [ one : "000 Bn ¤" , other : "000 Bn ¤" ] } ] , ... }","ref":"Plausible.Cldr.Number.Format.html#formats_for/2","title":"Plausible.Cldr.Number.Format.formats_for/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Number.Format.html#formats_for!/2","title":"Plausible.Cldr.Number.Format.formats_for!/2","type":"function"},{"doc":"Returns the minimum grouping digits for a locale. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 . The default is Plausible.Cldr.get_locale/0 . Returns {:ok, minumum_digits} or {:error, {exception, message}} Examples iex> Plausible.Cldr.Number.Format . minimum_grouping_digits_for ( "en" ) { :ok , 1 }","ref":"Plausible.Cldr.Number.Format.html#minimum_grouping_digits_for/1","title":"Plausible.Cldr.Number.Format.minimum_grouping_digits_for/1","type":"function"},{"doc":"Returns the minimum grouping digits for a locale or raises on error. Arguments locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 . The default is Plausible.Cldr.get_locale/0 . Returns minumum_digits or raises an exception Examples iex> Plausible.Cldr.Number.Format . minimum_grouping_digits_for! ( "en" ) 1","ref":"Plausible.Cldr.Number.Format.html#minimum_grouping_digits_for!/1","title":"Plausible.Cldr.Number.Format.minimum_grouping_digits_for!/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Number.Formatter.Decimal.html","title":"Plausible.Cldr.Number.Formatter.Decimal","type":"module"},{"doc":"","ref":"Plausible.Cldr.Number.Formatter.Decimal.html#metadata!/1","title":"Plausible.Cldr.Number.Formatter.Decimal.metadata!/1","type":"function"},{"doc":"Formats a number according to a decimal format string. Arguments number is an integer, float or Decimal format is a format string. See Plausible.Cldr.Number for further information. options is a map of options. See Plausible.Cldr.Number.to_string/2 for further information.","ref":"Plausible.Cldr.Number.Formatter.Decimal.html#to_string/3","title":"Plausible.Cldr.Number.Formatter.Decimal.to_string/3","type":"function"},{"doc":"Implements ordinal plural rules for numbers.","ref":"Plausible.Cldr.Number.Ordinal.html","title":"Plausible.Cldr.Number.Ordinal","type":"module"},{"doc":"The locale names for which plural rules are defined.","ref":"Plausible.Cldr.Number.Ordinal.html#available_locale_names/0","title":"Plausible.Cldr.Number.Ordinal.available_locale_names/0","type":"function"},{"doc":"The configured locales for which plural rules are defined. Returns the intersection of Plausible.Cldr.known_locale_names/0 and the locales for which Ordinal plural rules are defined. There are many Cldr locales which don't have their own plural rules so this list is the intersection of Cldr 's configured locales and those that have rules.","ref":"Plausible.Cldr.Number.Ordinal.html#known_locale_names/0","title":"Plausible.Cldr.Number.Ordinal.known_locale_names/0","type":"function"},{"doc":"Return the plural key for a given number in a given locale Returns which plural key ( :zero , :one , :two , :few , :many or :other ) a given number fits into within the context of a given locale. Note that these key names should not be interpreted literally. For example, the key returned from Cldr.Number.Ordinal.plural_rule(0, "en") is actually :other , not :zero . This key can then be used to format a number, date, time, unit, list or other content in a plural-sensitive way. Arguments number is any integer , float or Decimal locale is any locale returned by Cldr.Locale.new!/2 or any locale_name returned by Plausible.Cldr.known_locale_names/0 rounding is one of [:down, :up, :ceiling, :floor, :half_even, :half_up, :half_down] . The default is :half_even . Examples iex> Plausible.Cldr.Number.Ordinal . plural_rule 0 , "fr" :other iex> Plausible.Cldr.Number.Ordinal . plural_rule 1 , "en" :one","ref":"Plausible.Cldr.Number.Ordinal.html#plural_rule/3","title":"Plausible.Cldr.Number.Ordinal.plural_rule/3","type":"function"},{"doc":"Returns all the plural rules defined in CLDR.","ref":"Plausible.Cldr.Number.Ordinal.html#plural_rules/0","title":"Plausible.Cldr.Number.Ordinal.plural_rules/0","type":"function"},{"doc":"Return the plural rules for a locale. Arguments locale is any locale returned by Plausible.Cldr.Locale.new!/1 or any locale_name returned by Plausible.Cldr.known_locale_names/0 The rules are returned in AST form after parsing.","ref":"Plausible.Cldr.Number.Ordinal.html#plural_rules_for/1","title":"Plausible.Cldr.Number.Ordinal.plural_rules_for/1","type":"function"},{"doc":"Pluralize a number using ordinal plural rules and a substitution map. Arguments number is an integer, float or Decimal or a Range.t{} . When a range, The is that in any usage, the start value is strictly less than the end value, and that no values are negative. Results for any cases that do not meet these criteria are undefined. locale is any locale returned by Plausible.Cldr.Locale.new!/1 or any locale_name returned by Plausible.Cldr.known_locale_names/0 substitutions is a map that maps plural keys to a string. The valid substitution keys are :zero , :one , :two , :few , :many and :other . See also Plausible.Cldr.Number.Ordinal.Ordinal.plural_rule/3 . Examples iex> Plausible.Cldr.Number.Ordinal . pluralize 1 , :en , %{ one : "one" } "one" iex> Plausible.Cldr.Number.Ordinal . pluralize 2 , :en , %{ one : "one" } nil iex> Plausible.Cldr.Number.Ordinal . pluralize 2 , :en , %{ one : "one" , two : "two" } "two" iex> Plausible.Cldr.Number.Ordinal . pluralize 22 , :en , %{ one : "one" , two : "two" , other : "other" } "two" iex> Plausible.Cldr.Number.Ordinal . pluralize Decimal . new ( 1 ) , :en , %{ one : "one" } "one" iex> Plausible.Cldr.Number.Ordinal . pluralize Decimal . new ( 2 ) , :en , %{ one : "one" } nil iex> Plausible.Cldr.Number.Ordinal . pluralize Decimal . new ( 2 ) , :en , %{ one : "one" , two : "two" } "two" iex> Plausible.Cldr.Number.Ordinal . pluralize 1 .. 10 , "ar" , %{ one : "one" , few : "few" , other : "other" } "other" iex> Plausible.Cldr.Number.Ordinal . pluralize 1 .. 10 , "en" , %{ one : "one" , few : "few" , other : "other" } "other"","ref":"Plausible.Cldr.Number.Ordinal.html#pluralize/3","title":"Plausible.Cldr.Number.Ordinal.pluralize/3","type":"function"},{"doc":"Implements plural rules for ranges","ref":"Plausible.Cldr.Number.PluralRule.Range.html","title":"Plausible.Cldr.Number.PluralRule.Range","type":"module"},{"doc":"Returns a final plural type for a start-of-range plural type, an end-of-range plural type and a locale. Arguments first is a plural type for the start of a range last is a plural type for the end of a range locale is any Cldr.LanguageTag.t or a language name (not locale name) Example iex> Plausible.Cldr.Number.PluralRule.Range . plural_rule :other , :few , "ar" :few","ref":"Plausible.Cldr.Number.PluralRule.Range.html#plural_rule/3","title":"Plausible.Cldr.Number.PluralRule.Range.plural_rule/3","type":"function"},{"doc":"","ref":"Plausible.Cldr.Number.Symbol.html","title":"Plausible.Cldr.Number.Symbol","type":"module"},{"doc":"Returns a list of all decimal symbols defined by the locales configured in this backend as a list.","ref":"Plausible.Cldr.Number.Symbol.html#all_decimal_symbols/0","title":"Plausible.Cldr.Number.Symbol.all_decimal_symbols/0","type":"function"},{"doc":"Returns a list of all decimal symbols defined by the locales configured in this backend as a string. This string can be used as a character class when builing a regular expression.","ref":"Plausible.Cldr.Number.Symbol.html#all_decimal_symbols_class/0","title":"Plausible.Cldr.Number.Symbol.all_decimal_symbols_class/0","type":"function"},{"doc":"Returns a list of all grouping symbols defined by the locales configured in this backend as a list.","ref":"Plausible.Cldr.Number.Symbol.html#all_grouping_symbols/0","title":"Plausible.Cldr.Number.Symbol.all_grouping_symbols/0","type":"function"},{"doc":"Returns a list of all grouping symbols defined by the locales configured in this backend as a string. This string can be used as a character class when builing a regular expression.","ref":"Plausible.Cldr.Number.Symbol.html#all_grouping_symbols_class/0","title":"Plausible.Cldr.Number.Symbol.all_grouping_symbols_class/0","type":"function"},{"doc":"Returns a map of Cldr.Number.Symbol.t structs of the number symbols for each of the number systems of a locale. Options locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 . The default is Plausible.Cldr.get_locale/0 . Example: iex> Plausible.Cldr.Number.Symbol . number_symbols_for ( :th ) { :ok , %{ latn : % Cldr.Number.Symbol { decimal : "." , exponential : "E" , group : "," , infinity : "∞" , list : ";" , minus_sign : "-" , nan : "NaN" , per_mille : "‰" , percent_sign : "%" , plus_sign : "+" , superscripting_exponent : "×" , time_separator : ":" } , thai : % Cldr.Number.Symbol { decimal : "." , exponential : "E" , group : "," , infinity : "∞" , list : ";" , minus_sign : "-" , nan : "NaN" , per_mille : "‰" , percent_sign : "%" , plus_sign : "+" , superscripting_exponent : "×" , time_separator : ":" } } }","ref":"Plausible.Cldr.Number.Symbol.html#number_symbols_for/1","title":"Plausible.Cldr.Number.Symbol.number_symbols_for/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Number.Symbol.html#number_symbols_for/2","title":"Plausible.Cldr.Number.Symbol.number_symbols_for/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Number.System.html","title":"Plausible.Cldr.Number.System","type":"module"},{"doc":"Returns the actual number system from a number system type. locale is any valid locale name returned by Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Cldr.Locale.new!/2 system_name is any number system name returned by Cldr.known_number_systems/0 or a number system type returned by Cldr.known_number_system_types/0 This function will decode a number system type into the actual number system. If the number system provided can't be decoded it is returned as is. Examples iex> Plausible.Cldr.Number.System . number_system_for "th" , :latn { :ok , %{ digits : "0123456789" , type : :numeric } } iex> Plausible.Cldr.Number.System . number_system_for "en" , :default { :ok , %{ digits : "0123456789" , type : :numeric } } iex> Plausible.Cldr.Number.System . number_system_for "he" , :traditional { :ok , %{ rules : "hebrew" , type : :algorithmic } } iex> Plausible.Cldr.Number.System . number_system_for "en" , :native { :ok , %{ digits : "0123456789" , type : :numeric } } iex> Plausible.Cldr.Number.System . number_system_for "en" , :finance { :error , { Cldr.UnknownNumberSystemError , "The number system :finance is unknown for the locale named :en. Valid number systems are %{default: :latn, native: :latn}" } }","ref":"Plausible.Cldr.Number.System.html#number_system_for/2","title":"Plausible.Cldr.Number.System.number_system_for/2","type":"function"},{"doc":"Returns the number system from a language tag or locale name. Arguments locale is any language tag returned be Cldr.Locale.new/2 or a locale name in the list returned by Cldr.known_locale_names/1 Returns A number system name as an atom Examples iex> Plausible.Cldr.Number.System . number_system_from_locale "en-US-u-nu-thai" :thai iex> Plausible.Cldr.Number.System . number_system_from_locale "en-US" :latn","ref":"Plausible.Cldr.Number.System.html#number_system_from_locale/1","title":"Plausible.Cldr.Number.System.number_system_from_locale/1","type":"function"},{"doc":"Returns the number systems available for a locale or {:error, message} if the locale is not known. locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 Examples iex> Plausible.Cldr.Number.System . number_system_names_for "en" { :ok , [ :latn ] } iex> Plausible.Cldr.Number.System . number_system_names_for "zz" { :error , { Cldr.InvalidLanguageError , "The language \\" zz \\" is invalid" } }","ref":"Plausible.Cldr.Number.System.html#number_system_names_for/1","title":"Plausible.Cldr.Number.System.number_system_names_for/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Number.System.html#number_system_names_for!/1","title":"Plausible.Cldr.Number.System.number_system_names_for!/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Number.System.html#number_system_types_for/1","title":"Plausible.Cldr.Number.System.number_system_types_for/1","type":"function"},{"doc":"Returns the number systems available for a locale or {:error, message} if the locale is not known. locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 Examples iex> Plausible.Cldr.Number.System . number_systems_for "en" { :ok , %{ default : :latn , native : :latn } } iex> Plausible.Cldr.Number.System . number_systems_for "th" { :ok , %{ default : :latn , native : :thai } } iex> Plausible.Cldr.Number.System . number_systems_for "zz" { :error , { Cldr.InvalidLanguageError , "The language \\" zz \\" is invalid" } }","ref":"Plausible.Cldr.Number.System.html#number_systems_for/1","title":"Plausible.Cldr.Number.System.number_systems_for/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Number.System.html#number_systems_for!/1","title":"Plausible.Cldr.Number.System.number_systems_for!/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Number.System.html#number_systems_like/2","title":"Plausible.Cldr.Number.System.number_systems_like/2","type":"function"},{"doc":"Returns a number system name for a given locale and number system reference. system_name is any number system name returned by Plausible.Cldr.known_number_systems/0 or a number system type returned by Plausible.Cldr.known_number_system_types/0 locale is any valid locale name returned by Plausible.Cldr.known_locale_names/0 or a Cldr.LanguageTag struct returned by Plausible.Cldr.Locale.new!/1 Number systems can be references in one of two ways: As a number system type such as :default, :native, :traditional and :finance. This allows references to a number system for a locale in a consistent fashion for a given use WIth the number system name directly, such as :latn, :arab or any of the other 70 or so This function dereferences the supplied system_name and returns the actual system name. Examples ex > Plausible.Cldr.Number.System . system_name_from ( :default , "en" ) { :ok , :latn } iex> Plausible.Cldr.Number.System . system_name_from ( "latn" , "en" ) { :ok , :latn } iex> Plausible.Cldr.Number.System . system_name_from ( :native , "en" ) { :ok , :latn } iex> Plausible.Cldr.Number.System . system_name_from ( :nope , "en" ) { :error , { Cldr.UnknownNumberSystemError , "The number system :nope is unknown" } } Note that return value is not guaranteed to be a valid number system for the given locale as demonstrated in the third example.","ref":"Plausible.Cldr.Number.System.html#system_name_from/2","title":"Plausible.Cldr.Number.System.system_name_from/2","type":"function"},{"doc":"Converts a number into the representation of a non-latin number system. This function converts numbers to a known number system only, it does not provide number formatting. number is a float , integer or Decimal system_name is any number system name returned by Cldr.known_number_systems/0 or a number system type returned by Cldr.known_number_system_types/0 There are two types of number systems in CLDR: :numeric in which the number system defines a direct mapping between the latin digits 0..9 into a the number system equivalent. In this case, to_system/2 invokes Cldr.Number.Transliterate.transliterate_digits/3 for the given number. :algorithmic in which the number system does not have the same structure as the :latn number system and therefore the conversion is done algorithmically. For CLDR the algorithm is implemented through Cldr.Rbnf rulesets. These rulesets are considered by CLDR to be less rigorous than the :numeric number systems and caution and testing for a specific use case is recommended. Examples iex> Plausible.Cldr.Number.System . to_system 123456 , :hebr { :ok , "קכ״ג׳תנ״ו" } iex> Plausible.Cldr.Number.System . to_system 123 , :hans { :ok , "一百二十三" } iex> Plausible.Cldr.Number.System . to_system 123 , :hant { :ok , "一百二十三" } iex> Plausible.Cldr.Number.System . to_system 123 , :hansfin { :ok , "壹佰贰拾叁" }","ref":"Plausible.Cldr.Number.System.html#to_system/2","title":"Plausible.Cldr.Number.System.to_system/2","type":"function"},{"doc":"Converts a number into the representation of a non-latin number system. Returns a converted string or raises on error. number is a float , integer or Decimal system_name is any number system name returned by Plausible.Cldr.known_number_systems/0 or a number system type returned by Plausible.Cldr.known_number_system_types/0 See Plausible.Cldr.Number.System.to_system/2 for further information. Examples iex> Plausible.Cldr.Number.System . to_system! 123 , :hans "一百二十三" iex> Plausible.Cldr.Number.System . to_system! 123 , :hant "一百二十三" iex> Plausible.Cldr.Number.System . to_system! 123 , :hansfin "壹佰贰拾叁"","ref":"Plausible.Cldr.Number.System.html#to_system!/2","title":"Plausible.Cldr.Number.System.to_system!/2","type":"function"},{"doc":"Transliteration for digits and separators. Transliterating a string is an expensive business. First the string has to be exploded into its component graphemes. Then for each grapheme we have to map to the equivalent in the other {locale, number_system} . Then we have to reassemble the string. Effort is made to short circuit where possible. Transliteration is not required for any {locale, number_system} that is the same as {"en", "latn"} since the implementation uses this combination for the placeholders during formatting already. When short circuiting is possible (typically the en-* locales with "latn" number_system - the total number of short circuited locales is 211 of the 537 in CLDR) the overall number formatting is twice as fast than when formal transliteration is required. Configuring precompilation of digit transliterations This module includes Cldr.Number.Transliterate.transliterate_digits/3 which transliterates digits between number systems. For example from :arabic to :latn. Since generating a transliteration map is slow, pairs of transliterations can be configured so that the transliteration map is created at compile time and therefore speeding up transliteration at run time. To configure these transliteration pairs, add the to the use Cldr configuration in a backend module: defmodule MyApp.Cldr do use Cldr , locale : [ "en" , "fr" , "th" ] , default_locale : "en" , precompile_transliterations : [ { :latn , :thai } , { :arab , :thai } ] end Where each tuple in the list configures one transliteration map. In this example, two maps are configured: from :latn to :thai and from :arab to :thai . A list of configurable number systems is returned by Cldr.Number.System.systems_with_digits/0 . If a transliteration is requested between two number pairs that have not been configured for precompilation, a warning is logged.","ref":"Plausible.Cldr.Number.Transliterate.html","title":"Plausible.Cldr.Number.Transliterate","type":"module"},{"doc":"Transliterates from latin digits to another number system's digits. Transliterates the latin digits 0..9 to their equivalents in another number system. Also transliterates the decimal and grouping separators as well as the plus, minus and exponent symbols. Any other character in the string will be returned "as is". Arguments sequence is the string to be transliterated. locale is any known locale, defaulting to Plausible.Cldr.get_locale/0 . number_system is any known number system. If expressed as a string it is the actual name of a known number system. If epressed as an atom it is used as a key to look up a number system for the locale (the usual keys are :default and :native but :traditional and :finance are also part of the standard). See Plausible.Cldr.Number.System.number_systems_for/1 for a locale to see what number system types are defined. The default is :default . For available number systems see Cldr.Number.System.number_systems/0 and Plausible.Cldr.Number.System.number_systems_for/1 . Also see Plausible.Cldr.Number.Symbol.number_symbols_for/1 . Examples iex> Plausible.Cldr.Number.Transliterate . transliterate ( "123556" ) "123556" iex> Plausible.Cldr.Number.Transliterate . transliterate ( "123,556.000" , "fr" , :default ) "123 556,000" iex> Plausible.Cldr.Number.Transliterate . transliterate ( "123556" , "th" , :default ) "123556" iex> Plausible.Cldr.Number.Transliterate . transliterate ( "123556" , "th" , "thai" ) "๑๒๓๕๕๖" iex> Plausible.Cldr.Number.Transliterate . transliterate ( "123556" , "th" , :native ) "๑๒๓๕๕๖" iex> Plausible.Cldr.Number.Transliterate . transliterate ( "Some number is: 123556" , "th" , "thai" ) "Some number is: ๑๒๓๕๕๖"","ref":"Plausible.Cldr.Number.Transliterate.html#transliterate/3","title":"Plausible.Cldr.Number.Transliterate.transliterate/3","type":"function"},{"doc":"","ref":"Plausible.Cldr.Number.Transliterate.html#transliterate!/3","title":"Plausible.Cldr.Number.Transliterate.transliterate!/3","type":"function"},{"doc":"Transliterates digits from one number system to another number system digits is binary representation of a number from_system and to_system are number system names in atom form. See Cldr.Number.System.systems_with_digits/0 for available number systems. Example iex> Plausible.Cldr.Number.Transliterate . transliterate_digits "٠١٢٣٤٥٦٧٨٩" , :arab , :latn "0123456789"","ref":"Plausible.Cldr.Number.Transliterate.html#transliterate_digits/3","title":"Plausible.Cldr.Number.Transliterate.transliterate_digits/3","type":"function"},{"doc":"Functions to implement the number system rule-based-number-format rules of CLDR. These rules are defined only on the "und" locale and represent specialised number formatting. The standard public API for RBNF is via the Cldr.Number.to_string/2 function. The functions on this module are defined at compile time based upon the RBNF rules defined in the Unicode CLDR data repository. Available rules are identified by: iex> Plausible.Cldr.Rbnf.NumberSystem . rule_sets ( :und ) [ :zz_default , :tamil , :roman_upper , :roman_lower , :hebrew_item , :hebrew , :greek_upper , :greek_lower , :georgian , :ethiopic , :cyrillic_lower , :armenian_upper , :armenian_lower ] A rule can then be invoked on an available rule_set. For example iex> Plausible.Cldr.Rbnf.NumberSystem . roman_upper ( 123 , :und ) "CXXIII" This particular call is equivalent to the call through the public API of: iex> Plausible.Cldr.Number . to_string ( 123 , format : :roman ) { :ok , "CXXIII" }","ref":"Plausible.Cldr.Rbnf.NumberSystem.html","title":"Plausible.Cldr.Rbnf.NumberSystem","type":"module"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#all_rule_sets/0","title":"Plausible.Cldr.Rbnf.NumberSystem.all_rule_sets/0","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#armenian_lower/1","title":"Plausible.Cldr.Rbnf.NumberSystem.armenian_lower/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#armenian_lower/2","title":"Plausible.Cldr.Rbnf.NumberSystem.armenian_lower/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#armenian_upper/1","title":"Plausible.Cldr.Rbnf.NumberSystem.armenian_upper/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#armenian_upper/2","title":"Plausible.Cldr.Rbnf.NumberSystem.armenian_upper/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#cyrillic_lower/1","title":"Plausible.Cldr.Rbnf.NumberSystem.cyrillic_lower/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#cyrillic_lower/2","title":"Plausible.Cldr.Rbnf.NumberSystem.cyrillic_lower/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#cyrillic_lower_1_10/2","title":"Plausible.Cldr.Rbnf.NumberSystem.cyrillic_lower_1_10/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#cyrillic_lower_final/2","title":"Plausible.Cldr.Rbnf.NumberSystem.cyrillic_lower_final/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#cyrillic_lower_post/2","title":"Plausible.Cldr.Rbnf.NumberSystem.cyrillic_lower_post/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#cyrillic_lower_thousands/2","title":"Plausible.Cldr.Rbnf.NumberSystem.cyrillic_lower_thousands/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#ethiopic/1","title":"Plausible.Cldr.Rbnf.NumberSystem.ethiopic/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#ethiopic/2","title":"Plausible.Cldr.Rbnf.NumberSystem.ethiopic/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#ethiopic_p1/2","title":"Plausible.Cldr.Rbnf.NumberSystem.ethiopic_p1/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#ethiopic_p2/2","title":"Plausible.Cldr.Rbnf.NumberSystem.ethiopic_p2/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#ethiopic_p3/2","title":"Plausible.Cldr.Rbnf.NumberSystem.ethiopic_p3/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#ethiopic_p/2","title":"Plausible.Cldr.Rbnf.NumberSystem.ethiopic_p/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#georgian/1","title":"Plausible.Cldr.Rbnf.NumberSystem.georgian/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#georgian/2","title":"Plausible.Cldr.Rbnf.NumberSystem.georgian/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#greek_lower/1","title":"Plausible.Cldr.Rbnf.NumberSystem.greek_lower/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#greek_lower/2","title":"Plausible.Cldr.Rbnf.NumberSystem.greek_lower/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#greek_numeral_majuscules/2","title":"Plausible.Cldr.Rbnf.NumberSystem.greek_numeral_majuscules/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#greek_numeral_minuscules/2","title":"Plausible.Cldr.Rbnf.NumberSystem.greek_numeral_minuscules/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#greek_upper/1","title":"Plausible.Cldr.Rbnf.NumberSystem.greek_upper/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#greek_upper/2","title":"Plausible.Cldr.Rbnf.NumberSystem.greek_upper/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#hebrew/1","title":"Plausible.Cldr.Rbnf.NumberSystem.hebrew/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#hebrew/2","title":"Plausible.Cldr.Rbnf.NumberSystem.hebrew/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#hebrew_0_99/2","title":"Plausible.Cldr.Rbnf.NumberSystem.hebrew_0_99/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#hebrew_item/1","title":"Plausible.Cldr.Rbnf.NumberSystem.hebrew_item/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#hebrew_item/2","title":"Plausible.Cldr.Rbnf.NumberSystem.hebrew_item/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#hebrew_item_hundreds/2","title":"Plausible.Cldr.Rbnf.NumberSystem.hebrew_item_hundreds/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#hebrew_thousands/2","title":"Plausible.Cldr.Rbnf.NumberSystem.hebrew_thousands/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#roman_lower/1","title":"Plausible.Cldr.Rbnf.NumberSystem.roman_lower/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#roman_lower/2","title":"Plausible.Cldr.Rbnf.NumberSystem.roman_lower/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#roman_upper/1","title":"Plausible.Cldr.Rbnf.NumberSystem.roman_upper/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#roman_upper/2","title":"Plausible.Cldr.Rbnf.NumberSystem.roman_upper/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#rule_sets/0","title":"Plausible.Cldr.Rbnf.NumberSystem.rule_sets/0","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#rule_sets/1","title":"Plausible.Cldr.Rbnf.NumberSystem.rule_sets/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#tamil/1","title":"Plausible.Cldr.Rbnf.NumberSystem.tamil/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#tamil/2","title":"Plausible.Cldr.Rbnf.NumberSystem.tamil/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#tamil_thousands/2","title":"Plausible.Cldr.Rbnf.NumberSystem.tamil_thousands/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#zz_default/1","title":"Plausible.Cldr.Rbnf.NumberSystem.zz_default/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.NumberSystem.html#zz_default/2","title":"Plausible.Cldr.Rbnf.NumberSystem.zz_default/2","type":"function"},{"doc":"Functions to implement the ordinal rule-based-number-format rules of CLDR. As CLDR notes, the data is incomplete or non-existent for many languages. It is considered complete for English however. The standard public API for RBNF is via the Cldr.Number.to_string/2 function. The functions on this module are defined at compile time based upon the RBNF rules defined in the Unicode CLDR data repository. Available rules are identified by: iex> Plausible.Cldr.Rbnf.Ordinal . rule_sets ( :en ) [ :digits_ordinal ] iex> Plausible.Cldr.Rbnf.Ordinal . rule_sets ( "fr" ) [ :digits_ordinal_masculine_plural , :digits_ordinal_masculine , :digits_ordinal_feminine_plural , :digits_ordinal_feminine , :digits_ordinal ] A rule can then be invoked on an available rule_set. For example iex> Plausible.Cldr.Rbnf.Ordinal . digits_ordinal ( 123 , :en ) "123rd" This call is equivalent to the call through the public API of: iex> Plausible.Cldr.Number . to_string ( 123 , format : :ordinal ) { :ok , "123rd" }","ref":"Plausible.Cldr.Rbnf.Ordinal.html","title":"Plausible.Cldr.Rbnf.Ordinal","type":"module"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Ordinal.html#all_rule_sets/0","title":"Plausible.Cldr.Rbnf.Ordinal.all_rule_sets/0","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Ordinal.html#digits_ordinal/2","title":"Plausible.Cldr.Rbnf.Ordinal.digits_ordinal/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Ordinal.html#rule_sets/0","title":"Plausible.Cldr.Rbnf.Ordinal.rule_sets/0","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Ordinal.html#rule_sets/1","title":"Plausible.Cldr.Rbnf.Ordinal.rule_sets/1","type":"function"},{"doc":"Functions to implement the spellout rule-based-number-format rules of CLDR. As CLDR notes, the data is incomplete or non-existent for many languages. It is considered complete for English however. The standard public API for RBNF is via the Cldr.Number.to_string/2 function. The functions on this module are defined at compile time based upon the RBNF rules defined in the Unicode CLDR data repository. Available rules are identified by: iex> Plausible.Cldr.Rbnf.Spellout . rule_sets ( "en" ) [ :spellout_ordinal_verbose , :spellout_ordinal , :spellout_numbering_year , :spellout_numbering_verbose , :spellout_numbering , :spellout_cardinal_verbose , :spellout_cardinal ] A rule can then be invoked on an available rule_set. For example: iex> Plausible.Cldr.Rbnf.Spellout . spellout_ordinal ( 123 , "en" ) "one hundred twenty-third" This call is equivalent to the call through the public API of: iex> Plausible.Cldr.Number . to_string ( 123 , format : :spellout ) { :ok , "one hundred twenty-three" }","ref":"Plausible.Cldr.Rbnf.Spellout.html","title":"Plausible.Cldr.Rbnf.Spellout","type":"module"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#2d_year/2","title":"Plausible.Cldr.Rbnf.Spellout.2d_year/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#all_rule_sets/0","title":"Plausible.Cldr.Rbnf.Spellout.all_rule_sets/0","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#and/2","title":"Plausible.Cldr.Rbnf.Spellout.and/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#and_o/2","title":"Plausible.Cldr.Rbnf.Spellout.and_o/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#commas/2","title":"Plausible.Cldr.Rbnf.Spellout.commas/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#commas_o/2","title":"Plausible.Cldr.Rbnf.Spellout.commas_o/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#rule_sets/0","title":"Plausible.Cldr.Rbnf.Spellout.rule_sets/0","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#rule_sets/1","title":"Plausible.Cldr.Rbnf.Spellout.rule_sets/1","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#spellout_cardinal/2","title":"Plausible.Cldr.Rbnf.Spellout.spellout_cardinal/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#spellout_cardinal_verbose/2","title":"Plausible.Cldr.Rbnf.Spellout.spellout_cardinal_verbose/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#spellout_numbering/2","title":"Plausible.Cldr.Rbnf.Spellout.spellout_numbering/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#spellout_numbering_verbose/2","title":"Plausible.Cldr.Rbnf.Spellout.spellout_numbering_verbose/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#spellout_numbering_year/2","title":"Plausible.Cldr.Rbnf.Spellout.spellout_numbering_year/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#spellout_ordinal/2","title":"Plausible.Cldr.Rbnf.Spellout.spellout_ordinal/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#spellout_ordinal_verbose/2","title":"Plausible.Cldr.Rbnf.Spellout.spellout_ordinal_verbose/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#th/2","title":"Plausible.Cldr.Rbnf.Spellout.th/2","type":"function"},{"doc":"","ref":"Plausible.Cldr.Rbnf.Spellout.html#tieth/2","title":"Plausible.Cldr.Rbnf.Spellout.tieth/2","type":"function"},{"doc":"Event schema for when NumericIDs migration is complete","ref":"Plausible.ClickhouseEventV2.html","title":"Plausible.ClickhouseEventV2","type":"module"},{"doc":"","ref":"Plausible.ClickhouseEventV2.html#new/1","title":"Plausible.ClickhouseEventV2.new/1","type":"function"},{"doc":"","ref":"Plausible.ClickhouseRepo.html","title":"Plausible.ClickhouseRepo","type":"module"},{"doc":"Callback implementation for Ecto.Repo.aggregate/3 .","ref":"Plausible.ClickhouseRepo.html#aggregate/3","title":"Plausible.ClickhouseRepo.aggregate/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.aggregate/4 .","ref":"Plausible.ClickhouseRepo.html#aggregate/4","title":"Plausible.ClickhouseRepo.aggregate/4","type":"function"},{"doc":"Callback implementation for Ecto.Repo.all/2 .","ref":"Plausible.ClickhouseRepo.html#all/2","title":"Plausible.ClickhouseRepo.all/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.checked_out?/0 .","ref":"Plausible.ClickhouseRepo.html#checked_out?/0","title":"Plausible.ClickhouseRepo.checked_out?/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.checkout/2 .","ref":"Plausible.ClickhouseRepo.html#checkout/2","title":"Plausible.ClickhouseRepo.checkout/2","type":"function"},{"doc":"","ref":"Plausible.ClickhouseRepo.html#child_spec/1","title":"Plausible.ClickhouseRepo.child_spec/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.config/0 .","ref":"Plausible.ClickhouseRepo.html#config/0","title":"Plausible.ClickhouseRepo.config/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.default_options/1 .","ref":"Plausible.ClickhouseRepo.html#default_options/1","title":"Plausible.ClickhouseRepo.default_options/1","type":"function"},{"doc":"A convenience function for SQL-based repositories that forces all connections in the pool to disconnect within the given interval. See Ecto.Adapters.SQL.disconnect_all/3 for more information.","ref":"Plausible.ClickhouseRepo.html#disconnect_all/2","title":"Plausible.ClickhouseRepo.disconnect_all/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.exists?/2 .","ref":"Plausible.ClickhouseRepo.html#exists?/2","title":"Plausible.ClickhouseRepo.exists?/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get/3 .","ref":"Plausible.ClickhouseRepo.html#get/3","title":"Plausible.ClickhouseRepo.get/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get!/3 .","ref":"Plausible.ClickhouseRepo.html#get!/3","title":"Plausible.ClickhouseRepo.get!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_by/3 .","ref":"Plausible.ClickhouseRepo.html#get_by/3","title":"Plausible.ClickhouseRepo.get_by/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_by!/3 .","ref":"Plausible.ClickhouseRepo.html#get_by!/3","title":"Plausible.ClickhouseRepo.get_by!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_dynamic_repo/0 .","ref":"Plausible.ClickhouseRepo.html#get_dynamic_repo/0","title":"Plausible.ClickhouseRepo.get_dynamic_repo/0","type":"function"},{"doc":"Similar to insert_all/2 but with the following differences: accepts rows as streams or lists sends rows as a chunked request doesn't autogenerate ids or does any other preprocessing Example: Repo . query! ( "create table ecto_ch_demo(a UInt64, b String) engine Null" ) defmodule Demo do use Ecto.Schema @primary_key false schema "ecto_ch_demo" do field :a , Ch , type : "UInt64" field :b , :string end end rows = Stream . map ( 1 .. 100_000 , fn i -> %{ a : i , b : to_string ( i ) } end ) { 100_000 , nil } = Repo . insert_stream ( Demo , rows ) # schemaless { 100_000 , nil } = Repo . insert_stream ( "ecto_ch_demo" , rows , types : [ a : Ch.Types . u64 ( ) , b : :string ] )","ref":"Plausible.ClickhouseRepo.html#insert_stream/3","title":"Plausible.ClickhouseRepo.insert_stream/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.load/2 .","ref":"Plausible.ClickhouseRepo.html#load/2","title":"Plausible.ClickhouseRepo.load/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.one/2 .","ref":"Plausible.ClickhouseRepo.html#one/2","title":"Plausible.ClickhouseRepo.one/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.one!/2 .","ref":"Plausible.ClickhouseRepo.html#one!/2","title":"Plausible.ClickhouseRepo.one!/2","type":"function"},{"doc":"","ref":"Plausible.ClickhouseRepo.html#parallel_tasks/1","title":"Plausible.ClickhouseRepo.parallel_tasks/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.preload/3 .","ref":"Plausible.ClickhouseRepo.html#preload/3","title":"Plausible.ClickhouseRepo.preload/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.prepare_query/3 .","ref":"Plausible.ClickhouseRepo.html#prepare_query/3","title":"Plausible.ClickhouseRepo.prepare_query/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.put_dynamic_repo/1 .","ref":"Plausible.ClickhouseRepo.html#put_dynamic_repo/1","title":"Plausible.ClickhouseRepo.put_dynamic_repo/1","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given query. See Ecto.Adapters.SQL.query/4 for more information.","ref":"Plausible.ClickhouseRepo.html#query/3","title":"Plausible.ClickhouseRepo.query/3","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given query. See Ecto.Adapters.SQL.query!/4 for more information.","ref":"Plausible.ClickhouseRepo.html#query!/3","title":"Plausible.ClickhouseRepo.query!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.reload/2 .","ref":"Plausible.ClickhouseRepo.html#reload/2","title":"Plausible.ClickhouseRepo.reload/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.reload!/2 .","ref":"Plausible.ClickhouseRepo.html#reload!/2","title":"Plausible.ClickhouseRepo.reload!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.start_link/1 .","ref":"Plausible.ClickhouseRepo.html#start_link/1","title":"Plausible.ClickhouseRepo.start_link/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.stop/1 .","ref":"Plausible.ClickhouseRepo.html#stop/1","title":"Plausible.ClickhouseRepo.stop/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.stream/2 .","ref":"Plausible.ClickhouseRepo.html#stream/2","title":"Plausible.ClickhouseRepo.stream/2","type":"function"},{"doc":"A convenience function for SQL-based repositories that translates the given query to SQL. See Ecto.Adapters.SQL.to_sql/3 for more information.","ref":"Plausible.ClickhouseRepo.html#to_sql/2","title":"Plausible.ClickhouseRepo.to_sql/2","type":"function"},{"doc":"Session schema for when NumericIDs migration is complete","ref":"Plausible.ClickhouseSessionV2.html","title":"Plausible.ClickhouseSessionV2","type":"module"},{"doc":"","ref":"Plausible.ClickhouseSessionV2.html#random_uint64/0","title":"Plausible.ClickhouseSessionV2.random_uint64/0","type":"function"},{"doc":"Custom type to cast Bool as UInt8","ref":"Plausible.ClickhouseSessionV2.BoolUInt8.html","title":"Plausible.ClickhouseSessionV2.BoolUInt8","type":"module"},{"doc":"Callback implementation for Ecto.Type.embed_as/1 .","ref":"Plausible.ClickhouseSessionV2.BoolUInt8.html#embed_as/1","title":"Plausible.ClickhouseSessionV2.BoolUInt8.embed_as/1","type":"function"},{"doc":"Callback implementation for Ecto.Type.equal?/2 .","ref":"Plausible.ClickhouseSessionV2.BoolUInt8.html#equal?/2","title":"Plausible.ClickhouseSessionV2.BoolUInt8.equal?/2","type":"function"},{"doc":"","ref":"Plausible.ConfigHelpers.html","title":"Plausible.ConfigHelpers","type":"module"},{"doc":"","ref":"Plausible.ConfigHelpers.html#get_int_from_path_or_env/3","title":"Plausible.ConfigHelpers.get_int_from_path_or_env/3","type":"function"},{"doc":"","ref":"Plausible.ConfigHelpers.html#get_var_from_path_or_env/3","title":"Plausible.ConfigHelpers.get_var_from_path_or_env/3","type":"function"},{"doc":"This module defines the setup for tests requiring access to the application's data layer. You may define functions here to be used as helpers in your tests. Finally, if the test case interacts with the database, it cannot be async. For this reason, every test runs inside a transaction which is reset at the beginning of the test unless the test case is marked as async.","ref":"Plausible.DataCase.html","title":"Plausible.DataCase","type":"module"},{"doc":"Base module for coordinated Clickhouse data migrations run via remote shell or otherwise (TBD).","ref":"Plausible.DataMigration.html","title":"Plausible.DataMigration","type":"module"},{"doc":"Numeric IDs migration, SQL files available at: priv/data_migrations/NumericIDs/sql","ref":"Plausible.DataMigration.NumericIDs.html","title":"Plausible.DataMigration.NumericIDs","type":"module"},{"doc":"","ref":"Plausible.DataMigration.NumericIDs.html#confirm/3","title":"Plausible.DataMigration.NumericIDs.confirm/3","type":"function"},{"doc":"","ref":"Plausible.DataMigration.NumericIDs.html#run/1","title":"Plausible.DataMigration.NumericIDs.run/1","type":"function"},{"doc":"","ref":"Plausible.DataMigration.NumericIDs.html#run_sql/2","title":"Plausible.DataMigration.NumericIDs.run_sql/2","type":"function"},{"doc":"","ref":"Plausible.DataMigration.NumericIDs.html#run_sql_confirm/2","title":"Plausible.DataMigration.NumericIDs.run_sql_confirm/2","type":"function"},{"doc":"Ecto.Repo for Clickhouse data migrations, to be started manually, outside of the main application supervision tree.","ref":"Plausible.DataMigration.Repo.html","title":"Plausible.DataMigration.Repo","type":"module"},{"doc":"Callback implementation for Ecto.Repo.aggregate/3 .","ref":"Plausible.DataMigration.Repo.html#aggregate/3","title":"Plausible.DataMigration.Repo.aggregate/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.aggregate/4 .","ref":"Plausible.DataMigration.Repo.html#aggregate/4","title":"Plausible.DataMigration.Repo.aggregate/4","type":"function"},{"doc":"Callback implementation for Ecto.Repo.all/2 .","ref":"Plausible.DataMigration.Repo.html#all/2","title":"Plausible.DataMigration.Repo.all/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.checked_out?/0 .","ref":"Plausible.DataMigration.Repo.html#checked_out?/0","title":"Plausible.DataMigration.Repo.checked_out?/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.checkout/2 .","ref":"Plausible.DataMigration.Repo.html#checkout/2","title":"Plausible.DataMigration.Repo.checkout/2","type":"function"},{"doc":"","ref":"Plausible.DataMigration.Repo.html#child_spec/1","title":"Plausible.DataMigration.Repo.child_spec/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.config/0 .","ref":"Plausible.DataMigration.Repo.html#config/0","title":"Plausible.DataMigration.Repo.config/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.default_options/1 .","ref":"Plausible.DataMigration.Repo.html#default_options/1","title":"Plausible.DataMigration.Repo.default_options/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete/2 .","ref":"Plausible.DataMigration.Repo.html#delete/2","title":"Plausible.DataMigration.Repo.delete/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete!/2 .","ref":"Plausible.DataMigration.Repo.html#delete!/2","title":"Plausible.DataMigration.Repo.delete!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete_all/2 .","ref":"Plausible.DataMigration.Repo.html#delete_all/2","title":"Plausible.DataMigration.Repo.delete_all/2","type":"function"},{"doc":"A convenience function for SQL-based repositories that forces all connections in the pool to disconnect within the given interval. See Ecto.Adapters.SQL.disconnect_all/3 for more information.","ref":"Plausible.DataMigration.Repo.html#disconnect_all/2","title":"Plausible.DataMigration.Repo.disconnect_all/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.exists?/2 .","ref":"Plausible.DataMigration.Repo.html#exists?/2","title":"Plausible.DataMigration.Repo.exists?/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get/3 .","ref":"Plausible.DataMigration.Repo.html#get/3","title":"Plausible.DataMigration.Repo.get/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get!/3 .","ref":"Plausible.DataMigration.Repo.html#get!/3","title":"Plausible.DataMigration.Repo.get!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_by/3 .","ref":"Plausible.DataMigration.Repo.html#get_by/3","title":"Plausible.DataMigration.Repo.get_by/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_by!/3 .","ref":"Plausible.DataMigration.Repo.html#get_by!/3","title":"Plausible.DataMigration.Repo.get_by!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_dynamic_repo/0 .","ref":"Plausible.DataMigration.Repo.html#get_dynamic_repo/0","title":"Plausible.DataMigration.Repo.get_dynamic_repo/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert/2 .","ref":"Plausible.DataMigration.Repo.html#insert/2","title":"Plausible.DataMigration.Repo.insert/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert!/2 .","ref":"Plausible.DataMigration.Repo.html#insert!/2","title":"Plausible.DataMigration.Repo.insert!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_all/3 .","ref":"Plausible.DataMigration.Repo.html#insert_all/3","title":"Plausible.DataMigration.Repo.insert_all/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_or_update/2 .","ref":"Plausible.DataMigration.Repo.html#insert_or_update/2","title":"Plausible.DataMigration.Repo.insert_or_update/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_or_update!/2 .","ref":"Plausible.DataMigration.Repo.html#insert_or_update!/2","title":"Plausible.DataMigration.Repo.insert_or_update!/2","type":"function"},{"doc":"Similar to insert_all/2 but with the following differences: accepts rows as streams or lists sends rows as a chunked request doesn't autogenerate ids or does any other preprocessing Example: Repo . query! ( "create table ecto_ch_demo(a UInt64, b String) engine Null" ) defmodule Demo do use Ecto.Schema @primary_key false schema "ecto_ch_demo" do field :a , Ch , type : "UInt64" field :b , :string end end rows = Stream . map ( 1 .. 100_000 , fn i -> %{ a : i , b : to_string ( i ) } end ) { 100_000 , nil } = Repo . insert_stream ( Demo , rows ) # schemaless { 100_000 , nil } = Repo . insert_stream ( "ecto_ch_demo" , rows , types : [ a : Ch.Types . u64 ( ) , b : :string ] )","ref":"Plausible.DataMigration.Repo.html#insert_stream/3","title":"Plausible.DataMigration.Repo.insert_stream/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.load/2 .","ref":"Plausible.DataMigration.Repo.html#load/2","title":"Plausible.DataMigration.Repo.load/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.one/2 .","ref":"Plausible.DataMigration.Repo.html#one/2","title":"Plausible.DataMigration.Repo.one/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.one!/2 .","ref":"Plausible.DataMigration.Repo.html#one!/2","title":"Plausible.DataMigration.Repo.one!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.preload/3 .","ref":"Plausible.DataMigration.Repo.html#preload/3","title":"Plausible.DataMigration.Repo.preload/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.prepare_query/3 .","ref":"Plausible.DataMigration.Repo.html#prepare_query/3","title":"Plausible.DataMigration.Repo.prepare_query/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.put_dynamic_repo/1 .","ref":"Plausible.DataMigration.Repo.html#put_dynamic_repo/1","title":"Plausible.DataMigration.Repo.put_dynamic_repo/1","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given query. See Ecto.Adapters.SQL.query/4 for more information.","ref":"Plausible.DataMigration.Repo.html#query/3","title":"Plausible.DataMigration.Repo.query/3","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given query. See Ecto.Adapters.SQL.query!/4 for more information.","ref":"Plausible.DataMigration.Repo.html#query!/3","title":"Plausible.DataMigration.Repo.query!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.reload/2 .","ref":"Plausible.DataMigration.Repo.html#reload/2","title":"Plausible.DataMigration.Repo.reload/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.reload!/2 .","ref":"Plausible.DataMigration.Repo.html#reload!/2","title":"Plausible.DataMigration.Repo.reload!/2","type":"function"},{"doc":"","ref":"Plausible.DataMigration.Repo.html#start/2","title":"Plausible.DataMigration.Repo.start/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.start_link/1 .","ref":"Plausible.DataMigration.Repo.html#start_link/1","title":"Plausible.DataMigration.Repo.start_link/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.stop/1 .","ref":"Plausible.DataMigration.Repo.html#stop/1","title":"Plausible.DataMigration.Repo.stop/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.stream/2 .","ref":"Plausible.DataMigration.Repo.html#stream/2","title":"Plausible.DataMigration.Repo.stream/2","type":"function"},{"doc":"A convenience function for SQL-based repositories that translates the given query to SQL. See Ecto.Adapters.SQL.to_sql/3 for more information.","ref":"Plausible.DataMigration.Repo.html#to_sql/2","title":"Plausible.DataMigration.Repo.to_sql/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update/2 .","ref":"Plausible.DataMigration.Repo.html#update/2","title":"Plausible.DataMigration.Repo.update/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update!/2 .","ref":"Plausible.DataMigration.Repo.html#update!/2","title":"Plausible.DataMigration.Repo.update!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update_all/3 .","ref":"Plausible.DataMigration.Repo.html#update_all/3","title":"Plausible.DataMigration.Repo.update_all/3","type":"function"},{"doc":"Custom type for event name. Accepts Strings and Integers and stores them as String. Returns cast error if any other type is provided. Accepting integers is important for 404 tracking.","ref":"Plausible.Ecto.EventName.html","title":"Plausible.Ecto.EventName","type":"module"},{"doc":"Callback implementation for Ecto.Type.cast/1 .","ref":"Plausible.Ecto.EventName.html#cast/1","title":"Plausible.Ecto.EventName.cast/1","type":"function"},{"doc":"Callback implementation for Ecto.Type.dump/1 .","ref":"Plausible.Ecto.EventName.html#dump/1","title":"Plausible.Ecto.EventName.dump/1","type":"function"},{"doc":"Callback implementation for Ecto.Type.embed_as/1 .","ref":"Plausible.Ecto.EventName.html#embed_as/1","title":"Plausible.Ecto.EventName.embed_as/1","type":"function"},{"doc":"Callback implementation for Ecto.Type.equal?/2 .","ref":"Plausible.Ecto.EventName.html#equal?/2","title":"Plausible.Ecto.EventName.equal?/2","type":"function"},{"doc":"Callback implementation for Ecto.Type.load/1 .","ref":"Plausible.Ecto.EventName.html#load/1","title":"Plausible.Ecto.EventName.load/1","type":"function"},{"doc":"Callback implementation for Ecto.Type.type/0 .","ref":"Plausible.Ecto.EventName.html#type/0","title":"Plausible.Ecto.EventName.type/0","type":"function"},{"doc":"","ref":"Plausible.Event.WriteBuffer.html","title":"Plausible.Event.WriteBuffer","type":"module"},{"doc":"Returns a specification to start this module under a supervisor. See Supervisor .","ref":"Plausible.Event.WriteBuffer.html#child_spec/1","title":"Plausible.Event.WriteBuffer.child_spec/1","type":"function"},{"doc":"","ref":"Plausible.Event.WriteBuffer.html#flush/0","title":"Plausible.Event.WriteBuffer.flush/0","type":"function"},{"doc":"Callback implementation for GenServer.init/1 .","ref":"Plausible.Event.WriteBuffer.html#init/1","title":"Plausible.Event.WriteBuffer.init/1","type":"function"},{"doc":"","ref":"Plausible.Event.WriteBuffer.html#insert/1","title":"Plausible.Event.WriteBuffer.insert/1","type":"function"},{"doc":"","ref":"Plausible.Event.WriteBuffer.html#start_link/1","title":"Plausible.Event.WriteBuffer.start_link/1","type":"function"},{"doc":"","ref":"Plausible.Factory.html","title":"Plausible.Factory","type":"module"},{"doc":"","ref":"Plausible.Factory.html#api_key_factory/0","title":"Plausible.Factory.api_key_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#build/2","title":"Plausible.Factory.build/2","type":"function"},{"doc":"","ref":"Plausible.Factory.html#build_list/3","title":"Plausible.Factory.build_list/3","type":"function"},{"doc":"","ref":"Plausible.Factory.html#build_pair/2","title":"Plausible.Factory.build_pair/2","type":"function"},{"doc":"","ref":"Plausible.Factory.html#ch_session_factory/0","title":"Plausible.Factory.ch_session_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#create/1","title":"Plausible.Factory.create/1","type":"function"},{"doc":"","ref":"Plausible.Factory.html#create/2","title":"Plausible.Factory.create/2","type":"function"},{"doc":"","ref":"Plausible.Factory.html#create_list/3","title":"Plausible.Factory.create_list/3","type":"function"},{"doc":"","ref":"Plausible.Factory.html#create_pair/2","title":"Plausible.Factory.create_pair/2","type":"function"},{"doc":"","ref":"Plausible.Factory.html#custom_domain_factory/0","title":"Plausible.Factory.custom_domain_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#enterprise_plan_factory/0","title":"Plausible.Factory.enterprise_plan_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#event_factory/0","title":"Plausible.Factory.event_factory/0","type":"function"},{"doc":"Raises a helpful error if no factory is defined.","ref":"Plausible.Factory.html#factory/1","title":"Plausible.Factory.factory/1","type":"function"},{"doc":"","ref":"Plausible.Factory.html#goal_factory/0","title":"Plausible.Factory.goal_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#google_auth_factory/0","title":"Plausible.Factory.google_auth_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#imported_browsers_factory/0","title":"Plausible.Factory.imported_browsers_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#imported_devices_factory/0","title":"Plausible.Factory.imported_devices_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#imported_entry_pages_factory/0","title":"Plausible.Factory.imported_entry_pages_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#imported_exit_pages_factory/0","title":"Plausible.Factory.imported_exit_pages_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#imported_locations_factory/0","title":"Plausible.Factory.imported_locations_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#imported_operating_systems_factory/0","title":"Plausible.Factory.imported_operating_systems_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#imported_pages_factory/0","title":"Plausible.Factory.imported_pages_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#imported_sources_factory/0","title":"Plausible.Factory.imported_sources_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#imported_visitors_factory/0","title":"Plausible.Factory.imported_visitors_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#insert/1","title":"Plausible.Factory.insert/1","type":"function"},{"doc":"","ref":"Plausible.Factory.html#insert/2","title":"Plausible.Factory.insert/2","type":"function"},{"doc":"","ref":"Plausible.Factory.html#insert/3","title":"Plausible.Factory.insert/3","type":"function"},{"doc":"","ref":"Plausible.Factory.html#insert_list/3","title":"Plausible.Factory.insert_list/3","type":"function"},{"doc":"","ref":"Plausible.Factory.html#insert_list/4","title":"Plausible.Factory.insert_list/4","type":"function"},{"doc":"","ref":"Plausible.Factory.html#insert_pair/2","title":"Plausible.Factory.insert_pair/2","type":"function"},{"doc":"","ref":"Plausible.Factory.html#insert_pair/3","title":"Plausible.Factory.insert_pair/3","type":"function"},{"doc":"","ref":"Plausible.Factory.html#invitation_factory/0","title":"Plausible.Factory.invitation_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#monthly_report_factory/0","title":"Plausible.Factory.monthly_report_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#pageview_factory/0","title":"Plausible.Factory.pageview_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#params_for/2","title":"Plausible.Factory.params_for/2","type":"function"},{"doc":"","ref":"Plausible.Factory.html#params_with_assocs/2","title":"Plausible.Factory.params_with_assocs/2","type":"function"},{"doc":"","ref":"Plausible.Factory.html#shared_link_factory/0","title":"Plausible.Factory.shared_link_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#site_factory/0","title":"Plausible.Factory.site_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#site_membership_factory/0","title":"Plausible.Factory.site_membership_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#spike_notification_factory/0","title":"Plausible.Factory.spike_notification_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#string_params_for/2","title":"Plausible.Factory.string_params_for/2","type":"function"},{"doc":"","ref":"Plausible.Factory.html#string_params_with_assocs/2","title":"Plausible.Factory.string_params_with_assocs/2","type":"function"},{"doc":"","ref":"Plausible.Factory.html#subscription_factory/0","title":"Plausible.Factory.subscription_factory/0","type":"function"},{"doc":"","ref":"Plausible.Factory.html#user_factory/1","title":"Plausible.Factory.user_factory/1","type":"function"},{"doc":"","ref":"Plausible.Factory.html#weekly_report_factory/0","title":"Plausible.Factory.weekly_report_factory/0","type":"function"},{"doc":"A funnel is a marketing term used to capture and describe the journey that users go through, from initial step to conversion. A funnel consists of several steps (here: 2..8). This module defines the database schema for storing funnels and changeset helpers for enumerating the steps within. Each step references a goal (either a Custom Event or Visit) see: Plausible.Goal .","ref":"Plausible.Funnel.html","title":"Plausible.Funnel","type":"module"},{"doc":"","ref":"Plausible.Funnel.html#changeset/2","title":"Plausible.Funnel.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Funnel.html#max_steps/0","title":"Plausible.Funnel.max_steps/0","type":"macro"},{"doc":"","ref":"Plausible.Funnel.html#min_steps/0","title":"Plausible.Funnel.min_steps/0","type":"macro"},{"doc":"","ref":"Plausible.Funnel.html#put_step_orders/1","title":"Plausible.Funnel.put_step_orders/1","type":"function"},{"doc":"","ref":"Plausible.Funnel.html#t:t/0","title":"Plausible.Funnel.t/0","type":"type"},{"doc":"This module defines the database schema for a single Funnel step. See: Plausible.Funnel for more information.","ref":"Plausible.Funnel.Step.html","title":"Plausible.Funnel.Step","type":"module"},{"doc":"","ref":"Plausible.Funnel.Step.html#changeset/2","title":"Plausible.Funnel.Step.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Funnel.Step.html#t:t/0","title":"Plausible.Funnel.Step.t/0","type":"type"},{"doc":"This module implements contextual Funnel interface, allowing listing, creating and deleting funnel definitions. For brief explanation of what a Funnel is, please see Plausible.Funnel schema. See Plausible.Stats.Funnel for the evaluation logic.","ref":"Plausible.Funnels.html","title":"Plausible.Funnels","type":"module"},{"doc":"","ref":"Plausible.Funnels.html#create/3","title":"Plausible.Funnels.create/3","type":"function"},{"doc":"","ref":"Plausible.Funnels.html#create_changeset/3","title":"Plausible.Funnels.create_changeset/3","type":"function"},{"doc":"","ref":"Plausible.Funnels.html#delete/2","title":"Plausible.Funnels.delete/2","type":"function"},{"doc":"","ref":"Plausible.Funnels.html#enabled_for?/1","title":"Plausible.Funnels.enabled_for?/1","type":"function"},{"doc":"","ref":"Plausible.Funnels.html#ephemeral_definition/3","title":"Plausible.Funnels.ephemeral_definition/3","type":"function"},{"doc":"","ref":"Plausible.Funnels.html#get/2","title":"Plausible.Funnels.get/2","type":"function"},{"doc":"","ref":"Plausible.Funnels.html#list/1","title":"Plausible.Funnels.list/1","type":"function"},{"doc":"This module provides an API for fetching IP geolocation.","ref":"Plausible.Geo.html","title":"Plausible.Geo","type":"module"},{"doc":"Waits for the database to start after calling load_db/1 with the async option.","ref":"Plausible.Geo.html#await_loader/0","title":"Plausible.Geo.await_loader/0","type":"function"},{"doc":"Returns geodatabase type. Used for deciding whether to show the DB-IP disclaimer or not. Examples In the case of a DB-IP database: iex> database_type ( ) "DBIP-City-Lite" In the case of a MaxMind database: iex> database_type ( ) "GeoLite2-City"","ref":"Plausible.Geo.html#database_type/0","title":"Plausible.Geo.database_type/0","type":"function"},{"doc":"Starts the geodatabase loading process. Two modes are supported: local file and MaxMind license key. Options :path - the path to the .mmdb database local file. When present, :license_key and :edition are not required. :license_key - the license key from MaxMind to authenticate requests to MaxMind. :edition - the name of the MaxMind database to be downloaded from MaxMind servers. Defaults to GeoLite2-City . :async - when used, configures the database loading to run asynchronously. Examples Loading from a local file: iex> load_db ( path : "/etc/plausible/dbip-city.mmdb" ) :ok Downloading a MaxMind DB (this license key is no longer active): iex> load_db ( license_key : "LNpsJCCKPis6XvBP" , edition : "GeoLite2-City" , async : true ) :ok","ref":"Plausible.Geo.html#load_db/1","title":"Plausible.Geo.load_db/1","type":"function"},{"doc":"Looks up geo info about an IP address. Examples iex> lookup ( "8.7.6.5" ) %{ "city" => %{ "geoname_id" => 5349755 , "names" => %{ "de" => "Fontana" , "en" => "Fontana" , "ja" => "フォンタナ" , "ru" => "Фонтана" } } , "continent" => %{ "code" => "NA" , "geoname_id" => 6255149 , "names" => %{ "de" => "Nordamerika" , "en" => "North America" , "es" => "Norteamérica" , "fr" => "Amérique du Nord" , "ja" => "北アメリカ" , "pt-BR" => "América do Norte" , "ru" => "Северная Америка" , "zh-CN" => "北美洲" } } , "country" => %{ "geoname_id" => 6252001 , "iso_code" => "US" , "names" => %{ "de" => "Vereinigte Staaten" , "en" => "United States" , "es" => "Estados Unidos" , "fr" => "États Unis" , "ja" => "アメリカ" , "pt-BR" => "EUA" , "ru" => "США" , "zh-CN" => "美国" } } , "location" => %{ "accuracy_radius" => 50 , "latitude" => 34.1211 , "longitude" => - 117.4362 , "metro_code" => 803 , "time_zone" => "America/Los_Angeles" } , "postal" => %{ "code" => "92336" } , "registered_country" => %{ "geoname_id" => 6252001 , "iso_code" => "US" , "names" => %{ "de" => "Vereinigte Staaten" , "en" => "United States" , "es" => "Estados Unidos" , "fr" => "États Unis" , "ja" => "アメリカ" , "pt-BR" => "EUA" , "ru" => "США" , "zh-CN" => "美国" } } , "subdivisions" => [ %{ "geoname_id" => 5332921 , "iso_code" => "CA" , "names" => %{ "de" => "Kalifornien" , "en" => "California" , "es" => "California" , "fr" => "Californie" , "ja" => "カリフォルニア州" , "pt-BR" => "Califórnia" , "ru" => "Калифорния" , "zh-CN" => "加州" } } ] }","ref":"Plausible.Geo.html#lookup/1","title":"Plausible.Geo.lookup/1","type":"function"},{"doc":"","ref":"Plausible.Goal.html","title":"Plausible.Goal","type":"module"},{"doc":"","ref":"Plausible.Goal.html#changeset/2","title":"Plausible.Goal.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Goal.html#currency_options/0","title":"Plausible.Goal.currency_options/0","type":"function"},{"doc":"","ref":"Plausible.Goal.html#revenue?/1","title":"Plausible.Goal.revenue?/1","type":"function"},{"doc":"","ref":"Plausible.Goal.html#valid_currencies/0","title":"Plausible.Goal.valid_currencies/0","type":"function"},{"doc":"","ref":"Plausible.Goal.html#t:t/0","title":"Plausible.Goal.t/0","type":"type"},{"doc":"","ref":"Plausible.Goals.html","title":"Plausible.Goals","type":"module"},{"doc":"","ref":"Plausible.Goals.html#count/1","title":"Plausible.Goals.count/1","type":"function"},{"doc":"Creates a Goal for a site. If the created goal is a revenue goal, it sets site.updated_at to be refreshed by the sites cache, as revenue goals are used during ingestion.","ref":"Plausible.Goals.html#create/3","title":"Plausible.Goals.create/3","type":"function"},{"doc":"If a goal belongs to funnel(s), we need to inspect their number of steps. If it exceeds the minimum allowed (defined via Plausible.Funnel.min_steps/0 ), the funnel will be reduced (i.e. a step associated with the goal to be deleted is removed), so that the minimum number of steps is preserved. This is done implicitly, by postgres, as per on_delete: :delete_all. Otherwise, for associated funnel(s) consisting of minimum number steps only, funnel record(s) are removed completely along with the targeted goal.","ref":"Plausible.Goals.html#delete/2","title":"Plausible.Goals.delete/2","type":"function"},{"doc":"","ref":"Plausible.Goals.html#find_or_create/2","title":"Plausible.Goals.find_or_create/2","type":"function"},{"doc":"","ref":"Plausible.Goals.html#for_site/2","title":"Plausible.Goals.for_site/2","type":"function"},{"doc":"","ref":"Plausible.Google.Api.html","title":"Plausible.Google.Api","type":"module"},{"doc":"","ref":"Plausible.Google.Api.html#fetch_and_persist/3","title":"Plausible.Google.Api.fetch_and_persist/3","type":"function"},{"doc":"","ref":"Plausible.Google.Api.html#fetch_stats/3","title":"Plausible.Google.Api.fetch_stats/3","type":"function"},{"doc":"","ref":"Plausible.Google.Api.html#fetch_verified_properties/1","title":"Plausible.Google.Api.fetch_verified_properties/1","type":"function"},{"doc":"Returns a single Google Analytics view if the user has access to it.","ref":"Plausible.Google.Api.html#get_view/2","title":"Plausible.Google.Api.get_view/2","type":"function"},{"doc":"Imports stats from a Google Analytics UA view to a Plausible site. This function fetches Google Analytics reports in batches of 7500 per request. The batches are then buffered to Clickhouse by the Plausible.Google.Buffer process. Requests to Google Analytics can fail, and are retried at most 5 times with an exponential backoff. Returns :ok when importing has finished or {:error, term()} when a request to GA failed too many times. Useful links: Feature documentation GA API reference GA Dimensions reference","ref":"Plausible.Google.Api.html#import_analytics/4","title":"Plausible.Google.Api.import_analytics/4","type":"function"},{"doc":"","ref":"Plausible.Google.Api.html#import_authorize_url/2","title":"Plausible.Google.Api.import_authorize_url/2","type":"function"},{"doc":"Lists Google Analytics views grouped by hostname.","ref":"Plausible.Google.Api.html#list_views/1","title":"Plausible.Google.Api.list_views/1","type":"function"},{"doc":"","ref":"Plausible.Google.Api.html#search_console_authorize_url/2","title":"Plausible.Google.Api.search_console_authorize_url/2","type":"function"},{"doc":"","ref":"Plausible.Google.Api.html#t:google_analytics_view/0","title":"Plausible.Google.Api.google_analytics_view/0","type":"type"},{"doc":"","ref":"Plausible.Google.Api.html#t:import_auth/0","title":"Plausible.Google.Api.import_auth/0","type":"type"},{"doc":"","ref":"Plausible.Google.Api.Mock.html","title":"Plausible.Google.Api.Mock","type":"module"},{"doc":"","ref":"Plausible.Google.Api.Mock.html#fetch_stats/3","title":"Plausible.Google.Api.Mock.fetch_stats/3","type":"function"},{"doc":"This GenServer inserts records into Clickhouse imported_* tables. Multiple buffers are automatically created for each table. Records are flushed when the table buffer reaches the maximum size, defined by max_buffer_size/0 .","ref":"Plausible.Google.Buffer.html","title":"Plausible.Google.Buffer","type":"module"},{"doc":"Returns a specification to start this module under a supervisor. See Supervisor .","ref":"Plausible.Google.Buffer.html#child_spec/1","title":"Plausible.Google.Buffer.child_spec/1","type":"function"},{"doc":"Flushes all table buffers to Clickhouse.","ref":"Plausible.Google.Buffer.html#flush/2","title":"Plausible.Google.Buffer.flush/2","type":"function"},{"doc":"Callback implementation for GenServer.handle_continue/2 .","ref":"Plausible.Google.Buffer.html#handle_continue/2","title":"Plausible.Google.Buffer.handle_continue/2","type":"function"},{"doc":"Callback implementation for GenServer.init/1 .","ref":"Plausible.Google.Buffer.html#init/1","title":"Plausible.Google.Buffer.init/1","type":"function"},{"doc":"Puts the given records into the table buffer.","ref":"Plausible.Google.Buffer.html#insert_many/3","title":"Plausible.Google.Buffer.insert_many/3","type":"function"},{"doc":"Returns the total count of items in the given table buffer.","ref":"Plausible.Google.Buffer.html#size/2","title":"Plausible.Google.Buffer.size/2","type":"function"},{"doc":"","ref":"Plausible.Google.Buffer.html#start_link/0","title":"Plausible.Google.Buffer.start_link/0","type":"function"},{"doc":"","ref":"Plausible.Google.Buffer.html#stop/1","title":"Plausible.Google.Buffer.stop/1","type":"function"},{"doc":"","ref":"Plausible.Google.HTTP.html","title":"Plausible.Google.HTTP","type":"module"},{"doc":"","ref":"Plausible.Google.HTTP.html#fetch_access_token/1","title":"Plausible.Google.HTTP.fetch_access_token/1","type":"function"},{"doc":"","ref":"Plausible.Google.HTTP.html#get_analytics_start_date/2","title":"Plausible.Google.HTTP.get_analytics_start_date/2","type":"function"},{"doc":"","ref":"Plausible.Google.HTTP.html#get_report/1","title":"Plausible.Google.HTTP.get_report/1","type":"function"},{"doc":"","ref":"Plausible.Google.HTTP.html#list_sites/1","title":"Plausible.Google.HTTP.list_sites/1","type":"function"},{"doc":"","ref":"Plausible.Google.HTTP.html#list_stats/5","title":"Plausible.Google.HTTP.list_stats/5","type":"function"},{"doc":"","ref":"Plausible.Google.HTTP.html#list_views_for_user/1","title":"Plausible.Google.HTTP.list_views_for_user/1","type":"function"},{"doc":"","ref":"Plausible.Google.HTTP.html#refresh_auth_token/1","title":"Plausible.Google.HTTP.refresh_auth_token/1","type":"function"},{"doc":"","ref":"Plausible.Google.ReportRequest.html","title":"Plausible.Google.ReportRequest","type":"module"},{"doc":"","ref":"Plausible.Google.ReportRequest.html#full_report/0","title":"Plausible.Google.ReportRequest.full_report/0","type":"function"},{"doc":"","ref":"Plausible.Google.ReportRequest.html#t:t/0","title":"Plausible.Google.ReportRequest.t/0","type":"type"},{"doc":"HTTP Client built on top of Finch. By default, request parameters are json-encoded. If a raw binary value is supplied, no encoding is performed. If x-www-form-urlencoded content-type is set in headers, URL encoding is invoked.","ref":"Plausible.HTTPClient.html","title":"Plausible.HTTPClient","type":"module"},{"doc":"Make a GET request","ref":"Plausible.HTTPClient.html#get/2","title":"Plausible.HTTPClient.get/2","type":"function"},{"doc":"","ref":"Plausible.HTTPClient.html#impl/0","title":"Plausible.HTTPClient.impl/0","type":"function"},{"doc":"Make a POST request","ref":"Plausible.HTTPClient.html#post/4","title":"Plausible.HTTPClient.post/4","type":"function"},{"doc":"","ref":"Plausible.HTTPClient.Interface.html","title":"Plausible.HTTPClient.Interface","type":"behaviour"},{"doc":"","ref":"Plausible.HTTPClient.Interface.html#c:get/1","title":"Plausible.HTTPClient.Interface.get/1","type":"callback"},{"doc":"","ref":"Plausible.HTTPClient.Interface.html#c:get/2","title":"Plausible.HTTPClient.Interface.get/2","type":"callback"},{"doc":"","ref":"Plausible.HTTPClient.Interface.html#c:post/3","title":"Plausible.HTTPClient.Interface.post/3","type":"callback"},{"doc":"","ref":"Plausible.HTTPClient.Interface.html#c:post/4","title":"Plausible.HTTPClient.Interface.post/4","type":"callback"},{"doc":"","ref":"Plausible.HTTPClient.Interface.html#t:finch_request_opts/0","title":"Plausible.HTTPClient.Interface.finch_request_opts/0","type":"type"},{"doc":"","ref":"Plausible.HTTPClient.Interface.html#t:headers/0","title":"Plausible.HTTPClient.Interface.headers/0","type":"type"},{"doc":"","ref":"Plausible.HTTPClient.Interface.html#t:params/0","title":"Plausible.HTTPClient.Interface.params/0","type":"type"},{"doc":"","ref":"Plausible.HTTPClient.Interface.html#t:response/0","title":"Plausible.HTTPClient.Interface.response/0","type":"type"},{"doc":"","ref":"Plausible.HTTPClient.Interface.html#t:url/0","title":"Plausible.HTTPClient.Interface.url/0","type":"type"},{"doc":"","ref":"Plausible.HTTPClient.Non200Error.html","title":"Plausible.HTTPClient.Non200Error","type":"module"},{"doc":"","ref":"Plausible.HTTPClient.Non200Error.html#new/1","title":"Plausible.HTTPClient.Non200Error.new/1","type":"function"},{"doc":"","ref":"Plausible.HTTPClient.Non200Error.html#t:t/0","title":"Plausible.HTTPClient.Non200Error.t/0","type":"type"},{"doc":"A dedicated repo for import related mutations","ref":"Plausible.ImportDeletionRepo.html","title":"Plausible.ImportDeletionRepo","type":"module"},{"doc":"Callback implementation for Ecto.Repo.aggregate/3 .","ref":"Plausible.ImportDeletionRepo.html#aggregate/3","title":"Plausible.ImportDeletionRepo.aggregate/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.aggregate/4 .","ref":"Plausible.ImportDeletionRepo.html#aggregate/4","title":"Plausible.ImportDeletionRepo.aggregate/4","type":"function"},{"doc":"Callback implementation for Ecto.Repo.all/2 .","ref":"Plausible.ImportDeletionRepo.html#all/2","title":"Plausible.ImportDeletionRepo.all/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.checked_out?/0 .","ref":"Plausible.ImportDeletionRepo.html#checked_out?/0","title":"Plausible.ImportDeletionRepo.checked_out?/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.checkout/2 .","ref":"Plausible.ImportDeletionRepo.html#checkout/2","title":"Plausible.ImportDeletionRepo.checkout/2","type":"function"},{"doc":"","ref":"Plausible.ImportDeletionRepo.html#child_spec/1","title":"Plausible.ImportDeletionRepo.child_spec/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.config/0 .","ref":"Plausible.ImportDeletionRepo.html#config/0","title":"Plausible.ImportDeletionRepo.config/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.default_options/1 .","ref":"Plausible.ImportDeletionRepo.html#default_options/1","title":"Plausible.ImportDeletionRepo.default_options/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete/2 .","ref":"Plausible.ImportDeletionRepo.html#delete/2","title":"Plausible.ImportDeletionRepo.delete/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete!/2 .","ref":"Plausible.ImportDeletionRepo.html#delete!/2","title":"Plausible.ImportDeletionRepo.delete!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete_all/2 .","ref":"Plausible.ImportDeletionRepo.html#delete_all/2","title":"Plausible.ImportDeletionRepo.delete_all/2","type":"function"},{"doc":"A convenience function for SQL-based repositories that forces all connections in the pool to disconnect within the given interval. See Ecto.Adapters.SQL.disconnect_all/3 for more information.","ref":"Plausible.ImportDeletionRepo.html#disconnect_all/2","title":"Plausible.ImportDeletionRepo.disconnect_all/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.exists?/2 .","ref":"Plausible.ImportDeletionRepo.html#exists?/2","title":"Plausible.ImportDeletionRepo.exists?/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get/3 .","ref":"Plausible.ImportDeletionRepo.html#get/3","title":"Plausible.ImportDeletionRepo.get/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get!/3 .","ref":"Plausible.ImportDeletionRepo.html#get!/3","title":"Plausible.ImportDeletionRepo.get!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_by/3 .","ref":"Plausible.ImportDeletionRepo.html#get_by/3","title":"Plausible.ImportDeletionRepo.get_by/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_by!/3 .","ref":"Plausible.ImportDeletionRepo.html#get_by!/3","title":"Plausible.ImportDeletionRepo.get_by!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_dynamic_repo/0 .","ref":"Plausible.ImportDeletionRepo.html#get_dynamic_repo/0","title":"Plausible.ImportDeletionRepo.get_dynamic_repo/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert/2 .","ref":"Plausible.ImportDeletionRepo.html#insert/2","title":"Plausible.ImportDeletionRepo.insert/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert!/2 .","ref":"Plausible.ImportDeletionRepo.html#insert!/2","title":"Plausible.ImportDeletionRepo.insert!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_all/3 .","ref":"Plausible.ImportDeletionRepo.html#insert_all/3","title":"Plausible.ImportDeletionRepo.insert_all/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_or_update/2 .","ref":"Plausible.ImportDeletionRepo.html#insert_or_update/2","title":"Plausible.ImportDeletionRepo.insert_or_update/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_or_update!/2 .","ref":"Plausible.ImportDeletionRepo.html#insert_or_update!/2","title":"Plausible.ImportDeletionRepo.insert_or_update!/2","type":"function"},{"doc":"Similar to insert_all/2 but with the following differences: accepts rows as streams or lists sends rows as a chunked request doesn't autogenerate ids or does any other preprocessing Example: Repo . query! ( "create table ecto_ch_demo(a UInt64, b String) engine Null" ) defmodule Demo do use Ecto.Schema @primary_key false schema "ecto_ch_demo" do field :a , Ch , type : "UInt64" field :b , :string end end rows = Stream . map ( 1 .. 100_000 , fn i -> %{ a : i , b : to_string ( i ) } end ) { 100_000 , nil } = Repo . insert_stream ( Demo , rows ) # schemaless { 100_000 , nil } = Repo . insert_stream ( "ecto_ch_demo" , rows , types : [ a : Ch.Types . u64 ( ) , b : :string ] )","ref":"Plausible.ImportDeletionRepo.html#insert_stream/3","title":"Plausible.ImportDeletionRepo.insert_stream/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.load/2 .","ref":"Plausible.ImportDeletionRepo.html#load/2","title":"Plausible.ImportDeletionRepo.load/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.one/2 .","ref":"Plausible.ImportDeletionRepo.html#one/2","title":"Plausible.ImportDeletionRepo.one/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.one!/2 .","ref":"Plausible.ImportDeletionRepo.html#one!/2","title":"Plausible.ImportDeletionRepo.one!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.preload/3 .","ref":"Plausible.ImportDeletionRepo.html#preload/3","title":"Plausible.ImportDeletionRepo.preload/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.prepare_query/3 .","ref":"Plausible.ImportDeletionRepo.html#prepare_query/3","title":"Plausible.ImportDeletionRepo.prepare_query/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.put_dynamic_repo/1 .","ref":"Plausible.ImportDeletionRepo.html#put_dynamic_repo/1","title":"Plausible.ImportDeletionRepo.put_dynamic_repo/1","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given query. See Ecto.Adapters.SQL.query/4 for more information.","ref":"Plausible.ImportDeletionRepo.html#query/3","title":"Plausible.ImportDeletionRepo.query/3","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given query. See Ecto.Adapters.SQL.query!/4 for more information.","ref":"Plausible.ImportDeletionRepo.html#query!/3","title":"Plausible.ImportDeletionRepo.query!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.reload/2 .","ref":"Plausible.ImportDeletionRepo.html#reload/2","title":"Plausible.ImportDeletionRepo.reload/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.reload!/2 .","ref":"Plausible.ImportDeletionRepo.html#reload!/2","title":"Plausible.ImportDeletionRepo.reload!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.start_link/1 .","ref":"Plausible.ImportDeletionRepo.html#start_link/1","title":"Plausible.ImportDeletionRepo.start_link/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.stop/1 .","ref":"Plausible.ImportDeletionRepo.html#stop/1","title":"Plausible.ImportDeletionRepo.stop/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.stream/2 .","ref":"Plausible.ImportDeletionRepo.html#stream/2","title":"Plausible.ImportDeletionRepo.stream/2","type":"function"},{"doc":"A convenience function for SQL-based repositories that translates the given query to SQL. See Ecto.Adapters.SQL.to_sql/3 for more information.","ref":"Plausible.ImportDeletionRepo.html#to_sql/2","title":"Plausible.ImportDeletionRepo.to_sql/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update/2 .","ref":"Plausible.ImportDeletionRepo.html#update/2","title":"Plausible.ImportDeletionRepo.update/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update!/2 .","ref":"Plausible.ImportDeletionRepo.html#update!/2","title":"Plausible.ImportDeletionRepo.update!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update_all/3 .","ref":"Plausible.ImportDeletionRepo.html#update_all/3","title":"Plausible.ImportDeletionRepo.update_all/3","type":"function"},{"doc":"","ref":"Plausible.Imported.html","title":"Plausible.Imported","type":"module"},{"doc":"","ref":"Plausible.Imported.html#forget/1","title":"Plausible.Imported.forget/1","type":"function"},{"doc":"","ref":"Plausible.Imported.html#from_google_analytics/3","title":"Plausible.Imported.from_google_analytics/3","type":"function"},{"doc":"","ref":"Plausible.Imported.html#tables/0","title":"Plausible.Imported.tables/0","type":"function"},{"doc":"Write-centric Clickhouse access interface","ref":"Plausible.IngestRepo.html","title":"Plausible.IngestRepo","type":"module"},{"doc":"Callback implementation for Ecto.Repo.aggregate/3 .","ref":"Plausible.IngestRepo.html#aggregate/3","title":"Plausible.IngestRepo.aggregate/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.aggregate/4 .","ref":"Plausible.IngestRepo.html#aggregate/4","title":"Plausible.IngestRepo.aggregate/4","type":"function"},{"doc":"Callback implementation for Ecto.Repo.all/2 .","ref":"Plausible.IngestRepo.html#all/2","title":"Plausible.IngestRepo.all/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.checked_out?/0 .","ref":"Plausible.IngestRepo.html#checked_out?/0","title":"Plausible.IngestRepo.checked_out?/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.checkout/2 .","ref":"Plausible.IngestRepo.html#checkout/2","title":"Plausible.IngestRepo.checkout/2","type":"function"},{"doc":"","ref":"Plausible.IngestRepo.html#child_spec/1","title":"Plausible.IngestRepo.child_spec/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.config/0 .","ref":"Plausible.IngestRepo.html#config/0","title":"Plausible.IngestRepo.config/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.default_options/1 .","ref":"Plausible.IngestRepo.html#default_options/1","title":"Plausible.IngestRepo.default_options/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete/2 .","ref":"Plausible.IngestRepo.html#delete/2","title":"Plausible.IngestRepo.delete/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete!/2 .","ref":"Plausible.IngestRepo.html#delete!/2","title":"Plausible.IngestRepo.delete!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete_all/2 .","ref":"Plausible.IngestRepo.html#delete_all/2","title":"Plausible.IngestRepo.delete_all/2","type":"function"},{"doc":"A convenience function for SQL-based repositories that forces all connections in the pool to disconnect within the given interval. See Ecto.Adapters.SQL.disconnect_all/3 for more information.","ref":"Plausible.IngestRepo.html#disconnect_all/2","title":"Plausible.IngestRepo.disconnect_all/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.exists?/2 .","ref":"Plausible.IngestRepo.html#exists?/2","title":"Plausible.IngestRepo.exists?/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get/3 .","ref":"Plausible.IngestRepo.html#get/3","title":"Plausible.IngestRepo.get/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get!/3 .","ref":"Plausible.IngestRepo.html#get!/3","title":"Plausible.IngestRepo.get!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_by/3 .","ref":"Plausible.IngestRepo.html#get_by/3","title":"Plausible.IngestRepo.get_by/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_by!/3 .","ref":"Plausible.IngestRepo.html#get_by!/3","title":"Plausible.IngestRepo.get_by!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_dynamic_repo/0 .","ref":"Plausible.IngestRepo.html#get_dynamic_repo/0","title":"Plausible.IngestRepo.get_dynamic_repo/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert/2 .","ref":"Plausible.IngestRepo.html#insert/2","title":"Plausible.IngestRepo.insert/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert!/2 .","ref":"Plausible.IngestRepo.html#insert!/2","title":"Plausible.IngestRepo.insert!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_all/3 .","ref":"Plausible.IngestRepo.html#insert_all/3","title":"Plausible.IngestRepo.insert_all/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_or_update/2 .","ref":"Plausible.IngestRepo.html#insert_or_update/2","title":"Plausible.IngestRepo.insert_or_update/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_or_update!/2 .","ref":"Plausible.IngestRepo.html#insert_or_update!/2","title":"Plausible.IngestRepo.insert_or_update!/2","type":"function"},{"doc":"Similar to insert_all/2 but with the following differences: accepts rows as streams or lists sends rows as a chunked request doesn't autogenerate ids or does any other preprocessing Example: Repo . query! ( "create table ecto_ch_demo(a UInt64, b String) engine Null" ) defmodule Demo do use Ecto.Schema @primary_key false schema "ecto_ch_demo" do field :a , Ch , type : "UInt64" field :b , :string end end rows = Stream . map ( 1 .. 100_000 , fn i -> %{ a : i , b : to_string ( i ) } end ) { 100_000 , nil } = Repo . insert_stream ( Demo , rows ) # schemaless { 100_000 , nil } = Repo . insert_stream ( "ecto_ch_demo" , rows , types : [ a : Ch.Types . u64 ( ) , b : :string ] )","ref":"Plausible.IngestRepo.html#insert_stream/3","title":"Plausible.IngestRepo.insert_stream/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.load/2 .","ref":"Plausible.IngestRepo.html#load/2","title":"Plausible.IngestRepo.load/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.one/2 .","ref":"Plausible.IngestRepo.html#one/2","title":"Plausible.IngestRepo.one/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.one!/2 .","ref":"Plausible.IngestRepo.html#one!/2","title":"Plausible.IngestRepo.one!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.preload/3 .","ref":"Plausible.IngestRepo.html#preload/3","title":"Plausible.IngestRepo.preload/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.prepare_query/3 .","ref":"Plausible.IngestRepo.html#prepare_query/3","title":"Plausible.IngestRepo.prepare_query/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.put_dynamic_repo/1 .","ref":"Plausible.IngestRepo.html#put_dynamic_repo/1","title":"Plausible.IngestRepo.put_dynamic_repo/1","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given query. See Ecto.Adapters.SQL.query/4 for more information.","ref":"Plausible.IngestRepo.html#query/3","title":"Plausible.IngestRepo.query/3","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given query. See Ecto.Adapters.SQL.query!/4 for more information.","ref":"Plausible.IngestRepo.html#query!/3","title":"Plausible.IngestRepo.query!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.reload/2 .","ref":"Plausible.IngestRepo.html#reload/2","title":"Plausible.IngestRepo.reload/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.reload!/2 .","ref":"Plausible.IngestRepo.html#reload!/2","title":"Plausible.IngestRepo.reload!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.start_link/1 .","ref":"Plausible.IngestRepo.html#start_link/1","title":"Plausible.IngestRepo.start_link/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.stop/1 .","ref":"Plausible.IngestRepo.html#stop/1","title":"Plausible.IngestRepo.stop/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.stream/2 .","ref":"Plausible.IngestRepo.html#stream/2","title":"Plausible.IngestRepo.stream/2","type":"function"},{"doc":"A convenience function for SQL-based repositories that translates the given query to SQL. See Ecto.Adapters.SQL.to_sql/3 for more information.","ref":"Plausible.IngestRepo.html#to_sql/2","title":"Plausible.IngestRepo.to_sql/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update/2 .","ref":"Plausible.IngestRepo.html#update/2","title":"Plausible.IngestRepo.update/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update!/2 .","ref":"Plausible.IngestRepo.html#update!/2","title":"Plausible.IngestRepo.update!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update_all/3 .","ref":"Plausible.IngestRepo.html#update_all/3","title":"Plausible.IngestRepo.update_all/3","type":"function"},{"doc":"This is instrumentation necessary for keeping track of per-domain internal metrics. Due to metric labels cardinality (domain x metric_name), these statistics are not suitable for prometheus/grafana exposure, hence an internal storage is used. The module installs Counters.TelemetryHandler and periodically flushes the internal counter aggregates via Counters.Buffer interface. The underlying database schema is running SummingMergeTree engine. To take advantage of automatic roll-ups it provides, upon dispatching the buffered records to Clickhouse this module transforms each event_timebucket aggregate into a 1-minute resolution. Clickhouse connection is set to insert counters asynchronously every time a pool checkout is made. Those properties are reverted once the insert is done (or naturally, if the connection crashes).","ref":"Plausible.Ingestion.Counters.html","title":"Plausible.Ingestion.Counters","type":"module"},{"doc":"","ref":"Plausible.Ingestion.Counters.html#child_spec/1","title":"Plausible.Ingestion.Counters.child_spec/1","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Counters.html#enabled?/0","title":"Plausible.Ingestion.Counters.enabled?/0","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Counters.html#stop/1","title":"Plausible.Ingestion.Counters.stop/1","type":"function"},{"doc":"A buffer aggregating counters for internal metrics, within 10 seconds time buckets. See Plausible.Ingestion.Counters for integration. Flushing is by default possible only once the 10s bucket is complete (its window has moved). This is to avoid race conditions when clearing up the buffer on dequeue - because there is no atomic "get and delete", and items are buffered concurrently, there is a gap between get and delete in which items written may disappear otherwise. aggregate_bucket_fn and flush_boundary_fn control that semantics and are configurable only for test purposes.","ref":"Plausible.Ingestion.Counters.Buffer.html","title":"Plausible.Ingestion.Counters.Buffer","type":"module"},{"doc":"","ref":"Plausible.Ingestion.Counters.Buffer.html#aggregate/4","title":"Plausible.Ingestion.Counters.Buffer.aggregate/4","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Counters.Buffer.html#bucket_10s/1","title":"Plausible.Ingestion.Counters.Buffer.bucket_10s/1","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Counters.Buffer.html#flush/2","title":"Plausible.Ingestion.Counters.Buffer.flush/2","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Counters.Buffer.html#new/2","title":"Plausible.Ingestion.Counters.Buffer.new/2","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Counters.Buffer.html#previous_10s/1","title":"Plausible.Ingestion.Counters.Buffer.previous_10s/1","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Counters.Buffer.html#t:bucket_fn_opt/0","title":"Plausible.Ingestion.Counters.Buffer.bucket_fn_opt/0","type":"type"},{"doc":"","ref":"Plausible.Ingestion.Counters.Buffer.html#t:t/0","title":"Plausible.Ingestion.Counters.Buffer.t/0","type":"type"},{"doc":"","ref":"Plausible.Ingestion.Counters.Buffer.html#t:unix_timestamp/0","title":"Plausible.Ingestion.Counters.Buffer.unix_timestamp/0","type":"type"},{"doc":"Clickhouse schema for storing ingest counter metrics","ref":"Plausible.Ingestion.Counters.Record.html","title":"Plausible.Ingestion.Counters.Record","type":"module"},{"doc":"","ref":"Plausible.Ingestion.Counters.Record.html#t:t/0","title":"Plausible.Ingestion.Counters.Record.t/0","type":"type"},{"doc":"Susbcribes to telemetry events emitted by Plausible.Ingestion.Event . Every time a request derived event is either dispatched to clickhouse or dropped, a telemetry event is emitted respectively. That event is captured here, its metadata is extracted and sent for internal stats aggregation via Counters.Buffer interface.","ref":"Plausible.Ingestion.Counters.TelemetryHandler.html","title":"Plausible.Ingestion.Counters.TelemetryHandler","type":"module"},{"doc":"","ref":"Plausible.Ingestion.Counters.TelemetryHandler.html#handle_event/4","title":"Plausible.Ingestion.Counters.TelemetryHandler.handle_event/4","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Counters.TelemetryHandler.html#install/1","title":"Plausible.Ingestion.Counters.TelemetryHandler.install/1","type":"function"},{"doc":"This module exposes the build_and_buffer/1 function capable of turning %Plausible.Ingestion.Request{} into a series of events that in turn are uniformly either buffered in batches (to Clickhouse) or dropped (e.g. due to spam blocklist) from the processing pipeline.","ref":"Plausible.Ingestion.Event.html","title":"Plausible.Ingestion.Event","type":"module"},{"doc":"","ref":"Plausible.Ingestion.Event.html#build_and_buffer/1","title":"Plausible.Ingestion.Event.build_and_buffer/1","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Event.html#emit_telemetry_buffered/1","title":"Plausible.Ingestion.Event.emit_telemetry_buffered/1","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Event.html#emit_telemetry_dropped/2","title":"Plausible.Ingestion.Event.emit_telemetry_dropped/2","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Event.html#telemetry_event_buffered/0","title":"Plausible.Ingestion.Event.telemetry_event_buffered/0","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Event.html#telemetry_event_dropped/0","title":"Plausible.Ingestion.Event.telemetry_event_dropped/0","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Event.html#t:drop_reason/0","title":"Plausible.Ingestion.Event.drop_reason/0","type":"type"},{"doc":"","ref":"Plausible.Ingestion.Event.html#t:t/0","title":"Plausible.Ingestion.Event.t/0","type":"type"},{"doc":"The %Plausible.Ingestion.Request{} struct stores all needed fields to create an event downstream. Pre-eliminary validation is made to detect user errors early.","ref":"Plausible.Ingestion.Request.html","title":"Plausible.Ingestion.Request","type":"module"},{"doc":"Builds and initially validates %Plausible.Ingestion.Request{} struct from %Plug.Conn{}.","ref":"Plausible.Ingestion.Request.html#build/2","title":"Plausible.Ingestion.Request.build/2","type":"function"},{"doc":"Removes the "www" part of a hostname.","ref":"Plausible.Ingestion.Request.html#sanitize_hostname/1","title":"Plausible.Ingestion.Request.sanitize_hostname/1","type":"function"},{"doc":"","ref":"Plausible.Ingestion.Request.html#t:t/0","title":"Plausible.Ingestion.Request.t/0","type":"type"},{"doc":"","ref":"Plausible.Mailer.html","title":"Plausible.Mailer","type":"module"},{"doc":"","ref":"Plausible.Mailer.html#deliver/1","title":"Plausible.Mailer.deliver/1","type":"function"},{"doc":"","ref":"Plausible.Mailer.html#deliver_later/2","title":"Plausible.Mailer.deliver_later/2","type":"function"},{"doc":"","ref":"Plausible.Mailer.html#deliver_later!/2","title":"Plausible.Mailer.deliver_later!/2","type":"function"},{"doc":"","ref":"Plausible.Mailer.html#deliver_now/2","title":"Plausible.Mailer.deliver_now/2","type":"function"},{"doc":"","ref":"Plausible.Mailer.html#deliver_now!/2","title":"Plausible.Mailer.deliver_now!/2","type":"function"},{"doc":"","ref":"Plausible.Mailer.html#send/1","title":"Plausible.Mailer.send/1","type":"function"},{"doc":"Custom OpenTelemetry sampler implementation that ignores particular traces to reduce noise. Ingestion HTTP requests and queries to Oban tables are ignored, for example.","ref":"Plausible.OpenTelemetry.Sampler.html","title":"Plausible.OpenTelemetry.Sampler","type":"module"},{"doc":"","ref":"Plausible.PaddleApi.Mock.html","title":"Plausible.PaddleApi.Mock","type":"module"},{"doc":"","ref":"Plausible.PaddleApi.Mock.html#get_invoices/1","title":"Plausible.PaddleApi.Mock.get_invoices/1","type":"function"},{"doc":"","ref":"Plausible.PaddleApi.Mock.html#get_subscription/1","title":"Plausible.PaddleApi.Mock.get_subscription/1","type":"function"},{"doc":"","ref":"Plausible.PaddleApi.Mock.html#update_subscription/2","title":"Plausible.PaddleApi.Mock.update_subscription/2","type":"function"},{"doc":"","ref":"Plausible.PromEx.html","title":"Plausible.PromEx","type":"module"},{"doc":"Returns a specification to start this module under a supervisor. See Supervisor .","ref":"Plausible.PromEx.html#child_spec/1","title":"Plausible.PromEx.child_spec/1","type":"function"},{"doc":"Custom PromEx plugin for instrumenting code within Plausible app.","ref":"Plausible.PromEx.Plugins.PlausibleMetrics.html","title":"Plausible.PromEx.Plugins.PlausibleMetrics","type":"module"},{"doc":"Add telemetry events for Cachex user agents and sessions","ref":"Plausible.PromEx.Plugins.PlausibleMetrics.html#execute_cache_metrics/0","title":"Plausible.PromEx.Plugins.PlausibleMetrics.execute_cache_metrics/0","type":"function"},{"doc":"Add telemetry events for Session and Event write buffers","ref":"Plausible.PromEx.Plugins.PlausibleMetrics.html#execute_write_buffer_metrics/0","title":"Plausible.PromEx.Plugins.PlausibleMetrics.execute_write_buffer_metrics/0","type":"function"},{"doc":"Deletes data from a site. Stats are stored on Clickhouse, and unlike other databases data deletion is done asynchronously. Clickhouse ALTER TABLE ... DELETE Statement Synchronicity of ALTER Queries","ref":"Plausible.Purge.html","title":"Plausible.Purge","type":"module"},{"doc":"Deletes imported stats from Google Analytics, and clears the stats_start_date field.","ref":"Plausible.Purge.html#delete_imported_stats!/1","title":"Plausible.Purge.delete_imported_stats!/1","type":"function"},{"doc":"Move stats pointers so that no historical stats are available.","ref":"Plausible.Purge.html#delete_native_stats!/1","title":"Plausible.Purge.delete_native_stats!/1","type":"function"},{"doc":"","ref":"Plausible.Purge.html#reset!/1","title":"Plausible.Purge.reset!/1","type":"function"},{"doc":"","ref":"Plausible.Release.html","title":"Plausible.Release","type":"module"},{"doc":"","ref":"Plausible.Release.html#configure_ref_inspector/0","title":"Plausible.Release.configure_ref_inspector/0","type":"function"},{"doc":"","ref":"Plausible.Release.html#configure_ua_inspector/0","title":"Plausible.Release.configure_ua_inspector/0","type":"function"},{"doc":"","ref":"Plausible.Release.html#createdb/0","title":"Plausible.Release.createdb/0","type":"function"},{"doc":"","ref":"Plausible.Release.html#migrate/0","title":"Plausible.Release.migrate/0","type":"function"},{"doc":"","ref":"Plausible.Release.html#rollback/0","title":"Plausible.Release.rollback/0","type":"function"},{"doc":"","ref":"Plausible.Release.html#seed/0","title":"Plausible.Release.seed/0","type":"function"},{"doc":"","ref":"Plausible.Release.html#selfhost?/0","title":"Plausible.Release.selfhost?/0","type":"function"},{"doc":"","ref":"Plausible.Release.html#should_be_first_launch?/0","title":"Plausible.Release.should_be_first_launch?/0","type":"function"},{"doc":"","ref":"Plausible.Repo.html","title":"Plausible.Repo","type":"module"},{"doc":"Callback implementation for Ecto.Repo.aggregate/3 .","ref":"Plausible.Repo.html#aggregate/3","title":"Plausible.Repo.aggregate/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.aggregate/4 .","ref":"Plausible.Repo.html#aggregate/4","title":"Plausible.Repo.aggregate/4","type":"function"},{"doc":"Callback implementation for Ecto.Repo.all/2 .","ref":"Plausible.Repo.html#all/2","title":"Plausible.Repo.all/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.checked_out?/0 .","ref":"Plausible.Repo.html#checked_out?/0","title":"Plausible.Repo.checked_out?/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.checkout/2 .","ref":"Plausible.Repo.html#checkout/2","title":"Plausible.Repo.checkout/2","type":"function"},{"doc":"","ref":"Plausible.Repo.html#child_spec/1","title":"Plausible.Repo.child_spec/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.config/0 .","ref":"Plausible.Repo.html#config/0","title":"Plausible.Repo.config/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.default_options/1 .","ref":"Plausible.Repo.html#default_options/1","title":"Plausible.Repo.default_options/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete/2 .","ref":"Plausible.Repo.html#delete/2","title":"Plausible.Repo.delete/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete!/2 .","ref":"Plausible.Repo.html#delete!/2","title":"Plausible.Repo.delete!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.delete_all/2 .","ref":"Plausible.Repo.html#delete_all/2","title":"Plausible.Repo.delete_all/2","type":"function"},{"doc":"A convenience function for SQL-based repositories that forces all connections in the pool to disconnect within the given interval. See Ecto.Adapters.SQL.disconnect_all/3 for more information.","ref":"Plausible.Repo.html#disconnect_all/2","title":"Plausible.Repo.disconnect_all/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.exists?/2 .","ref":"Plausible.Repo.html#exists?/2","title":"Plausible.Repo.exists?/2","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes an EXPLAIN statement or similar depending on the adapter to obtain statistics for the given query. See Ecto.Adapters.SQL.explain/4 for more information.","ref":"Plausible.Repo.html#explain/3","title":"Plausible.Repo.explain/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get/3 .","ref":"Plausible.Repo.html#get/3","title":"Plausible.Repo.get/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get!/3 .","ref":"Plausible.Repo.html#get!/3","title":"Plausible.Repo.get!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_by/3 .","ref":"Plausible.Repo.html#get_by/3","title":"Plausible.Repo.get_by/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_by!/3 .","ref":"Plausible.Repo.html#get_by!/3","title":"Plausible.Repo.get_by!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.get_dynamic_repo/0 .","ref":"Plausible.Repo.html#get_dynamic_repo/0","title":"Plausible.Repo.get_dynamic_repo/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.in_transaction?/0 .","ref":"Plausible.Repo.html#in_transaction?/0","title":"Plausible.Repo.in_transaction?/0","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert/2 .","ref":"Plausible.Repo.html#insert/2","title":"Plausible.Repo.insert/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert!/2 .","ref":"Plausible.Repo.html#insert!/2","title":"Plausible.Repo.insert!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_all/3 .","ref":"Plausible.Repo.html#insert_all/3","title":"Plausible.Repo.insert_all/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_or_update/2 .","ref":"Plausible.Repo.html#insert_or_update/2","title":"Plausible.Repo.insert_or_update/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.insert_or_update!/2 .","ref":"Plausible.Repo.html#insert_or_update!/2","title":"Plausible.Repo.insert_or_update!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.load/2 .","ref":"Plausible.Repo.html#load/2","title":"Plausible.Repo.load/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.one/2 .","ref":"Plausible.Repo.html#one/2","title":"Plausible.Repo.one/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.one!/2 .","ref":"Plausible.Repo.html#one!/2","title":"Plausible.Repo.one!/2","type":"function"},{"doc":"","ref":"Plausible.Repo.html#paginate/3","title":"Plausible.Repo.paginate/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.preload/3 .","ref":"Plausible.Repo.html#preload/3","title":"Plausible.Repo.preload/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.prepare_query/3 .","ref":"Plausible.Repo.html#prepare_query/3","title":"Plausible.Repo.prepare_query/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.put_dynamic_repo/1 .","ref":"Plausible.Repo.html#put_dynamic_repo/1","title":"Plausible.Repo.put_dynamic_repo/1","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given query. See Ecto.Adapters.SQL.query/4 for more information.","ref":"Plausible.Repo.html#query/3","title":"Plausible.Repo.query/3","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given query. See Ecto.Adapters.SQL.query!/4 for more information.","ref":"Plausible.Repo.html#query!/3","title":"Plausible.Repo.query!/3","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given multi-result query. See Ecto.Adapters.SQL.query_many/4 for more information.","ref":"Plausible.Repo.html#query_many/3","title":"Plausible.Repo.query_many/3","type":"function"},{"doc":"A convenience function for SQL-based repositories that executes the given multi-result query. See Ecto.Adapters.SQL.query_many!/4 for more information.","ref":"Plausible.Repo.html#query_many!/3","title":"Plausible.Repo.query_many!/3","type":"function"},{"doc":"Callback implementation for Ecto.Repo.reload/2 .","ref":"Plausible.Repo.html#reload/2","title":"Plausible.Repo.reload/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.reload!/2 .","ref":"Plausible.Repo.html#reload!/2","title":"Plausible.Repo.reload!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.rollback/1 .","ref":"Plausible.Repo.html#rollback/1","title":"Plausible.Repo.rollback/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.start_link/1 .","ref":"Plausible.Repo.html#start_link/1","title":"Plausible.Repo.start_link/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.stop/1 .","ref":"Plausible.Repo.html#stop/1","title":"Plausible.Repo.stop/1","type":"function"},{"doc":"Callback implementation for Ecto.Repo.stream/2 .","ref":"Plausible.Repo.html#stream/2","title":"Plausible.Repo.stream/2","type":"function"},{"doc":"A convenience function for SQL-based repositories that translates the given query to SQL. See Ecto.Adapters.SQL.to_sql/3 for more information.","ref":"Plausible.Repo.html#to_sql/2","title":"Plausible.Repo.to_sql/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.transaction/2 .","ref":"Plausible.Repo.html#transaction/2","title":"Plausible.Repo.transaction/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update/2 .","ref":"Plausible.Repo.html#update/2","title":"Plausible.Repo.update/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update!/2 .","ref":"Plausible.Repo.html#update!/2","title":"Plausible.Repo.update!/2","type":"function"},{"doc":"Callback implementation for Ecto.Repo.update_all/3 .","ref":"Plausible.Repo.html#update_all/3","title":"Plausible.Repo.update_all/3","type":"function"},{"doc":"","ref":"Plausible.Sentry.Client.html","title":"Plausible.Sentry.Client","type":"module"},{"doc":"The Sentry.HTTPClient behaviour requires a child spec to be supplied. In this case we don't want Sentry to manage our Finch instances, hence it's fed with a dummy module for the sake of the contract. XXX: Submit a Sentry PR making the child spec callback optional.","ref":"Plausible.Sentry.Client.html#child_spec/0","title":"Plausible.Sentry.Client.child_spec/0","type":"function"},{"doc":"Callback implementation for Sentry.HTTPClient.post/3 .","ref":"Plausible.Sentry.Client.html#post/3","title":"Plausible.Sentry.Client.post/3","type":"function"},{"doc":"Sentry callbacks for filtering and grouping events","ref":"Plausible.SentryFilter.html","title":"Plausible.SentryFilter","type":"module"},{"doc":"","ref":"Plausible.SentryFilter.html#before_send/1","title":"Plausible.SentryFilter.before_send/1","type":"function"},{"doc":"Callback implementation for Sentry.EventFilter.exclude_exception?/2 .","ref":"Plausible.SentryFilter.html#exclude_exception?/2","title":"Plausible.SentryFilter.exclude_exception?/2","type":"function"},{"doc":"","ref":"Plausible.Session.CacheStore.html","title":"Plausible.Session.CacheStore","type":"module"},{"doc":"","ref":"Plausible.Session.CacheStore.html#on_event/3","title":"Plausible.Session.CacheStore.on_event/3","type":"function"},{"doc":"","ref":"Plausible.Session.Salts.html","title":"Plausible.Session.Salts","type":"module"},{"doc":"Returns a specification to start this module under a supervisor. See Supervisor .","ref":"Plausible.Session.Salts.html#child_spec/1","title":"Plausible.Session.Salts.child_spec/1","type":"function"},{"doc":"","ref":"Plausible.Session.Salts.html#fetch/0","title":"Plausible.Session.Salts.fetch/0","type":"function"},{"doc":"","ref":"Plausible.Session.Salts.html#rotate/0","title":"Plausible.Session.Salts.rotate/0","type":"function"},{"doc":"","ref":"Plausible.Session.Salts.html#start_link/1","title":"Plausible.Session.Salts.start_link/1","type":"function"},{"doc":"","ref":"Plausible.Session.WriteBuffer.html","title":"Plausible.Session.WriteBuffer","type":"module"},{"doc":"Returns a specification to start this module under a supervisor. See Supervisor .","ref":"Plausible.Session.WriteBuffer.html#child_spec/1","title":"Plausible.Session.WriteBuffer.child_spec/1","type":"function"},{"doc":"","ref":"Plausible.Session.WriteBuffer.html#flush/0","title":"Plausible.Session.WriteBuffer.flush/0","type":"function"},{"doc":"Callback implementation for GenServer.init/1 .","ref":"Plausible.Session.WriteBuffer.html#init/1","title":"Plausible.Session.WriteBuffer.init/1","type":"function"},{"doc":"","ref":"Plausible.Session.WriteBuffer.html#insert/1","title":"Plausible.Session.WriteBuffer.insert/1","type":"function"},{"doc":"","ref":"Plausible.Session.WriteBuffer.html#start_link/1","title":"Plausible.Session.WriteBuffer.start_link/1","type":"function"},{"doc":"Site schema","ref":"Plausible.Site.html","title":"Plausible.Site","type":"module"},{"doc":"","ref":"Plausible.Site.html#changeset/2","title":"Plausible.Site.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Site.html#crm_changeset/2","title":"Plausible.Site.crm_changeset/2","type":"function"},{"doc":"","ref":"Plausible.Site.html#feature_toggle_change/3","title":"Plausible.Site.feature_toggle_change/3","type":"function"},{"doc":"","ref":"Plausible.Site.html#import_failure/1","title":"Plausible.Site.import_failure/1","type":"function"},{"doc":"","ref":"Plausible.Site.html#import_success/1","title":"Plausible.Site.import_success/1","type":"function"},{"doc":"Returns the date of the first recorded stat in the timezone configured by the user. This function does 2 transformations: UTC %NaiveDateTime{} -> Local %DateTime{} -> Local %Date Examples iex> Plausible.Site.local_start_date(%Plausible.Site{stats_start_date: nil}) nil iex> utc_start = ~N[2022-09-28 00:00:00] iex> tz = "Europe/Helsinki" iex> site = %Plausible.Site{stats_start_date: utc_start, timezone: tz} iex> Plausible.Site.local_start_date(site) ~D[2022-09-28] iex> utc_start = ~N[2022-09-28 00:00:00] iex> tz = "America/Los_Angeles" iex> site = %Plausible.Site{stats_start_date: utc_start, timezone: tz} iex> Plausible.Site.local_start_date(site) ~D[2022-09-27]","ref":"Plausible.Site.html#local_start_date/1","title":"Plausible.Site.local_start_date/1","type":"function"},{"doc":"","ref":"Plausible.Site.html#make_private/1","title":"Plausible.Site.make_private/1","type":"function"},{"doc":"","ref":"Plausible.Site.html#make_public/1","title":"Plausible.Site.make_public/1","type":"function"},{"doc":"","ref":"Plausible.Site.html#remove_imported_data/1","title":"Plausible.Site.remove_imported_data/1","type":"function"},{"doc":"","ref":"Plausible.Site.html#set_allowed_event_props/2","title":"Plausible.Site.set_allowed_event_props/2","type":"function"},{"doc":"","ref":"Plausible.Site.html#set_imported_source/2","title":"Plausible.Site.set_imported_source/2","type":"function"},{"doc":"","ref":"Plausible.Site.html#set_native_stats_start_at/2","title":"Plausible.Site.set_native_stats_start_at/2","type":"function"},{"doc":"","ref":"Plausible.Site.html#set_stats_start_date/2","title":"Plausible.Site.set_stats_start_date/2","type":"function"},{"doc":"","ref":"Plausible.Site.html#start_import/5","title":"Plausible.Site.start_import/5","type":"function"},{"doc":"","ref":"Plausible.Site.html#tz_offset/2","title":"Plausible.Site.tz_offset/2","type":"function"},{"doc":"","ref":"Plausible.Site.html#update_changeset/3","title":"Plausible.Site.update_changeset/3","type":"function"},{"doc":"","ref":"Plausible.Site.html#t:t/0","title":"Plausible.Site.t/0","type":"type"},{"doc":"A "sites by domain" caching interface. Serves as a thin wrapper around Cachex, but the underlying implementation can be transparently swapped. Even though the Cachex process is started, cache access is disabled during tests via the :sites_by_domain_cache_enabled application env key. This can be overridden on case by case basis, using the child specs options. NOTE: the cache allows lookups by both domain and domain_changed_from fields - this is to allow traffic from sites whose domains changed within a certain grace period (see: Plausible.Site.Transfer ). When Cache is disabled via application env, the get/1 function falls back to pure database lookups. This should help with introducing cached lookups in existing code, so that no existing tests should break. To differentiate cached Site structs from those retrieved directly from the database, a virtual schema field from_cache?: true is set. This indicates the Plausible.Site struct is incomplete in comparison to its database counterpart -- to spare bandwidth and query execution time, only selected database columns are retrieved and cached. There are two modes of refreshing the cache: :all and :updated_recently . :all means querying the database for all Site entries and should be done periodically (via Cache.Warmer ). All stale Cache entries are cleared upon persisting the new batch. :updated_recently attempts to re-query sites updated within the last 15 minutes only, to account for most recent changes. This refresh is lighter on the database and is meant to be executed more frequently (via Cache.Warmer.RecentlyUpdated ). Refreshing the cache emits telemetry event defined as per telemetry_event_refresh/2 . The @cached_schema_fields attribute defines the list of DB columns queried on each cache refresh. Also see tests for more comprehensive examples.","ref":"Plausible.Site.Cache.html","title":"Plausible.Site.Cache","type":"module"},{"doc":"","ref":"Plausible.Site.Cache.html#child_spec/1","title":"Plausible.Site.Cache.child_spec/1","type":"function"},{"doc":"","ref":"Plausible.Site.Cache.html#enabled?/0","title":"Plausible.Site.Cache.enabled?/0","type":"function"},{"doc":"","ref":"Plausible.Site.Cache.html#get/2","title":"Plausible.Site.Cache.get/2","type":"function"},{"doc":"","ref":"Plausible.Site.Cache.html#get_site_id/2","title":"Plausible.Site.Cache.get_site_id/2","type":"function"},{"doc":"","ref":"Plausible.Site.Cache.html#hit_rate/1","title":"Plausible.Site.Cache.hit_rate/1","type":"function"},{"doc":"","ref":"Plausible.Site.Cache.html#merge/2","title":"Plausible.Site.Cache.merge/2","type":"function"},{"doc":"","ref":"Plausible.Site.Cache.html#name/0","title":"Plausible.Site.Cache.name/0","type":"function"},{"doc":"Ensures the cache has non-zero size unless no sites exist. Useful for orchestrating app startup to prevent the service going up asynchronously with an empty cache.","ref":"Plausible.Site.Cache.html#ready?/1","title":"Plausible.Site.Cache.ready?/1","type":"function"},{"doc":"","ref":"Plausible.Site.Cache.html#refresh_all/1","title":"Plausible.Site.Cache.refresh_all/1","type":"function"},{"doc":"","ref":"Plausible.Site.Cache.html#refresh_updated_recently/1","title":"Plausible.Site.Cache.refresh_updated_recently/1","type":"function"},{"doc":"","ref":"Plausible.Site.Cache.html#size/1","title":"Plausible.Site.Cache.size/1","type":"function"},{"doc":"","ref":"Plausible.Site.Cache.html#telemetry_event_refresh/2","title":"Plausible.Site.Cache.telemetry_event_refresh/2","type":"function"},{"doc":"","ref":"Plausible.Site.Cache.html#t:t/0","title":"Plausible.Site.Cache.t/0","type":"type"},{"doc":"A periodic cache warmer. Queries all Sites from Postgres, every interval and pre-populates the cache. After each run the process is hibernated, triggering garbage collection. Currently Cachex is used, but the underlying implementation can be transparently swapped. Child specification options available: interval - the number of milliseconds for each warm-up cycle, defaults to :sites_by_domain_cache_refresh_interval application env value with random jitter added, for which the maximum is stored under :sites_by_domain_cache_refresh_interval_max_jitter key. cache_name - defaults to Cache.name() but can be overriden for testing force_start? - enforcess process startup for testing, even if it's barred by Cache.enabled? . This is useful for avoiding issues with DB ownership and async tests. warmer_fn - used for testing, a custom function to retrieve the items meant to be cached during the warm-up cycle. See tests for more comprehensive examples.","ref":"Plausible.Site.Cache.Warmer.html","title":"Plausible.Site.Cache.Warmer","type":"module"},{"doc":"","ref":"Plausible.Site.Cache.Warmer.html#child_spec/1","title":"Plausible.Site.Cache.Warmer.child_spec/1","type":"function"},{"doc":"","ref":"Plausible.Site.Cache.Warmer.html#interval/0","title":"Plausible.Site.Cache.Warmer.interval/0","type":"function"},{"doc":"A Cache.Warmer adapter that refreshes the Sites Cache fully. This module exists only to make it explicit what the warmer refreshes, to be used in the supervisor tree.","ref":"Plausible.Site.Cache.Warmer.All.html","title":"Plausible.Site.Cache.Warmer.All","type":"module"},{"doc":"See Plausible.Site.Cache.Warmer.child_spec/1 .","ref":"Plausible.Site.Cache.Warmer.All.html#child_spec/1","title":"Plausible.Site.Cache.Warmer.All.child_spec/1","type":"function"},{"doc":"A Cache.Warmer adapter that only refreshes the Cache with recently updated sites every 30 seconds.","ref":"Plausible.Site.Cache.Warmer.RecentlyUpdated.html","title":"Plausible.Site.Cache.Warmer.RecentlyUpdated","type":"module"},{"doc":"","ref":"Plausible.Site.Cache.Warmer.RecentlyUpdated.html#child_spec/1","title":"Plausible.Site.Cache.Warmer.RecentlyUpdated.child_spec/1","type":"function"},{"doc":"","ref":"Plausible.Site.CustomDomain.html","title":"Plausible.Site.CustomDomain","type":"module"},{"doc":"Basic interface for domain changes. Once Plausible.DataMigration.NumericIDs schema migration is ready, domain change operation will be enabled, accessible to the users. We will set a transition period of 72 hours during which, both old and new domains, will be accepted as traffic identifiers to the same site. A periodic worker will call the expire/0 function to end it where applicable. See: Plausible.Workers.ExpireDomainChangeTransitions . The underlying changeset for domain change (see: Plausible.Site ) relies on database trigger installed via Plausible.Repo.Migrations.AllowDomainChange Postgres migration. The trigger checks if either domain or domain_changed_from exist to ensure unicity.","ref":"Plausible.Site.Domain.html","title":"Plausible.Site.Domain","type":"module"},{"doc":"","ref":"Plausible.Site.Domain.html#change/3","title":"Plausible.Site.Domain.change/3","type":"function"},{"doc":"","ref":"Plausible.Site.Domain.html#expire_change_transitions/1","title":"Plausible.Site.Domain.expire_change_transitions/1","type":"function"},{"doc":"Thin wrapper around Hammer for gate keeping domain-specific events during the ingestion phase. When the site is allowed, gate keeping check returns :allow , otherwise a :deny tagged tuple is returned with one of the following policy markers: :not_found (indicates site not found in cache) :block (indicates disabled sites) :throttle (indicates rate limiting) Rate Limiting buckets are configured per site (externally via the CRM). See: Plausible.Site To look up each site's configuration, the RateLimiter fetches a Site by domain using Plausible.Cache interface. The module defines two policies outside the regular bucket inspection: when the the site is not found in cache: not_found when the underlying rate limiting mechanism returns an internal error: :allow","ref":"Plausible.Site.GateKeeper.html","title":"Plausible.Site.GateKeeper","type":"module"},{"doc":"","ref":"Plausible.Site.GateKeeper.html#check/2","title":"Plausible.Site.GateKeeper.check/2","type":"function"},{"doc":"","ref":"Plausible.Site.GateKeeper.html#key/1","title":"Plausible.Site.GateKeeper.key/1","type":"function"},{"doc":"","ref":"Plausible.Site.GateKeeper.html#t:policy/0","title":"Plausible.Site.GateKeeper.policy/0","type":"type"},{"doc":"","ref":"Plausible.Site.GateKeeper.html#t:t/0","title":"Plausible.Site.GateKeeper.t/0","type":"type"},{"doc":"","ref":"Plausible.Site.GoogleAuth.html","title":"Plausible.Site.GoogleAuth","type":"module"},{"doc":"","ref":"Plausible.Site.GoogleAuth.html#changeset/2","title":"Plausible.Site.GoogleAuth.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Site.GoogleAuth.html#set_property/2","title":"Plausible.Site.GoogleAuth.set_property/2","type":"function"},{"doc":"Embedded schema for Google Analytics imports","ref":"Plausible.Site.ImportedData.html","title":"Plausible.Site.ImportedData","type":"module"},{"doc":"","ref":"Plausible.Site.Membership.html","title":"Plausible.Site.Membership","type":"module"},{"doc":"","ref":"Plausible.Site.Membership.html#changeset/2","title":"Plausible.Site.Membership.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Site.MonthlyReport.html","title":"Plausible.Site.MonthlyReport","type":"module"},{"doc":"","ref":"Plausible.Site.MonthlyReport.html#add_recipient/2","title":"Plausible.Site.MonthlyReport.add_recipient/2","type":"function"},{"doc":"","ref":"Plausible.Site.MonthlyReport.html#changeset/2","title":"Plausible.Site.MonthlyReport.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Site.MonthlyReport.html#remove_recipient/2","title":"Plausible.Site.MonthlyReport.remove_recipient/2","type":"function"},{"doc":"A site deletion service stub.","ref":"Plausible.Site.Removal.html","title":"Plausible.Site.Removal","type":"module"},{"doc":"","ref":"Plausible.Site.Removal.html#run/1","title":"Plausible.Site.Removal.run/1","type":"function"},{"doc":"","ref":"Plausible.Site.SharedLink.html","title":"Plausible.Site.SharedLink","type":"module"},{"doc":"","ref":"Plausible.Site.SharedLink.html#changeset/2","title":"Plausible.Site.SharedLink.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Site.SpikeNotification.html","title":"Plausible.Site.SpikeNotification","type":"module"},{"doc":"","ref":"Plausible.Site.SpikeNotification.html#add_recipient/2","title":"Plausible.Site.SpikeNotification.add_recipient/2","type":"function"},{"doc":"","ref":"Plausible.Site.SpikeNotification.html#changeset/2","title":"Plausible.Site.SpikeNotification.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Site.SpikeNotification.html#remove_recipient/2","title":"Plausible.Site.SpikeNotification.remove_recipient/2","type":"function"},{"doc":"","ref":"Plausible.Site.SpikeNotification.html#was_sent/1","title":"Plausible.Site.SpikeNotification.was_sent/1","type":"function"},{"doc":"","ref":"Plausible.Site.WeeklyReport.html","title":"Plausible.Site.WeeklyReport","type":"module"},{"doc":"","ref":"Plausible.Site.WeeklyReport.html#add_recipient/2","title":"Plausible.Site.WeeklyReport.add_recipient/2","type":"function"},{"doc":"","ref":"Plausible.Site.WeeklyReport.html#changeset/2","title":"Plausible.Site.WeeklyReport.changeset/2","type":"function"},{"doc":"","ref":"Plausible.Site.WeeklyReport.html#remove_recipient/2","title":"Plausible.Site.WeeklyReport.remove_recipient/2","type":"function"},{"doc":"","ref":"Plausible.SiteAdmin.html","title":"Plausible.SiteAdmin","type":"module"},{"doc":"","ref":"Plausible.SiteAdmin.html#create_changeset/2","title":"Plausible.SiteAdmin.create_changeset/2","type":"function"},{"doc":"","ref":"Plausible.SiteAdmin.html#custom_index_query/3","title":"Plausible.SiteAdmin.custom_index_query/3","type":"function"},{"doc":"","ref":"Plausible.SiteAdmin.html#form_fields/1","title":"Plausible.SiteAdmin.form_fields/1","type":"function"},{"doc":"","ref":"Plausible.SiteAdmin.html#get_struct_fields/1","title":"Plausible.SiteAdmin.get_struct_fields/1","type":"function"},{"doc":"","ref":"Plausible.SiteAdmin.html#index/1","title":"Plausible.SiteAdmin.index/1","type":"function"},{"doc":"","ref":"Plausible.SiteAdmin.html#list_actions/1","title":"Plausible.SiteAdmin.list_actions/1","type":"function"},{"doc":"","ref":"Plausible.SiteAdmin.html#ordering/1","title":"Plausible.SiteAdmin.ordering/1","type":"function"},{"doc":"","ref":"Plausible.SiteAdmin.html#search_fields/1","title":"Plausible.SiteAdmin.search_fields/1","type":"function"},{"doc":"","ref":"Plausible.SiteAdmin.html#set_allowed_props_for_site/3","title":"Plausible.SiteAdmin.set_allowed_props_for_site/3","type":"function"},{"doc":"","ref":"Plausible.SiteAdmin.html#update_changeset/2","title":"Plausible.SiteAdmin.update_changeset/2","type":"function"},{"doc":"","ref":"Plausible.Sites.html","title":"Plausible.Sites","type":"module"},{"doc":"","ref":"Plausible.Sites.html#create/2","title":"Plausible.Sites.create/2","type":"function"},{"doc":"","ref":"Plausible.Sites.html#create_shared_link/3","title":"Plausible.Sites.create_shared_link/3","type":"function"},{"doc":"","ref":"Plausible.Sites.html#get_by_domain/1","title":"Plausible.Sites.get_by_domain/1","type":"function"},{"doc":"","ref":"Plausible.Sites.html#get_for_user/3","title":"Plausible.Sites.get_for_user/3","type":"function"},{"doc":"","ref":"Plausible.Sites.html#get_for_user!/3","title":"Plausible.Sites.get_for_user!/3","type":"function"},{"doc":"","ref":"Plausible.Sites.html#has_admin_access?/2","title":"Plausible.Sites.has_admin_access?/2","type":"function"},{"doc":"","ref":"Plausible.Sites.html#has_goals?/1","title":"Plausible.Sites.has_goals?/1","type":"function"},{"doc":"","ref":"Plausible.Sites.html#has_stats?/1","title":"Plausible.Sites.has_stats?/1","type":"function"},{"doc":"","ref":"Plausible.Sites.html#is_member?/2","title":"Plausible.Sites.is_member?/2","type":"function"},{"doc":"","ref":"Plausible.Sites.html#locked?/1","title":"Plausible.Sites.locked?/1","type":"function"},{"doc":"","ref":"Plausible.Sites.html#owned_site_ids/1","title":"Plausible.Sites.owned_site_ids/1","type":"function"},{"doc":"","ref":"Plausible.Sites.html#owned_sites_count/1","title":"Plausible.Sites.owned_sites_count/1","type":"function"},{"doc":"","ref":"Plausible.Sites.html#owned_sites_domains/1","title":"Plausible.Sites.owned_sites_domains/1","type":"function"},{"doc":"","ref":"Plausible.Sites.html#owner_for/1","title":"Plausible.Sites.owner_for/1","type":"function"},{"doc":"","ref":"Plausible.Sites.html#role/2","title":"Plausible.Sites.role/2","type":"function"},{"doc":"","ref":"Plausible.Sites.html#shared_link_url/2","title":"Plausible.Sites.shared_link_url/2","type":"function"},{"doc":"Returns the date of the first event of the given site, or nil if the site does not have stats yet. If this is the first time the function is called for the site, it queries Clickhouse and saves the date in the sites table.","ref":"Plausible.Sites.html#stats_start_date/1","title":"Plausible.Sites.stats_start_date/1","type":"function"},{"doc":"","ref":"Plausible.Stats.html","title":"Plausible.Stats","type":"module"},{"doc":"See Plausible.Stats.Aggregate.aggregate/3 .","ref":"Plausible.Stats.html#aggregate/3","title":"Plausible.Stats.aggregate/3","type":"function"},{"doc":"See Plausible.Stats.Breakdown.breakdown/5 .","ref":"Plausible.Stats.html#breakdown/5","title":"Plausible.Stats.breakdown/5","type":"function"},{"doc":"See Plausible.Stats.CurrentVisitors.current_visitors/1 .","ref":"Plausible.Stats.html#current_visitors/1","title":"Plausible.Stats.current_visitors/1","type":"function"},{"doc":"See Plausible.Stats.FilterSuggestions.filter_suggestions/4 .","ref":"Plausible.Stats.html#filter_suggestions/4","title":"Plausible.Stats.filter_suggestions/4","type":"function"},{"doc":"See Plausible.Stats.Funnel.funnel/3 .","ref":"Plausible.Stats.html#funnel/3","title":"Plausible.Stats.funnel/3","type":"function"},{"doc":"See Plausible.Stats.Timeseries.timeseries/3 .","ref":"Plausible.Stats.html#timeseries/3","title":"Plausible.Stats.timeseries/3","type":"function"},{"doc":"","ref":"Plausible.Stats.Aggregate.html","title":"Plausible.Stats.Aggregate","type":"module"},{"doc":"","ref":"Plausible.Stats.Aggregate.html#aggregate/3","title":"Plausible.Stats.Aggregate.aggregate/3","type":"function"},{"doc":"","ref":"Plausible.Stats.Base.html","title":"Plausible.Stats.Base","type":"module"},{"doc":"","ref":"Plausible.Stats.Base.html#apply_entry_prop_filter/3","title":"Plausible.Stats.Base.apply_entry_prop_filter/3","type":"function"},{"doc":"","ref":"Plausible.Stats.Base.html#base_event_query/2","title":"Plausible.Stats.Base.base_event_query/2","type":"function"},{"doc":"","ref":"Plausible.Stats.Base.html#filter_by_entry_props/2","title":"Plausible.Stats.Base.filter_by_entry_props/2","type":"function"},{"doc":"","ref":"Plausible.Stats.Base.html#filter_converted_sessions/3","title":"Plausible.Stats.Base.filter_converted_sessions/3","type":"function"},{"doc":"","ref":"Plausible.Stats.Base.html#page_regex/1","title":"Plausible.Stats.Base.page_regex/1","type":"function"},{"doc":"","ref":"Plausible.Stats.Base.html#query_events/2","title":"Plausible.Stats.Base.query_events/2","type":"function"},{"doc":"","ref":"Plausible.Stats.Base.html#query_sessions/2","title":"Plausible.Stats.Base.query_sessions/2","type":"function"},{"doc":"","ref":"Plausible.Stats.Base.html#select_event_metrics/2","title":"Plausible.Stats.Base.select_event_metrics/2","type":"function"},{"doc":"","ref":"Plausible.Stats.Base.html#select_session_metrics/3","title":"Plausible.Stats.Base.select_session_metrics/3","type":"function"},{"doc":"","ref":"Plausible.Stats.Base.html#utc_boundaries/2","title":"Plausible.Stats.Base.utc_boundaries/2","type":"function"},{"doc":"","ref":"Plausible.Stats.Breakdown.html","title":"Plausible.Stats.Breakdown","type":"module"},{"doc":"","ref":"Plausible.Stats.Breakdown.html#breakdown/5","title":"Plausible.Stats.Breakdown.breakdown/5","type":"function"},{"doc":"","ref":"Plausible.Stats.Clickhouse.html","title":"Plausible.Stats.Clickhouse","type":"module"},{"doc":"","ref":"Plausible.Stats.Clickhouse.html#current_visitors/2","title":"Plausible.Stats.Clickhouse.current_visitors/2","type":"function"},{"doc":"","ref":"Plausible.Stats.Clickhouse.html#has_pageviews?/1","title":"Plausible.Stats.Clickhouse.has_pageviews?/1","type":"function"},{"doc":"","ref":"Plausible.Stats.Clickhouse.html#imported_pageview_count/1","title":"Plausible.Stats.Clickhouse.imported_pageview_count/1","type":"function"},{"doc":"","ref":"Plausible.Stats.Clickhouse.html#last_24h_visitors/1","title":"Plausible.Stats.Clickhouse.last_24h_visitors/1","type":"function"},{"doc":"","ref":"Plausible.Stats.Clickhouse.html#pageview_start_date_local/1","title":"Plausible.Stats.Clickhouse.pageview_start_date_local/1","type":"function"},{"doc":"","ref":"Plausible.Stats.Clickhouse.html#top_sources/6","title":"Plausible.Stats.Clickhouse.top_sources/6","type":"function"},{"doc":"","ref":"Plausible.Stats.Clickhouse.html#usage_breakdown/1","title":"Plausible.Stats.Clickhouse.usage_breakdown/1","type":"function"},{"doc":"","ref":"Plausible.Stats.Clickhouse.html#usage_breakdown/2","title":"Plausible.Stats.Clickhouse.usage_breakdown/2","type":"function"},{"doc":"","ref":"Plausible.Stats.Compare.html","title":"Plausible.Stats.Compare","type":"module"},{"doc":"","ref":"Plausible.Stats.Compare.html#calculate_change/3","title":"Plausible.Stats.Compare.calculate_change/3","type":"function"},{"doc":"This module provides functions for comparing query periods. It allows you to compare a given period with a previous period or with the same period from the previous year. For example, you can compare this month's main graph with last month or with the same month from last year.","ref":"Plausible.Stats.Comparisons.html","title":"Plausible.Stats.Comparisons","type":"module"},{"doc":"Generates a comparison query based on the source query and comparison mode. The mode parameter specifies the type of comparison and can be one of the following: "previous_period" - shifts back the query by the same number of days the source query has. "year_over_year" - shifts back the query by 1 year. "custom" - compares the query using a custom date range. See options for more details. The comparison query returned by the function has its end date restricted to the current day. This can be overriden by the now option, described below. Options :now - a NaiveDateTime struct with the current date and time. This is optional and used for testing purposes. :from - a ISO-8601 date string used when mode is "custom" . :to - a ISO-8601 date string used when mode is "custom" . Must be after from . :match_day_of_week? - determines whether the comparison query should be adjusted to match the day of the week of the source query. When this option is set to true, the comparison query is shifted to start on the same day of the week as the source query, rather than on the exact same date. For example, if the source query starts on Sunday, January 1st, 2023 and the year_over_year comparison query is configured to match_day_of_week? , it will be shifted to start on Sunday, January 2nd, 2022 instead of January 1st. Defaults to false.","ref":"Plausible.Stats.Comparisons.html#compare/4","title":"Plausible.Stats.Comparisons.compare/4","type":"function"},{"doc":"","ref":"Plausible.Stats.Comparisons.html#t:mode/0","title":"Plausible.Stats.Comparisons.mode/0","type":"type"},{"doc":"","ref":"Plausible.Stats.CurrentVisitors.html","title":"Plausible.Stats.CurrentVisitors","type":"module"},{"doc":"","ref":"Plausible.Stats.CurrentVisitors.html#current_visitors/1","title":"Plausible.Stats.CurrentVisitors.current_visitors/1","type":"function"},{"doc":"Module for querying user defined 'custom properties'.","ref":"Plausible.Stats.CustomProps.html","title":"Plausible.Stats.CustomProps","type":"module"},{"doc":"","ref":"Plausible.Stats.CustomProps.html#maybe_allowed_props_only/2","title":"Plausible.Stats.CustomProps.maybe_allowed_props_only/2","type":"function"},{"doc":"Returns a breakdown of event names with all existing custom properties for each event name.","ref":"Plausible.Stats.CustomProps.html#props_for_all_event_names/2","title":"Plausible.Stats.CustomProps.props_for_all_event_names/2","type":"function"},{"doc":"Expects a single goal filter in the query. Returns a list of custom props for that goal. Works for both custom event and pageview goals.","ref":"Plausible.Stats.CustomProps.html#props_for_goal/2","title":"Plausible.Stats.CustomProps.props_for_goal/2","type":"function"},{"doc":"A module for parsing filters used in stat queries.","ref":"Plausible.Stats.FilterParser.html","title":"Plausible.Stats.FilterParser","type":"module"},{"doc":"Parses different filter formats. Depending on the format and type of the filters argument, returns: a decoded map, when filters is encoded JSON a parsed filter map, when filters is a filter expression string the same map, when filters is a map Returns an empty map when argument type is unexpected (e.g. nil ). Examples: iex> FilterParser . parse_filters ( "{ \\" page \\" : \\" /blog/** \\" }" ) %{ "page" => "/blog/**" } iex> FilterParser . parse_filters ( "visit:browser!=Chrome" ) %{ "visit:browser" => { :is_not , "Chrome" } } iex> FilterParser . parse_filters ( nil ) %{ }","ref":"Plausible.Stats.FilterParser.html#parse_filters/1","title":"Plausible.Stats.FilterParser.parse_filters/1","type":"function"},{"doc":"","ref":"Plausible.Stats.FilterSuggestions.html","title":"Plausible.Stats.FilterSuggestions","type":"module"},{"doc":"","ref":"Plausible.Stats.FilterSuggestions.html#filter_suggestions/4","title":"Plausible.Stats.FilterSuggestions.filter_suggestions/4","type":"function"},{"doc":"","ref":"Plausible.Stats.Filters.html","title":"Plausible.Stats.Filters","type":"module"},{"doc":"","ref":"Plausible.Stats.Filters.html#add_prefix/1","title":"Plausible.Stats.Filters.add_prefix/1","type":"function"},{"doc":"","ref":"Plausible.Stats.Filters.html#visit_props/0","title":"Plausible.Stats.Filters.visit_props/0","type":"function"},{"doc":"","ref":"Plausible.Stats.Fragments.html","title":"Plausible.Stats.Fragments","type":"module"},{"doc":"","ref":"Plausible.Stats.Fragments.html#bounce_rate/0","title":"Plausible.Stats.Fragments.bounce_rate/0","type":"macro"},{"doc":"","ref":"Plausible.Stats.Fragments.html#coalesce_string/2","title":"Plausible.Stats.Fragments.coalesce_string/2","type":"macro"},{"doc":"","ref":"Plausible.Stats.Fragments.html#sample_percent/0","title":"Plausible.Stats.Fragments.sample_percent/0","type":"macro"},{"doc":"Converts time or date and time to the specified timezone. Reference: https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions/#totimezone","ref":"Plausible.Stats.Fragments.html#to_timezone/2","title":"Plausible.Stats.Fragments.to_timezone/2","type":"macro"},{"doc":"","ref":"Plausible.Stats.Fragments.html#total/0","title":"Plausible.Stats.Fragments.total/0","type":"macro"},{"doc":"","ref":"Plausible.Stats.Fragments.html#uniq/1","title":"Plausible.Stats.Fragments.uniq/1","type":"macro"},{"doc":"","ref":"Plausible.Stats.Fragments.html#visit_duration/0","title":"Plausible.Stats.Fragments.visit_duration/0","type":"macro"},{"doc":"Returns the weekstart for date . If the weekstart is before the not_before boundary, not_before is returned. Examples In this pseudo-code example, the fragment returns the weekstart. The not_before boundary is set to the past Saturday, which is before the weekstart, therefore the cap does not apply. iex> this_wednesday = ~D[2022-11-09] ...> past_saturday = ~D[2022-11-05] ...> weekstart_not_before(this_wednesday, past_saturday) ~D[2022-11-07] In this other example, the fragment returns Tuesday and not the weekstart. The not_before boundary is set to Tuesday, which is past the weekstart, therefore the cap applies. iex> this_wednesday = ~D[2022-11-09] ...> this_tuesday = ~D[2022-11-08] ...> weekstart_not_before(this_wednesday, this_tuesday) ~D[2022-11-08]","ref":"Plausible.Stats.Fragments.html#weekstart_not_before/2","title":"Plausible.Stats.Fragments.weekstart_not_before/2","type":"macro"},{"doc":"Same as Plausible.Stats.Fragments.weekstart_not_before/2 but converts dates to the specified timezone.","ref":"Plausible.Stats.Fragments.html#weekstart_not_before/3","title":"Plausible.Stats.Fragments.weekstart_not_before/3","type":"macro"},{"doc":"Module responsible for funnel evaluation, i.e. building and executing ClickHouse funnel query based on Plausible.Funnel definition.","ref":"Plausible.Stats.Funnel.html","title":"Plausible.Stats.Funnel","type":"module"},{"doc":"","ref":"Plausible.Stats.Funnel.html#funnel/3","title":"Plausible.Stats.Funnel.funnel/3","type":"function"},{"doc":"","ref":"Plausible.Stats.Imported.html","title":"Plausible.Stats.Imported","type":"module"},{"doc":"","ref":"Plausible.Stats.Imported.html#merge_imported/5","title":"Plausible.Stats.Imported.merge_imported/5","type":"function"},{"doc":"","ref":"Plausible.Stats.Imported.html#merge_imported_timeseries/4","title":"Plausible.Stats.Imported.merge_imported_timeseries/4","type":"function"},{"doc":"Collection of functions to work with intervals. The interval of a query defines the granularity of the data. You can think of it as a GROUP BY clause. Possible values are minute , hour , date , week , and month .","ref":"Plausible.Stats.Interval.html","title":"Plausible.Stats.Interval","type":"module"},{"doc":"Returns the suggested interval for the given Date.Range struct. Examples iex> Plausible.Stats.Interval.default_for_date_range(Date.range(~D[2022-01-01], ~D[2023-01-01])) "month" iex> Plausible.Stats.Interval.default_for_date_range(Date.range(~D[2022-01-01], ~D[2022-01-15])) "date" iex> Plausible.Stats.Interval.default_for_date_range(Date.range(~D[2022-01-01], ~D[2022-01-01])) "hour"","ref":"Plausible.Stats.Interval.html#default_for_date_range/1","title":"Plausible.Stats.Interval.default_for_date_range/1","type":"function"},{"doc":"Returns the suggested interval for the given time period. Examples iex> Plausible.Stats.Interval.default_for_period("7d") "date"","ref":"Plausible.Stats.Interval.html#default_for_period/1","title":"Plausible.Stats.Interval.default_for_period/1","type":"function"},{"doc":"","ref":"Plausible.Stats.Interval.html#list/0","title":"Plausible.Stats.Interval.list/0","type":"function"},{"doc":"","ref":"Plausible.Stats.Interval.html#valid?/1","title":"Plausible.Stats.Interval.valid?/1","type":"function"},{"doc":"","ref":"Plausible.Stats.Interval.html#valid_by_period/0","title":"Plausible.Stats.Interval.valid_by_period/0","type":"function"},{"doc":"Returns whether the given interval is valid for a time period. Intervals longer than periods are not supported, e.g. current month stats with a month interval, or today stats with a week interval. Examples iex> Plausible.Stats.Interval.valid_for_period?("month", "date") true iex> Plausible.Stats.Interval.valid_for_period?("30d", "month") false iex> Plausible.Stats.Interval.valid_for_period?("realtime", "week") false","ref":"Plausible.Stats.Interval.html#valid_for_period?/2","title":"Plausible.Stats.Interval.valid_for_period?/2","type":"function"},{"doc":"","ref":"Plausible.Stats.Interval.html#t:t/0","title":"Plausible.Stats.Interval.t/0","type":"type"},{"doc":"","ref":"Plausible.Stats.Props.html","title":"Plausible.Stats.Props","type":"module"},{"doc":"","ref":"Plausible.Stats.Props.html#event_props/0","title":"Plausible.Stats.Props.event_props/0","type":"function"},{"doc":"","ref":"Plausible.Stats.Props.html#valid_prop?/1","title":"Plausible.Stats.Props.valid_prop?/1","type":"function"},{"doc":"","ref":"Plausible.Stats.Query.html","title":"Plausible.Stats.Query","type":"module"},{"doc":"","ref":"Plausible.Stats.Query.html#from/2","title":"Plausible.Stats.Query.from/2","type":"function"},{"doc":"","ref":"Plausible.Stats.Query.html#get_filter_by_prefix/2","title":"Plausible.Stats.Query.get_filter_by_prefix/2","type":"function"},{"doc":"","ref":"Plausible.Stats.Query.html#has_event_filters?/1","title":"Plausible.Stats.Query.has_event_filters?/1","type":"function"},{"doc":"","ref":"Plausible.Stats.Query.html#include_imported?/3","title":"Plausible.Stats.Query.include_imported?/3","type":"function"},{"doc":"","ref":"Plausible.Stats.Query.html#put_filter/3","title":"Plausible.Stats.Query.put_filter/3","type":"function"},{"doc":"","ref":"Plausible.Stats.Query.html#remove_event_filters/2","title":"Plausible.Stats.Query.remove_event_filters/2","type":"function"},{"doc":"","ref":"Plausible.Stats.Query.html#trace/1","title":"Plausible.Stats.Query.trace/1","type":"function"},{"doc":"","ref":"Plausible.Stats.Query.html#t:t/0","title":"Plausible.Stats.Query.t/0","type":"type"},{"doc":"","ref":"Plausible.Stats.Timeseries.html","title":"Plausible.Stats.Timeseries","type":"module"},{"doc":"","ref":"Plausible.Stats.Timeseries.html#timeseries/3","title":"Plausible.Stats.Timeseries.timeseries/3","type":"function"},{"doc":"","ref":"Plausible.Stats.Timeseries.html#t:results/0","title":"Plausible.Stats.Timeseries.results/0","type":"type"},{"doc":"Utilities for modifying stat results","ref":"Plausible.Stats.Util.html","title":"Plausible.Stats.Util","type":"module"},{"doc":"","ref":"Plausible.Stats.Util.html#cast_revenue_metrics_to_money/2","title":"Plausible.Stats.Util.cast_revenue_metrics_to_money/2","type":"function"},{"doc":"Returns the common currency for the goal filters in a query. If there are no goal filters, or multiple currencies, nil is returned and revenue metrics are dropped. Aggregating revenue data works only for same currency goals. If the query is filtered by goals with different currencies, for example, one USD and other EUR, revenue metrics are dropped.","ref":"Plausible.Stats.Util.html#get_revenue_tracking_currency/3","title":"Plausible.Stats.Util.get_revenue_tracking_currency/3","type":"function"},{"doc":"","ref":"Plausible.Stats.Util.html#remove_internal_visits_metric/1","title":"Plausible.Stats.Util.remove_internal_visits_metric/1","type":"function"},{"doc":"__internal_visits is fetched when querying bounce rate and visit duration, as it is needed to calculate these from imported data. This function removes that metric from all entries in the results list.","ref":"Plausible.Stats.Util.html#remove_internal_visits_metric/2","title":"Plausible.Stats.Util.remove_internal_visits_metric/2","type":"function"},{"doc":"Floki wrappers to help make assertions about HTML/DOM structures","ref":"Plausible.Test.Support.HTML.html","title":"Plausible.Test.Support.HTML","type":"module"},{"doc":"","ref":"Plausible.Test.Support.HTML.html#element_exists?/2","title":"Plausible.Test.Support.HTML.element_exists?/2","type":"function"},{"doc":"","ref":"Plausible.Test.Support.HTML.html#find/2","title":"Plausible.Test.Support.HTML.find/2","type":"function"},{"doc":"","ref":"Plausible.Test.Support.HTML.html#form_exists?/2","title":"Plausible.Test.Support.HTML.form_exists?/2","type":"function"},{"doc":"","ref":"Plausible.Test.Support.HTML.html#submit_button/2","title":"Plausible.Test.Support.HTML.submit_button/2","type":"function"},{"doc":"","ref":"Plausible.Test.Support.HTML.html#text_of_attr/2","title":"Plausible.Test.Support.HTML.text_of_attr/2","type":"function"},{"doc":"","ref":"Plausible.Test.Support.HTML.html#text_of_element/2","title":"Plausible.Test.Support.HTML.text_of_element/2","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html","title":"Plausible.TestUtils","type":"module"},{"doc":"","ref":"Plausible.TestUtils.html#add_imported_data/1","title":"Plausible.TestUtils.add_imported_data/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#await_clickhouse_count/2","title":"Plausible.TestUtils.await_clickhouse_count/2","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#create_api_key/1","title":"Plausible.TestUtils.create_api_key/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#create_events/1","title":"Plausible.TestUtils.create_events/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#create_new_site/1","title":"Plausible.TestUtils.create_new_site/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#create_pageviews/1","title":"Plausible.TestUtils.create_pageviews/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#create_sessions/1","title":"Plausible.TestUtils.create_sessions/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#create_site/1","title":"Plausible.TestUtils.create_site/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#create_user/1","title":"Plausible.TestUtils.create_user/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#eventually/3","title":"Plausible.TestUtils.eventually/3","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#init_session/1","title":"Plausible.TestUtils.init_session/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#log_in/1","title":"Plausible.TestUtils.log_in/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#patch_env/2","title":"Plausible.TestUtils.patch_env/2","type":"macro"},{"doc":"","ref":"Plausible.TestUtils.html#populate_stats/1","title":"Plausible.TestUtils.populate_stats/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#populate_stats/2","title":"Plausible.TestUtils.populate_stats/2","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#relative_time/1","title":"Plausible.TestUtils.relative_time/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#setup_patch_env/2","title":"Plausible.TestUtils.setup_patch_env/2","type":"macro"},{"doc":"","ref":"Plausible.TestUtils.html#to_naive_truncate/1","title":"Plausible.TestUtils.to_naive_truncate/1","type":"function"},{"doc":"","ref":"Plausible.TestUtils.html#use_api_key/1","title":"Plausible.TestUtils.use_api_key/1","type":"function"},{"doc":"","ref":"Plausible.Themes.html","title":"Plausible.Themes","type":"module"},{"doc":"","ref":"Plausible.Themes.html#options/0","title":"Plausible.Themes.options/0","type":"function"},{"doc":"","ref":"Plausible.Timezones.html","title":"Plausible.Timezones","type":"module"},{"doc":"","ref":"Plausible.Timezones.html#options/1","title":"Plausible.Timezones.options/1","type":"function"},{"doc":"","ref":"Plausible.Workers.CheckUsage.html","title":"Plausible.Workers.CheckUsage","type":"module"},{"doc":"","ref":"Plausible.Workers.CheckUsage.html#check_enterprise_subscriber/2","title":"Plausible.Workers.CheckUsage.check_enterprise_subscriber/2","type":"function"},{"doc":"","ref":"Plausible.Workers.CheckUsage.html#day_of_month/1","title":"Plausible.Workers.CheckUsage.day_of_month/1","type":"macro"},{"doc":"","ref":"Plausible.Workers.CheckUsage.html#last_day_of_month/1","title":"Plausible.Workers.CheckUsage.last_day_of_month/1","type":"macro"},{"doc":"","ref":"Plausible.Workers.CheckUsage.html#least/2","title":"Plausible.Workers.CheckUsage.least/2","type":"macro"},{"doc":"","ref":"Plausible.Workers.CheckUsage.html#yesterday/0","title":"Plausible.Workers.CheckUsage.yesterday/0","type":"macro"},{"doc":"","ref":"Plausible.Workers.CleanEmailVerificationCodes.html","title":"Plausible.Workers.CleanEmailVerificationCodes","type":"module"},{"doc":"","ref":"Plausible.Workers.CleanInvitations.html","title":"Plausible.Workers.CleanInvitations","type":"module"},{"doc":"Periodic worker that expires domain change transition period. Old domains are frozen for a given time, so users can still access them before redeploying their scripts and integrations.","ref":"Plausible.Workers.ExpireDomainChangeTransitions.html","title":"Plausible.Workers.ExpireDomainChangeTransitions","type":"module"},{"doc":"","ref":"Plausible.Workers.ImportGoogleAnalytics.html","title":"Plausible.Workers.ImportGoogleAnalytics","type":"module"},{"doc":"","ref":"Plausible.Workers.ImportGoogleAnalytics.html#import_failed/1","title":"Plausible.Workers.ImportGoogleAnalytics.import_failed/1","type":"function"},{"doc":"","ref":"Plausible.Workers.LockSites.html","title":"Plausible.Workers.LockSites","type":"module"},{"doc":"","ref":"Plausible.Workers.NotifyAnnualRenewal.html","title":"Plausible.Workers.NotifyAnnualRenewal","type":"module"},{"doc":"Sends a notification at most 7 days and at least 1 day before the renewal of an annual subscription","ref":"Plausible.Workers.NotifyAnnualRenewal.html#perform/1","title":"Plausible.Workers.NotifyAnnualRenewal.perform/1","type":"function"},{"doc":"","ref":"Plausible.Workers.RotateSalts.html","title":"Plausible.Workers.RotateSalts","type":"module"},{"doc":"","ref":"Plausible.Workers.ScheduleEmailReports.html","title":"Plausible.Workers.ScheduleEmailReports","type":"module"},{"doc":"","ref":"Plausible.Workers.ScheduleEmailReports.html#first_of_month_9am/1","title":"Plausible.Workers.ScheduleEmailReports.first_of_month_9am/1","type":"function"},{"doc":"","ref":"Plausible.Workers.ScheduleEmailReports.html#monday_9am/1","title":"Plausible.Workers.ScheduleEmailReports.monday_9am/1","type":"function"},{"doc":"Email reports should be sent on Monday at 9am according to the timezone of a site. This job runs every day at midnight to ensure that all sites have a scheduled job for email reports.","ref":"Plausible.Workers.ScheduleEmailReports.html#perform/1","title":"Plausible.Workers.ScheduleEmailReports.perform/1","type":"function"},{"doc":"","ref":"Plausible.Workers.SendCheckStatsEmails.html","title":"Plausible.Workers.SendCheckStatsEmails","type":"module"},{"doc":"","ref":"Plausible.Workers.SendEmailReport.html","title":"Plausible.Workers.SendEmailReport","type":"module"},{"doc":"","ref":"Plausible.Workers.SendSiteSetupEmails.html","title":"Plausible.Workers.SendSiteSetupEmails","type":"module"},{"doc":"","ref":"Plausible.Workers.SendTrialNotifications.html","title":"Plausible.Workers.SendTrialNotifications","type":"module"},{"doc":"","ref":"Plausible.Workers.SpikeNotifier.html","title":"Plausible.Workers.SpikeNotifier","type":"module"},{"doc":"","ref":"PlausibleWeb.html","title":"PlausibleWeb","type":"module"},{"doc":"When used, dispatch to the appropriate controller/view/etc.","ref":"PlausibleWeb.html#__using__/1","title":"PlausibleWeb.__using__/1","type":"macro"},{"doc":"","ref":"PlausibleWeb.html#channel/0","title":"PlausibleWeb.channel/0","type":"function"},{"doc":"","ref":"PlausibleWeb.html#controller/0","title":"PlausibleWeb.controller/0","type":"function"},{"doc":"","ref":"PlausibleWeb.html#router/0","title":"PlausibleWeb.router/0","type":"function"},{"doc":"","ref":"PlausibleWeb.html#view/0","title":"PlausibleWeb.view/0","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalController.html","title":"PlausibleWeb.Api.ExternalController","type":"module"},{"doc":"","ref":"PlausibleWeb.Api.ExternalController.html#error/2","title":"PlausibleWeb.Api.ExternalController.error/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalController.html#event/2","title":"PlausibleWeb.Api.ExternalController.event/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalController.html#health/2","title":"PlausibleWeb.Api.ExternalController.health/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalController.html#info/2","title":"PlausibleWeb.Api.ExternalController.info/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalSitesController.html","title":"PlausibleWeb.Api.ExternalSitesController","type":"module"},{"doc":"","ref":"PlausibleWeb.Api.ExternalSitesController.html#create_site/2","title":"PlausibleWeb.Api.ExternalSitesController.create_site/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalSitesController.html#delete_goal/2","title":"PlausibleWeb.Api.ExternalSitesController.delete_goal/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalSitesController.html#delete_site/2","title":"PlausibleWeb.Api.ExternalSitesController.delete_site/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalSitesController.html#find_or_create_goal/2","title":"PlausibleWeb.Api.ExternalSitesController.find_or_create_goal/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalSitesController.html#find_or_create_shared_link/2","title":"PlausibleWeb.Api.ExternalSitesController.find_or_create_shared_link/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalSitesController.html#get_site/2","title":"PlausibleWeb.Api.ExternalSitesController.get_site/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalSitesController.html#update_site/2","title":"PlausibleWeb.Api.ExternalSitesController.update_site/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalStatsController.html","title":"PlausibleWeb.Api.ExternalStatsController","type":"module"},{"doc":"","ref":"PlausibleWeb.Api.ExternalStatsController.html#aggregate/2","title":"PlausibleWeb.Api.ExternalStatsController.aggregate/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalStatsController.html#breakdown/2","title":"PlausibleWeb.Api.ExternalStatsController.breakdown/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalStatsController.html#realtime_visitors/2","title":"PlausibleWeb.Api.ExternalStatsController.realtime_visitors/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.ExternalStatsController.html#timeseries/2","title":"PlausibleWeb.Api.ExternalStatsController.timeseries/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.Helpers.html","title":"PlausibleWeb.Api.Helpers","type":"module"},{"doc":"","ref":"PlausibleWeb.Api.Helpers.html#bad_request/2","title":"PlausibleWeb.Api.Helpers.bad_request/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.Helpers.html#not_found/2","title":"PlausibleWeb.Api.Helpers.not_found/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.Helpers.html#payment_required/2","title":"PlausibleWeb.Api.Helpers.payment_required/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.Helpers.html#too_many_requests/2","title":"PlausibleWeb.Api.Helpers.too_many_requests/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.Helpers.html#unauthorized/2","title":"PlausibleWeb.Api.Helpers.unauthorized/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.InternalController.html","title":"PlausibleWeb.Api.InternalController","type":"module"},{"doc":"","ref":"PlausibleWeb.Api.InternalController.html#disable_feature/2","title":"PlausibleWeb.Api.InternalController.disable_feature/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.InternalController.html#domain_status/2","title":"PlausibleWeb.Api.InternalController.domain_status/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.InternalController.html#sites/2","title":"PlausibleWeb.Api.InternalController.sites/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.PaddleController.html","title":"PlausibleWeb.Api.PaddleController","type":"module"},{"doc":"","ref":"PlausibleWeb.Api.PaddleController.html#verified_signature?/1","title":"PlausibleWeb.Api.PaddleController.verified_signature?/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.PaddleController.html#verify_signature/2","title":"PlausibleWeb.Api.PaddleController.verify_signature/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.PaddleController.html#webhook/2","title":"PlausibleWeb.Api.PaddleController.webhook/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html","title":"PlausibleWeb.Api.StatsController","type":"module"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#all_props_breakdown/2","title":"PlausibleWeb.Api.StatsController.all_props_breakdown/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#browser_versions/2","title":"PlausibleWeb.Api.StatsController.browser_versions/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#browsers/2","title":"PlausibleWeb.Api.StatsController.browsers/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#cities/2","title":"PlausibleWeb.Api.StatsController.cities/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#conversions/2","title":"PlausibleWeb.Api.StatsController.conversions/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#countries/2","title":"PlausibleWeb.Api.StatsController.countries/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#current_visitors/2","title":"PlausibleWeb.Api.StatsController.current_visitors/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#custom_prop_values/2","title":"PlausibleWeb.Api.StatsController.custom_prop_values/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#entry_pages/2","title":"PlausibleWeb.Api.StatsController.entry_pages/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#exit_pages/2","title":"PlausibleWeb.Api.StatsController.exit_pages/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#filter_suggestions/2","title":"PlausibleWeb.Api.StatsController.filter_suggestions/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#funnel/2","title":"PlausibleWeb.Api.StatsController.funnel/2","type":"function"},{"doc":"Returns a time-series based on given parameters. Parameters This API accepts the following parameters: period - x-axis of the graph, e.g. 12mo , day , custom . metric - y-axis of the graph, e.g. visits , visitors , pageviews . See the Stats API "Metrics" section for more details. Defaults to visitors . interval - granularity of the time-series data. You can think of it as a GROUP BY clause. Possible values are minute , hour , date , week , and month . The default depends on the period parameter. Check Plausible.Query.from/2 for each default. filters - optional filters to drill down data. See the Stats API "Filtering" section for more details. with_imported - boolean indicating whether to include Google Analytics imported data or not. Defaults to false . Full example: %{ "from" => "2021-09-06" , "interval" => "month" , "metric" => "visitors" , "period" => "custom" , "to" => "2021-12-13" } Response Returns a map with the following keys: plot - list of values for the requested metric representing the y-axis of the graph. labels - list of date times representing the x-axis of the graph. present_index - index of the element representing the current date in labels and plot lists. interval - the interval used for querying. with_imported - boolean indicating whether the Google Analytics data was queried or not. imported_source - the source of the imported data, when applicable. Currently only Google Analytics is supported. full_intervals - map of dates indicating whether the interval has been cut off by the requested date range or not. For example, if looking at a month week-by-week, some weeks may be cut off by the month boundaries. It's useful to adjust the graph display slightly in case the interval is not 'full' so that the user understands why the numbers might be lower for those partial periods. Full example: %{ "full_intervals" => %{ "2021-09-01" => false , "2021-10-01" => true , "2021-11-01" => true , "2021-12-01" => false } , "imported_source" => nil , "interval" => "month" , "labels" => [ "2021-09-01" , "2021-10-01" , "2021-11-01" , "2021-12-01" ] , "plot" => [ 0 , 0 , 0 , 0 ] , "present_index" => nil , "with_imported" => false }","ref":"PlausibleWeb.Api.StatsController.html#main_graph/2","title":"PlausibleWeb.Api.StatsController.main_graph/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#operating_system_versions/2","title":"PlausibleWeb.Api.StatsController.operating_system_versions/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#operating_systems/2","title":"PlausibleWeb.Api.StatsController.operating_systems/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#pages/2","title":"PlausibleWeb.Api.StatsController.pages/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#prop_breakdown/2","title":"PlausibleWeb.Api.StatsController.prop_breakdown/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#referrer_drilldown/2","title":"PlausibleWeb.Api.StatsController.referrer_drilldown/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#regions/2","title":"PlausibleWeb.Api.StatsController.regions/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#screen_sizes/2","title":"PlausibleWeb.Api.StatsController.screen_sizes/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#sources/2","title":"PlausibleWeb.Api.StatsController.sources/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#top_stats/2","title":"PlausibleWeb.Api.StatsController.top_stats/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#utm_campaigns/2","title":"PlausibleWeb.Api.StatsController.utm_campaigns/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#utm_contents/2","title":"PlausibleWeb.Api.StatsController.utm_contents/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#utm_mediums/2","title":"PlausibleWeb.Api.StatsController.utm_mediums/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#utm_sources/2","title":"PlausibleWeb.Api.StatsController.utm_sources/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Api.StatsController.html#utm_terms/2","title":"PlausibleWeb.Api.StatsController.utm_terms/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html","title":"PlausibleWeb.AuthController","type":"module"},{"doc":"","ref":"PlausibleWeb.AuthController.html#activate/2","title":"PlausibleWeb.AuthController.activate/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#activate_form/2","title":"PlausibleWeb.AuthController.activate_form/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#create_api_key/2","title":"PlausibleWeb.AuthController.create_api_key/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#delete_api_key/2","title":"PlausibleWeb.AuthController.delete_api_key/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#delete_me/2","title":"PlausibleWeb.AuthController.delete_me/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#google_auth_callback/2","title":"PlausibleWeb.AuthController.google_auth_callback/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#login/2","title":"PlausibleWeb.AuthController.login/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#login_form/2","title":"PlausibleWeb.AuthController.login_form/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#logout/2","title":"PlausibleWeb.AuthController.logout/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#new_api_key/2","title":"PlausibleWeb.AuthController.new_api_key/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#password_form/2","title":"PlausibleWeb.AuthController.password_form/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#password_reset/2","title":"PlausibleWeb.AuthController.password_reset/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#password_reset_form/2","title":"PlausibleWeb.AuthController.password_reset_form/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#password_reset_request/2","title":"PlausibleWeb.AuthController.password_reset_request/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#password_reset_request_form/2","title":"PlausibleWeb.AuthController.password_reset_request_form/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#register/2","title":"PlausibleWeb.AuthController.register/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#register_form/2","title":"PlausibleWeb.AuthController.register_form/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#register_from_invitation/2","title":"PlausibleWeb.AuthController.register_from_invitation/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#register_from_invitation_form/2","title":"PlausibleWeb.AuthController.register_from_invitation_form/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#request_activation_code/2","title":"PlausibleWeb.AuthController.request_activation_code/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#save_settings/2","title":"PlausibleWeb.AuthController.save_settings/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#set_password/2","title":"PlausibleWeb.AuthController.set_password/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthController.html#user_settings/2","title":"PlausibleWeb.AuthController.user_settings/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthPlug.html","title":"PlausibleWeb.AuthPlug","type":"module"},{"doc":"","ref":"PlausibleWeb.AuthPlug.html#call/2","title":"PlausibleWeb.AuthPlug.call/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthPlug.html#init/1","title":"PlausibleWeb.AuthPlug.init/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html","title":"PlausibleWeb.AuthView","type":"module"},{"doc":"The resource name, as an atom, for this view","ref":"PlausibleWeb.AuthView.html#__resource__/0","title":"PlausibleWeb.AuthView.__resource__/0","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#activate.html/1","title":"PlausibleWeb.AuthView.activate.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#base_domain/0","title":"PlausibleWeb.AuthView.base_domain/0","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#delimit_integer/1","title":"PlausibleWeb.AuthView.delimit_integer/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#format_invoices/1","title":"PlausibleWeb.AuthView.format_invoices/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#invitation_expired.html/1","title":"PlausibleWeb.AuthView.invitation_expired.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#login_form.html/1","title":"PlausibleWeb.AuthView.login_form.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#new_api_key.html/1","title":"PlausibleWeb.AuthView.new_api_key.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#password_form.html/1","title":"PlausibleWeb.AuthView.password_form.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#password_reset_form.html/1","title":"PlausibleWeb.AuthView.password_reset_form.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#password_reset_request_form.html/1","title":"PlausibleWeb.AuthView.password_reset_request_form.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#password_reset_request_success.html/1","title":"PlausibleWeb.AuthView.password_reset_request_success.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#plausible_url/0","title":"PlausibleWeb.AuthView.plausible_url/0","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#present_subscription_status/1","title":"PlausibleWeb.AuthView.present_subscription_status/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#register_form.html/1","title":"PlausibleWeb.AuthView.register_form.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#register_from_invitation_form.html/1","title":"PlausibleWeb.AuthView.register_from_invitation_form.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#register_success.html/1","title":"PlausibleWeb.AuthView.register_success.html/1","type":"function"},{"doc":"Renders the given template locally.","ref":"PlausibleWeb.AuthView.html#render/2","title":"PlausibleWeb.AuthView.render/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#subscription_colors/1","title":"PlausibleWeb.AuthView.subscription_colors/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#subscription_interval/1","title":"PlausibleWeb.AuthView.subscription_interval/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#subscription_quota/1","title":"PlausibleWeb.AuthView.subscription_quota/1","type":"function"},{"doc":"Callback invoked when no template is found. By default it raises but can be customized to render a particular template.","ref":"PlausibleWeb.AuthView.html#template_not_found/2","title":"PlausibleWeb.AuthView.template_not_found/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthView.html#user_settings.html/1","title":"PlausibleWeb.AuthView.user_settings.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthorizeSiteAccess.html","title":"PlausibleWeb.AuthorizeSiteAccess","type":"module"},{"doc":"","ref":"PlausibleWeb.AuthorizeSiteAccess.html#call/2","title":"PlausibleWeb.AuthorizeSiteAccess.call/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthorizeSiteAccess.html#init/1","title":"PlausibleWeb.AuthorizeSiteAccess.init/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthorizeSitesApiPlug.html","title":"PlausibleWeb.AuthorizeSitesApiPlug","type":"module"},{"doc":"","ref":"PlausibleWeb.AuthorizeSitesApiPlug.html#call/2","title":"PlausibleWeb.AuthorizeSitesApiPlug.call/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthorizeSitesApiPlug.html#init/1","title":"PlausibleWeb.AuthorizeSitesApiPlug.init/1","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthorizeStatsApiPlug.html","title":"PlausibleWeb.AuthorizeStatsApiPlug","type":"module"},{"doc":"","ref":"PlausibleWeb.AuthorizeStatsApiPlug.html#call/2","title":"PlausibleWeb.AuthorizeStatsApiPlug.call/2","type":"function"},{"doc":"","ref":"PlausibleWeb.AuthorizeStatsApiPlug.html#init/1","title":"PlausibleWeb.AuthorizeStatsApiPlug.init/1","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingController.html","title":"PlausibleWeb.BillingController","type":"module"},{"doc":"","ref":"PlausibleWeb.BillingController.html#change_enterprise_plan/2","title":"PlausibleWeb.BillingController.change_enterprise_plan/2","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingController.html#change_plan/2","title":"PlausibleWeb.BillingController.change_plan/2","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingController.html#change_plan_form/2","title":"PlausibleWeb.BillingController.change_plan_form/2","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingController.html#change_plan_preview/2","title":"PlausibleWeb.BillingController.change_plan_preview/2","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingController.html#ping_subscription/2","title":"PlausibleWeb.BillingController.ping_subscription/2","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingController.html#preview_susbcription/2","title":"PlausibleWeb.BillingController.preview_susbcription/2","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingController.html#upgrade/2","title":"PlausibleWeb.BillingController.upgrade/2","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingController.html#upgrade_enterprise_plan/2","title":"PlausibleWeb.BillingController.upgrade_enterprise_plan/2","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingController.html#upgrade_success/2","title":"PlausibleWeb.BillingController.upgrade_success/2","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html","title":"PlausibleWeb.BillingView","type":"module"},{"doc":"The resource name, as an atom, for this view","ref":"PlausibleWeb.BillingView.html#__resource__/0","title":"PlausibleWeb.BillingView.__resource__/0","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html#base_domain/0","title":"PlausibleWeb.BillingView.base_domain/0","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html#change_enterprise_plan.html/1","title":"PlausibleWeb.BillingView.change_enterprise_plan.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html#change_enterprise_plan_contact_us.html/1","title":"PlausibleWeb.BillingView.change_enterprise_plan_contact_us.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html#change_plan.html/1","title":"PlausibleWeb.BillingView.change_plan.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html#change_plan_preview.html/1","title":"PlausibleWeb.BillingView.change_plan_preview.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html#plausible_url/0","title":"PlausibleWeb.BillingView.plausible_url/0","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html#present_currency/1","title":"PlausibleWeb.BillingView.present_currency/1","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html#present_date/1","title":"PlausibleWeb.BillingView.present_date/1","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html#reccommended_plan/1","title":"PlausibleWeb.BillingView.reccommended_plan/1","type":"function"},{"doc":"Renders the given template locally.","ref":"PlausibleWeb.BillingView.html#render/2","title":"PlausibleWeb.BillingView.render/2","type":"function"},{"doc":"Callback invoked when no template is found. By default it raises but can be customized to render a particular template.","ref":"PlausibleWeb.BillingView.html#template_not_found/2","title":"PlausibleWeb.BillingView.template_not_found/2","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html#upgrade.html/1","title":"PlausibleWeb.BillingView.upgrade.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html#upgrade_success.html/1","title":"PlausibleWeb.BillingView.upgrade_success.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.BillingView.html#upgrade_to_plan.html/1","title":"PlausibleWeb.BillingView.upgrade_to_plan.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.CRMAuthPlug.html","title":"PlausibleWeb.CRMAuthPlug","type":"module"},{"doc":"","ref":"PlausibleWeb.CRMAuthPlug.html#call/2","title":"PlausibleWeb.CRMAuthPlug.call/2","type":"function"},{"doc":"","ref":"PlausibleWeb.CRMAuthPlug.html#init/1","title":"PlausibleWeb.CRMAuthPlug.init/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Captcha.html","title":"PlausibleWeb.Captcha","type":"module"},{"doc":"","ref":"PlausibleWeb.Captcha.html#enabled?/0","title":"PlausibleWeb.Captcha.enabled?/0","type":"function"},{"doc":"","ref":"PlausibleWeb.Captcha.html#sitekey/0","title":"PlausibleWeb.Captcha.sitekey/0","type":"function"},{"doc":"","ref":"PlausibleWeb.Captcha.html#verify/1","title":"PlausibleWeb.Captcha.verify/1","type":"function"},{"doc":"Generic reusable components","ref":"PlausibleWeb.Components.Generic.html","title":"PlausibleWeb.Components.Generic","type":"module"},{"doc":"Attributes title ( :string ) - Defaults to "Notice" . class ( :string ) - Defaults to "" . Slots inner_block","ref":"PlausibleWeb.Components.Generic.html#notice/1","title":"PlausibleWeb.Components.Generic.notice/1","type":"function"},{"doc":"Phoenix Component for rendering a user-facing feature toggle capable of flipping booleans in Plausible.Site via the toggle_feature controller action.","ref":"PlausibleWeb.Components.Site.Feature.html","title":"PlausibleWeb.Components.Site.Feature","type":"module"},{"doc":"The resource name, as an atom, for this view","ref":"PlausibleWeb.Components.Site.Feature.html#__resource__/0","title":"PlausibleWeb.Components.Site.Feature.__resource__/0","type":"function"},{"doc":"","ref":"PlausibleWeb.Components.Site.Feature.html#button_active/1","title":"PlausibleWeb.Components.Site.Feature.button_active/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Components.Site.Feature.html#button_inactive/1","title":"PlausibleWeb.Components.Site.Feature.button_inactive/1","type":"function"},{"doc":"Renders the given template locally.","ref":"PlausibleWeb.Components.Site.Feature.html#render/2","title":"PlausibleWeb.Components.Site.Feature.render/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Components.Site.Feature.html#target/4","title":"PlausibleWeb.Components.Site.Feature.target/4","type":"function"},{"doc":"Callback invoked when no template is found. By default it raises but can be customized to render a particular template.","ref":"PlausibleWeb.Components.Site.Feature.html#template_not_found/2","title":"PlausibleWeb.Components.Site.Feature.template_not_found/2","type":"function"},{"doc":"Attributes site ( Plausible.Site ) (required) setting ( :atom ) (required) label ( :string ) (required) conn ( Plug.Conn ) (required) Slots inner_block","ref":"PlausibleWeb.Components.Site.Feature.html#toggle/1","title":"PlausibleWeb.Components.Site.Feature.toggle/1","type":"function"},{"doc":"This module defines the test case to be used by tests that require setting up a connection. Such tests rely on Phoenix.ConnTest and also import other functionality to make it easier to build common data structures and query the data layer. Finally, if the test case interacts with the database, it cannot be async. For this reason, every test runs inside a transaction which is reset at the beginning of the test unless the test case is marked as async.","ref":"PlausibleWeb.ConnCase.html","title":"PlausibleWeb.ConnCase","type":"module"},{"doc":"","ref":"PlausibleWeb.ControllerHelpers.html","title":"PlausibleWeb.ControllerHelpers","type":"module"},{"doc":"","ref":"PlausibleWeb.ControllerHelpers.html#render_error/2","title":"PlausibleWeb.ControllerHelpers.render_error/2","type":"function"},{"doc":"","ref":"PlausibleWeb.ControllerHelpers.html#render_error/3","title":"PlausibleWeb.ControllerHelpers.render_error/3","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html","title":"PlausibleWeb.Email","type":"module"},{"doc":"","ref":"PlausibleWeb.Email.html#activation_email/2","title":"PlausibleWeb.Email.activation_email/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#base_email/0","title":"PlausibleWeb.Email.base_email/0","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#base_email/1","title":"PlausibleWeb.Email.base_email/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#cancellation_email/1","title":"PlausibleWeb.Email.cancellation_email/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#check_stats_email/1","title":"PlausibleWeb.Email.check_stats_email/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#create_site_email/1","title":"PlausibleWeb.Email.create_site_email/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#dashboard_locked/4","title":"PlausibleWeb.Email.dashboard_locked/4","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#enterprise_over_limit_internal_email/5","title":"PlausibleWeb.Email.enterprise_over_limit_internal_email/5","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#error_report/3","title":"PlausibleWeb.Email.error_report/3","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#existing_user_invitation/1","title":"PlausibleWeb.Email.existing_user_invitation/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#import_failure/2","title":"PlausibleWeb.Email.import_failure/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#import_success/2","title":"PlausibleWeb.Email.import_success/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#invitation_accepted/1","title":"PlausibleWeb.Email.invitation_accepted/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#invitation_rejected/1","title":"PlausibleWeb.Email.invitation_rejected/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#mailer_email_from/0","title":"PlausibleWeb.Email.mailer_email_from/0","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#new_user_invitation/1","title":"PlausibleWeb.Email.new_user_invitation/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#over_limit_email/4","title":"PlausibleWeb.Email.over_limit_email/4","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#ownership_transfer_accepted/1","title":"PlausibleWeb.Email.ownership_transfer_accepted/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#ownership_transfer_rejected/1","title":"PlausibleWeb.Email.ownership_transfer_rejected/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#ownership_transfer_request/2","title":"PlausibleWeb.Email.ownership_transfer_request/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#password_reset_email/2","title":"PlausibleWeb.Email.password_reset_email/2","type":"function"},{"doc":"Render an Phoenix template and set the body on the email. Pass an atom as the template name (:welcome_email) to render HTML and plain text emails. Use a string if you only want to render one type, e.g. "welcome_email.text" or "welcome_email.html". Scroll to the top for more examples.","ref":"PlausibleWeb.Email.html#render/3","title":"PlausibleWeb.Email.render/3","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#site_member_removed/1","title":"PlausibleWeb.Email.site_member_removed/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#site_setup_help/2","title":"PlausibleWeb.Email.site_setup_help/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#site_setup_success/2","title":"PlausibleWeb.Email.site_setup_success/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#spike_notification/5","title":"PlausibleWeb.Email.spike_notification/5","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#trial_one_week_reminder/1","title":"PlausibleWeb.Email.trial_one_week_reminder/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#trial_over_email/1","title":"PlausibleWeb.Email.trial_over_email/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#trial_upgrade_email/3","title":"PlausibleWeb.Email.trial_upgrade_email/3","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#weekly_report/3","title":"PlausibleWeb.Email.weekly_report/3","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#welcome_email/1","title":"PlausibleWeb.Email.welcome_email/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#yearly_expiration_notification/1","title":"PlausibleWeb.Email.yearly_expiration_notification/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Email.html#yearly_renewal_notification/1","title":"PlausibleWeb.Email.yearly_renewal_notification/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html","title":"PlausibleWeb.EmailView","type":"module"},{"doc":"The resource name, as an atom, for this view","ref":"PlausibleWeb.EmailView.html#__resource__/0","title":"PlausibleWeb.EmailView.__resource__/0","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#activation_email.html/1","title":"PlausibleWeb.EmailView.activation_email.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#base_domain/0","title":"PlausibleWeb.EmailView.base_domain/0","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#cancellation_email.html/1","title":"PlausibleWeb.EmailView.cancellation_email.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#check_stats_email.html/1","title":"PlausibleWeb.EmailView.check_stats_email.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#create_site_email.html/1","title":"PlausibleWeb.EmailView.create_site_email.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#dashboard_locked.html/1","title":"PlausibleWeb.EmailView.dashboard_locked.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#date_format/1","title":"PlausibleWeb.EmailView.date_format/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#enterprise_over_limit_internal.html/1","title":"PlausibleWeb.EmailView.enterprise_over_limit_internal.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#error_report_email.html/1","title":"PlausibleWeb.EmailView.error_report_email.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#existing_user_invitation.html/1","title":"PlausibleWeb.EmailView.existing_user_invitation.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#google_analytics_import.html/1","title":"PlausibleWeb.EmailView.google_analytics_import.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#greet_recipient/1","title":"PlausibleWeb.EmailView.greet_recipient/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#invitation_accepted.html/1","title":"PlausibleWeb.EmailView.invitation_accepted.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#invitation_rejected.html/1","title":"PlausibleWeb.EmailView.invitation_rejected.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#new_user_invitation.html/1","title":"PlausibleWeb.EmailView.new_user_invitation.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#over_limit.html/1","title":"PlausibleWeb.EmailView.over_limit.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#ownership_transfer_accepted.html/1","title":"PlausibleWeb.EmailView.ownership_transfer_accepted.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#ownership_transfer_rejected.html/1","title":"PlausibleWeb.EmailView.ownership_transfer_rejected.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#ownership_transfer_request.html/1","title":"PlausibleWeb.EmailView.ownership_transfer_request.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#password_reset_email.html/1","title":"PlausibleWeb.EmailView.password_reset_email.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#plausible_url/0","title":"PlausibleWeb.EmailView.plausible_url/0","type":"function"},{"doc":"Renders the given template locally.","ref":"PlausibleWeb.EmailView.html#render/2","title":"PlausibleWeb.EmailView.render/2","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#sentry_link/2","title":"PlausibleWeb.EmailView.sentry_link/2","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#site_member_removed.html/1","title":"PlausibleWeb.EmailView.site_member_removed.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#site_setup_help_email.html/1","title":"PlausibleWeb.EmailView.site_setup_help_email.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#site_setup_success_email.html/1","title":"PlausibleWeb.EmailView.site_setup_success_email.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#spike_notification.html/1","title":"PlausibleWeb.EmailView.spike_notification.html/1","type":"function"},{"doc":"Callback invoked when no template is found. By default it raises but can be customized to render a particular template.","ref":"PlausibleWeb.EmailView.html#template_not_found/2","title":"PlausibleWeb.EmailView.template_not_found/2","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#trial_one_week_reminder.html/1","title":"PlausibleWeb.EmailView.trial_one_week_reminder.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#trial_over_email.html/1","title":"PlausibleWeb.EmailView.trial_over_email.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#trial_upgrade_email.html/1","title":"PlausibleWeb.EmailView.trial_upgrade_email.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#welcome_email.html/1","title":"PlausibleWeb.EmailView.welcome_email.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#yearly_expiration_notification.html/1","title":"PlausibleWeb.EmailView.yearly_expiration_notification.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.EmailView.html#yearly_renewal_notification.html/1","title":"PlausibleWeb.EmailView.yearly_renewal_notification.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Endpoint.html","title":"PlausibleWeb.Endpoint","type":"module"},{"doc":"Callback implementation for Phoenix.Endpoint.broadcast/3 .","ref":"PlausibleWeb.Endpoint.html#broadcast/3","title":"PlausibleWeb.Endpoint.broadcast/3","type":"function"},{"doc":"Callback implementation for Phoenix.Endpoint.broadcast!/3 .","ref":"PlausibleWeb.Endpoint.html#broadcast!/3","title":"PlausibleWeb.Endpoint.broadcast!/3","type":"function"},{"doc":"Callback implementation for Phoenix.Endpoint.broadcast_from/4 .","ref":"PlausibleWeb.Endpoint.html#broadcast_from/4","title":"PlausibleWeb.Endpoint.broadcast_from/4","type":"function"},{"doc":"Callback implementation for Phoenix.Endpoint.broadcast_from!/4 .","ref":"PlausibleWeb.Endpoint.html#broadcast_from!/4","title":"PlausibleWeb.Endpoint.broadcast_from!/4","type":"function"},{"doc":"Callback implementation for Plug.call/2 .","ref":"PlausibleWeb.Endpoint.html#call/2","title":"PlausibleWeb.Endpoint.call/2","type":"function"},{"doc":"Returns the child specification to start the endpoint under a supervision tree.","ref":"PlausibleWeb.Endpoint.html#child_spec/1","title":"PlausibleWeb.Endpoint.child_spec/1","type":"function"},{"doc":"Returns the endpoint configuration for key Returns default if the key does not exist.","ref":"PlausibleWeb.Endpoint.html#config/2","title":"PlausibleWeb.Endpoint.config/2","type":"function"},{"doc":"Reloads the configuration given the application environment changes.","ref":"PlausibleWeb.Endpoint.html#config_change/2","title":"PlausibleWeb.Endpoint.config_change/2","type":"function"},{"doc":"Returns the host for the given endpoint.","ref":"PlausibleWeb.Endpoint.html#host/0","title":"PlausibleWeb.Endpoint.host/0","type":"function"},{"doc":"Callback implementation for Plug.init/1 .","ref":"PlausibleWeb.Endpoint.html#init/1","title":"PlausibleWeb.Endpoint.init/1","type":"function"},{"doc":"Callback implementation for Phoenix.Endpoint.local_broadcast/3 .","ref":"PlausibleWeb.Endpoint.html#local_broadcast/3","title":"PlausibleWeb.Endpoint.local_broadcast/3","type":"function"},{"doc":"Callback implementation for Phoenix.Endpoint.local_broadcast_from/4 .","ref":"PlausibleWeb.Endpoint.html#local_broadcast_from/4","title":"PlausibleWeb.Endpoint.local_broadcast_from/4","type":"function"},{"doc":"","ref":"PlausibleWeb.Endpoint.html#patch_session_opts/0","title":"PlausibleWeb.Endpoint.patch_session_opts/0","type":"function"},{"doc":"Generates the path information when routing to this endpoint.","ref":"PlausibleWeb.Endpoint.html#path/1","title":"PlausibleWeb.Endpoint.path/1","type":"function"},{"doc":"Generates the script name.","ref":"PlausibleWeb.Endpoint.html#script_name/0","title":"PlausibleWeb.Endpoint.script_name/0","type":"function"},{"doc":"Starts the endpoint supervision tree. All other options are merged into the endpoint configuration.","ref":"PlausibleWeb.Endpoint.html#start_link/1","title":"PlausibleWeb.Endpoint.start_link/1","type":"function"},{"doc":"Generates a base64-encoded cryptographic hash (sha512) to a static file in priv/static . Meant to be used for Subresource Integrity with CDNs.","ref":"PlausibleWeb.Endpoint.html#static_integrity/1","title":"PlausibleWeb.Endpoint.static_integrity/1","type":"function"},{"doc":"Returns a two item tuple with the first item being the static_path and the second item being the static_integrity .","ref":"PlausibleWeb.Endpoint.html#static_lookup/1","title":"PlausibleWeb.Endpoint.static_lookup/1","type":"function"},{"doc":"Generates a route to a static file in priv/static .","ref":"PlausibleWeb.Endpoint.html#static_path/1","title":"PlausibleWeb.Endpoint.static_path/1","type":"function"},{"doc":"Generates the static URL without any path information. It uses the configuration under :static_url to generate such. It falls back to :url if :static_url is not set.","ref":"PlausibleWeb.Endpoint.html#static_url/0","title":"PlausibleWeb.Endpoint.static_url/0","type":"function"},{"doc":"Generates the endpoint base URL but as a URI struct. It uses the configuration under :url to generate such. Useful for manipulating the URL data and passing it to URL helpers.","ref":"PlausibleWeb.Endpoint.html#struct_url/0","title":"PlausibleWeb.Endpoint.struct_url/0","type":"function"},{"doc":"Callback implementation for Phoenix.Endpoint.subscribe/2 .","ref":"PlausibleWeb.Endpoint.html#subscribe/2","title":"PlausibleWeb.Endpoint.subscribe/2","type":"function"},{"doc":"Callback implementation for Phoenix.Endpoint.unsubscribe/1 .","ref":"PlausibleWeb.Endpoint.html#unsubscribe/1","title":"PlausibleWeb.Endpoint.unsubscribe/1","type":"function"},{"doc":"Generates the endpoint base URL without any path information. It uses the configuration under :url to generate such.","ref":"PlausibleWeb.Endpoint.html#url/0","title":"PlausibleWeb.Endpoint.url/0","type":"function"},{"doc":"","ref":"PlausibleWeb.Endpoint.html#websocket_url/0","title":"PlausibleWeb.Endpoint.websocket_url/0","type":"function"},{"doc":"","ref":"PlausibleWeb.ErrorHelpers.html","title":"PlausibleWeb.ErrorHelpers","type":"module"},{"doc":"","ref":"PlausibleWeb.ErrorHelpers.html#error_tag/2","title":"PlausibleWeb.ErrorHelpers.error_tag/2","type":"function"},{"doc":"","ref":"PlausibleWeb.ErrorReportController.html","title":"PlausibleWeb.ErrorReportController","type":"module"},{"doc":"","ref":"PlausibleWeb.ErrorReportController.html#submit_error_report/2","title":"PlausibleWeb.ErrorReportController.submit_error_report/2","type":"function"},{"doc":"","ref":"PlausibleWeb.ErrorView.html","title":"PlausibleWeb.ErrorView","type":"module"},{"doc":"The resource name, as an atom, for this view","ref":"PlausibleWeb.ErrorView.html#__resource__/0","title":"PlausibleWeb.ErrorView.__resource__/0","type":"function"},{"doc":"","ref":"PlausibleWeb.ErrorView.html#generic_error.html/1","title":"PlausibleWeb.ErrorView.generic_error.html/1","type":"function"},{"doc":"Renders the given template locally.","ref":"PlausibleWeb.ErrorView.html#render/2","title":"PlausibleWeb.ErrorView.render/2","type":"function"},{"doc":"","ref":"PlausibleWeb.ErrorView.html#server_error.html/1","title":"PlausibleWeb.ErrorView.server_error.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.ErrorView.html#server_error_report_thanks.html/1","title":"PlausibleWeb.ErrorView.server_error_report_thanks.html/1","type":"function"},{"doc":"Callback invoked when no template is found. By default it raises but can be customized to render a particular template.","ref":"PlausibleWeb.ErrorView.html#template_not_found/2","title":"PlausibleWeb.ErrorView.template_not_found/2","type":"function"},{"doc":"A Plug that fetches favicon images from DuckDuckGo and returns them to the Plausible frontend. The proxying is there so we can reduce the number of third-party domains that the browser clients need to connect to. Our goal is to have 0 third-party domain connections on the website for privacy reasons. This module also maps between categorized sources and their respective URLs for favicons. What does that mean exactly? During ingestion we use PlausibleWeb.RefInspector.parse/1 to categorize our referrer sources like so: google.com -> Google google.co.uk -> Google google.com.au -> Google So when we show Google as a source in the dashboard, the request to this plug will come as: https://plausible/io/favicon/sources/Google Now, when we want to show a favicon for Google, we need to convert Google -> google.com or some other hostname owned by Google: https://icons.duckduckgo.com/ip3/google.com.ico The mapping from source category -> source hostname is stored in "priv/referer_favicon_domains.json" and managed by Mix.Tasks.GenerateReferrerFavicons.run/1","ref":"PlausibleWeb.Favicon.html","title":"PlausibleWeb.Favicon","type":"module"},{"doc":"Proxies HTTP request to DuckDuckGo favicon service. Swallows hop-by-hop HTTP headers that should not be forwarded as defined in RFC 2616 Placeholder Cases where we show a placeholder icon instead: In case of network error to DuckDuckGo In case of non-2xx status code from DuckDuckGo In case of broken image response body from DuckDuckGo I'm not sure why DDG sometimes returns a broken PNG image in their response but we filter that out. When the icon request fails, we show a placeholder favicon instead. The placeholder is an emoji from https://favicon.io/emoji-favicons/ DuckDuckGo favicon service has some issues with SVG favicons . For some reason, they return them with content-type=image/x-icon whereas SVG icons should be returned with content-type=image/svg+xml . This Plug detects when the response body starts with <svg and will override the Content-Type to correct it. Preventing XSS vulnerabilities SVGs may contain <script> tags, and as these SVGs come from external sources, we need to prevent untrusted code from running on the browser. This Plug sets a strict Content-Security-Policy header telling the browser not to run scripts. This Plug sets Content-Disposition=attachment to prevent the SVG from rendering when navigating to /favicon/sources/:domain directly. Browsers do not execute scripts from <img> tags, therefore it is safe to use <img src="https://plausible.io/favicon/sources/dummy.site"></img>","ref":"PlausibleWeb.Favicon.html#call/2","title":"PlausibleWeb.Favicon.call/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Favicon.html#init/1","title":"PlausibleWeb.Favicon.init/1","type":"function"},{"doc":"Redirects first-launch users to registration page.","ref":"PlausibleWeb.FirstLaunchPlug.html","title":"PlausibleWeb.FirstLaunchPlug","type":"module"},{"doc":"","ref":"PlausibleWeb.FormHelpers.html","title":"PlausibleWeb.FormHelpers","type":"module"},{"doc":"","ref":"PlausibleWeb.FormHelpers.html#styled_error/1","title":"PlausibleWeb.FormHelpers.styled_error/1","type":"function"},{"doc":"","ref":"PlausibleWeb.FormHelpers.html#styled_label/4","title":"PlausibleWeb.FormHelpers.styled_label/4","type":"function"},{"doc":"","ref":"PlausibleWeb.FormHelpers.html#styled_select/4","title":"PlausibleWeb.FormHelpers.styled_select/4","type":"function"},{"doc":"","ref":"PlausibleWeb.FormHelpers.html#styled_text_input/3","title":"PlausibleWeb.FormHelpers.styled_text_input/3","type":"function"},{"doc":"","ref":"PlausibleWeb.InvitationController.html","title":"PlausibleWeb.InvitationController","type":"module"},{"doc":"","ref":"PlausibleWeb.InvitationController.html#accept_invitation/2","title":"PlausibleWeb.InvitationController.accept_invitation/2","type":"function"},{"doc":"","ref":"PlausibleWeb.InvitationController.html#reject_invitation/2","title":"PlausibleWeb.InvitationController.reject_invitation/2","type":"function"},{"doc":"","ref":"PlausibleWeb.InvitationController.html#remove_invitation/2","title":"PlausibleWeb.InvitationController.remove_invitation/2","type":"function"},{"doc":"","ref":"PlausibleWeb.LastSeenPlug.html","title":"PlausibleWeb.LastSeenPlug","type":"module"},{"doc":"","ref":"PlausibleWeb.LastSeenPlug.html#call/2","title":"PlausibleWeb.LastSeenPlug.call/2","type":"function"},{"doc":"","ref":"PlausibleWeb.LastSeenPlug.html#init/1","title":"PlausibleWeb.LastSeenPlug.init/1","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html","title":"PlausibleWeb.LayoutView","type":"module"},{"doc":"The resource name, as an atom, for this view","ref":"PlausibleWeb.LayoutView.html#__resource__/0","title":"PlausibleWeb.LayoutView.__resource__/0","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#app.html/1","title":"PlausibleWeb.LayoutView.app.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#base_domain/0","title":"PlausibleWeb.LayoutView.base_domain/0","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#base_email.html/1","title":"PlausibleWeb.LayoutView.base_email.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#base_error.html/1","title":"PlausibleWeb.LayoutView.base_error.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#embedded.html/1","title":"PlausibleWeb.LayoutView.embedded.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#focus.html/1","title":"PlausibleWeb.LayoutView.focus.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#grace_period_end/1","title":"PlausibleWeb.LayoutView.grace_period_end/1","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#home_dest/1","title":"PlausibleWeb.LayoutView.home_dest/1","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#is_current_tab/2","title":"PlausibleWeb.LayoutView.is_current_tab/2","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#plausible_url/0","title":"PlausibleWeb.LayoutView.plausible_url/0","type":"function"},{"doc":"Renders the given template locally.","ref":"PlausibleWeb.LayoutView.html#render/2","title":"PlausibleWeb.LayoutView.render/2","type":"function"},{"doc":"http://blog.plataformatec.com.br/2018/05/nested-layouts-with-phoenix/","ref":"PlausibleWeb.LayoutView.html#render_layout/3","title":"PlausibleWeb.LayoutView.render_layout/3","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#settings_tabs/1","title":"PlausibleWeb.LayoutView.settings_tabs/1","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#site_settings.html/1","title":"PlausibleWeb.LayoutView.site_settings.html/1","type":"function"},{"doc":"Callback invoked when no template is found. By default it raises but can be customized to render a particular template.","ref":"PlausibleWeb.LayoutView.html#template_not_found/2","title":"PlausibleWeb.LayoutView.template_not_found/2","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#trial_notificaton/1","title":"PlausibleWeb.LayoutView.trial_notificaton/1","type":"function"},{"doc":"","ref":"PlausibleWeb.LayoutView.html#websocket_url/0","title":"PlausibleWeb.LayoutView.websocket_url/0","type":"function"},{"doc":"Flash component for LiveViews - works also when embedded within dead views","ref":"PlausibleWeb.Live.Flash.html","title":"PlausibleWeb.Live.Flash","type":"module"},{"doc":"","ref":"PlausibleWeb.Live.Flash.html#clear_flash_button/1","title":"PlausibleWeb.Live.Flash.clear_flash_button/1","type":"function"},{"doc":"Attributes on_close ( :any ) - Defaults to "lv:clear-flash" . Slots icon (required) title message (required)","ref":"PlausibleWeb.Live.Flash.html#flash/1","title":"PlausibleWeb.Live.Flash.flash/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Live.Flash.html#icon_error/1","title":"PlausibleWeb.Live.Flash.icon_error/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Live.Flash.html#icon_success/1","title":"PlausibleWeb.Live.Flash.icon_success/1","type":"function"},{"doc":"Callback implementation for Phoenix.LiveComponent.render/1 .","ref":"PlausibleWeb.Live.Flash.html#render/1","title":"PlausibleWeb.Live.Flash.render/1","type":"function"},{"doc":"LiveView allowing listing, creating and deleting funnels.","ref":"PlausibleWeb.Live.FunnelSettings.html","title":"PlausibleWeb.Live.FunnelSettings","type":"module"},{"doc":"Callback implementation for Phoenix.LiveView.handle_event/3 .","ref":"PlausibleWeb.Live.FunnelSettings.html#handle_event/3","title":"PlausibleWeb.Live.FunnelSettings.handle_event/3","type":"function"},{"doc":"Callback implementation for Phoenix.LiveView.handle_info/2 .","ref":"PlausibleWeb.Live.FunnelSettings.html#handle_info/2","title":"PlausibleWeb.Live.FunnelSettings.handle_info/2","type":"function"},{"doc":"Callback implementation for Phoenix.LiveView.mount/3 .","ref":"PlausibleWeb.Live.FunnelSettings.html#mount/3","title":"PlausibleWeb.Live.FunnelSettings.mount/3","type":"function"},{"doc":"Callback implementation for Phoenix.LiveView.render/1 .","ref":"PlausibleWeb.Live.FunnelSettings.html#render/1","title":"PlausibleWeb.Live.FunnelSettings.render/1","type":"function"},{"doc":"Phoenix LiveComponent for a combobox UI element with search and selection functionality. The component allows users to select an option from a list of options, which can be searched by typing in the input field. The component renders an input field with a dropdown anchor and a hidden input field for submitting the selected value. The number of options displayed in the dropdown is limited to 15 by default but can be customized. When a user types into the input field, the component searches the available options and provides suggestions based on the input.","ref":"PlausibleWeb.Live.FunnelSettings.ComboBox.html","title":"PlausibleWeb.Live.FunnelSettings.ComboBox","type":"module"},{"doc":"Attributes ref ( :string ) (required) options ( :list ) - Defaults to [] . suggestions ( :list ) - Defaults to [] . target ( :any )","ref":"PlausibleWeb.Live.FunnelSettings.ComboBox.html#dropdown/1","title":"PlausibleWeb.Live.FunnelSettings.ComboBox.dropdown/1","type":"function"},{"doc":"Attributes id ( :any ) (required)","ref":"PlausibleWeb.Live.FunnelSettings.ComboBox.html#dropdown_anchor/1","title":"PlausibleWeb.Live.FunnelSettings.ComboBox.dropdown_anchor/1","type":"function"},{"doc":"Callback implementation for Phoenix.LiveComponent.handle_event/3 .","ref":"PlausibleWeb.Live.FunnelSettings.ComboBox.html#handle_event/3","title":"PlausibleWeb.Live.FunnelSettings.ComboBox.handle_event/3","type":"function"},{"doc":"Attributes display_value ( :string ) (required) submit_value ( :integer ) (required) ref ( :string ) (required) target ( :any ) idx ( :integer ) (required)","ref":"PlausibleWeb.Live.FunnelSettings.ComboBox.html#option/1","title":"PlausibleWeb.Live.FunnelSettings.ComboBox.option/1","type":"function"},{"doc":"Attributes placeholder ( :string ) - Defaults to "Select option or search by typing" . id ( :any ) (required) options ( :list ) (required) submit_name ( :string ) (required) display_value ( :string ) - Defaults to "" . submit_value ( :string ) - Defaults to "" .","ref":"PlausibleWeb.Live.FunnelSettings.ComboBox.html#render/1","title":"PlausibleWeb.Live.FunnelSettings.ComboBox.render/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Live.FunnelSettings.ComboBox.html#select_option/4","title":"PlausibleWeb.Live.FunnelSettings.ComboBox.select_option/4","type":"function"},{"doc":"","ref":"PlausibleWeb.Live.FunnelSettings.ComboBox.html#suggest/2","title":"PlausibleWeb.Live.FunnelSettings.ComboBox.suggest/2","type":"function"},{"doc":"Callback implementation for Phoenix.LiveComponent.update/2 .","ref":"PlausibleWeb.Live.FunnelSettings.ComboBox.html#update/2","title":"PlausibleWeb.Live.FunnelSettings.ComboBox.update/2","type":"function"},{"doc":"Phoenix LiveComponent that renders a form used for setting up funnels. Makes use of dynamically placed PlausibleWeb.Live.FunnelSettings.ComboBox components to allow building searchable funnel definitions out of list of goals available.","ref":"PlausibleWeb.Live.FunnelSettings.Form.html","title":"PlausibleWeb.Live.FunnelSettings.Form","type":"module"},{"doc":"","ref":"PlausibleWeb.Live.FunnelSettings.Form.html#add_step_button/1","title":"PlausibleWeb.Live.FunnelSettings.Form.add_step_button/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Live.FunnelSettings.Form.html#cancel_button/1","title":"PlausibleWeb.Live.FunnelSettings.Form.cancel_button/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Live.FunnelSettings.Form.html#error/1","title":"PlausibleWeb.Live.FunnelSettings.Form.error/1","type":"function"},{"doc":"Attributes at ( :integer ) (required) result ( :map ) (required)","ref":"PlausibleWeb.Live.FunnelSettings.Form.html#evaluation/1","title":"PlausibleWeb.Live.FunnelSettings.Form.evaluation/1","type":"function"},{"doc":"Callback implementation for Phoenix.LiveView.handle_event/3 .","ref":"PlausibleWeb.Live.FunnelSettings.Form.html#handle_event/3","title":"PlausibleWeb.Live.FunnelSettings.Form.handle_event/3","type":"function"},{"doc":"Callback implementation for Phoenix.LiveView.handle_info/2 .","ref":"PlausibleWeb.Live.FunnelSettings.Form.html#handle_info/2","title":"PlausibleWeb.Live.FunnelSettings.Form.handle_info/2","type":"function"},{"doc":"Attributes field ( Phoenix.HTML.FormField )","ref":"PlausibleWeb.Live.FunnelSettings.Form.html#input/1","title":"PlausibleWeb.Live.FunnelSettings.Form.input/1","type":"function"},{"doc":"Callback implementation for Phoenix.LiveView.mount/3 .","ref":"PlausibleWeb.Live.FunnelSettings.Form.html#mount/3","title":"PlausibleWeb.Live.FunnelSettings.Form.mount/3","type":"function"},{"doc":"Attributes step_idx ( :integer ) (required)","ref":"PlausibleWeb.Live.FunnelSettings.Form.html#remove_step_button/1","title":"PlausibleWeb.Live.FunnelSettings.Form.remove_step_button/1","type":"function"},{"doc":"Callback implementation for Phoenix.LiveView.render/1 .","ref":"PlausibleWeb.Live.FunnelSettings.Form.html#render/1","title":"PlausibleWeb.Live.FunnelSettings.Form.render/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Live.FunnelSettings.Form.html#submit_button/1","title":"PlausibleWeb.Live.FunnelSettings.Form.submit_button/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Live.FunnelSettings.Form.html#submit_button_inactive/1","title":"PlausibleWeb.Live.FunnelSettings.Form.submit_button_inactive/1","type":"function"},{"doc":"Phoenix LiveComponent module that renders a list of funnels with their names and the number of steps they have. Each funnel is displayed with a delete button, which triggers a confirmation message before deleting the funnel from the UI. If there are no funnels configured for the site, a message is displayed indicating so.","ref":"PlausibleWeb.Live.FunnelSettings.List.html","title":"PlausibleWeb.Live.FunnelSettings.List","type":"module"},{"doc":"Callback implementation for Phoenix.LiveComponent.render/1 .","ref":"PlausibleWeb.Live.FunnelSettings.List.html#render/1","title":"PlausibleWeb.Live.FunnelSettings.List.render/1","type":"function"},{"doc":"MJML rendered for the weekly report e-mail","ref":"PlausibleWeb.MJML.WeeklyReport.html","title":"PlausibleWeb.MJML.WeeklyReport","type":"module"},{"doc":"Returns the raw MJML template. Useful for debugging rendering issues.","ref":"PlausibleWeb.MJML.WeeklyReport.html#debug_mjml_template/0","title":"PlausibleWeb.MJML.WeeklyReport.debug_mjml_template/0","type":"function"},{"doc":"Safely render the MJML template using Phoenix.HTML","ref":"PlausibleWeb.MJML.WeeklyReport.html#render/1","title":"PlausibleWeb.MJML.WeeklyReport.render/1","type":"function"},{"doc":"","ref":"PlausibleWeb.PageController.html","title":"PlausibleWeb.PageController","type":"module"},{"doc":"The root path is never accessible in Plausible.Cloud because it is handled by the upstream reverse proxy. This controller action is only ever triggered in self-hosted Plausible.","ref":"PlausibleWeb.PageController.html#index/2","title":"PlausibleWeb.PageController.index/2","type":"function"},{"doc":"","ref":"PlausibleWeb.PageView.html","title":"PlausibleWeb.PageView","type":"module"},{"doc":"The resource name, as an atom, for this view","ref":"PlausibleWeb.PageView.html#__resource__/0","title":"PlausibleWeb.PageView.__resource__/0","type":"function"},{"doc":"","ref":"PlausibleWeb.PageView.html#index.html/1","title":"PlausibleWeb.PageView.index.html/1","type":"function"},{"doc":"Renders the given template locally.","ref":"PlausibleWeb.PageView.html#render/2","title":"PlausibleWeb.PageView.render/2","type":"function"},{"doc":"Callback invoked when no template is found. By default it raises but can be customized to render a particular template.","ref":"PlausibleWeb.PageView.html#template_not_found/2","title":"PlausibleWeb.PageView.template_not_found/2","type":"function"},{"doc":"Rejects bot requests by any means available. We're adding x-robots-tag to the response header and annotate the conn with "noindex, nofollow" under private.robots key. The only exception is, if the request is trying to access our live demo at plausible.io/plausible.io - in which case we'll allow indexing, but deny following links and skip the bot detection, in kind robots we trust.","ref":"PlausibleWeb.Plugs.NoRobots.html","title":"PlausibleWeb.Plugs.NoRobots","type":"module"},{"doc":"A Plug.Session adapter that allows configuration at runtime. Sadly, the plug being wrapped has no MFA option for dynamic configuration. This is currently used so we can dynamically pass the :domain and have cookies planted across one root domain.","ref":"PlausibleWeb.Plugs.RuntimeSessionAdapter.html","title":"PlausibleWeb.Plugs.RuntimeSessionAdapter","type":"module"},{"doc":"","ref":"PlausibleWeb.RefInspector.html","title":"PlausibleWeb.RefInspector","type":"module"},{"doc":"","ref":"PlausibleWeb.RefInspector.html#parse/1","title":"PlausibleWeb.RefInspector.parse/1","type":"function"},{"doc":"","ref":"PlausibleWeb.RefInspector.html#right_uri?/1","title":"PlausibleWeb.RefInspector.right_uri?/1","type":"function"},{"doc":"","ref":"PlausibleWeb.RemoteIp.html","title":"PlausibleWeb.RemoteIp","type":"module"},{"doc":"","ref":"PlausibleWeb.RemoteIp.html#get/1","title":"PlausibleWeb.RemoteIp.get/1","type":"function"},{"doc":"","ref":"PlausibleWeb.RequireAccountPlug.html","title":"PlausibleWeb.RequireAccountPlug","type":"module"},{"doc":"","ref":"PlausibleWeb.RequireAccountPlug.html#call/2","title":"PlausibleWeb.RequireAccountPlug.call/2","type":"function"},{"doc":"","ref":"PlausibleWeb.RequireAccountPlug.html#init/1","title":"PlausibleWeb.RequireAccountPlug.init/1","type":"function"},{"doc":"","ref":"PlausibleWeb.RequireLoggedOutPlug.html","title":"PlausibleWeb.RequireLoggedOutPlug","type":"module"},{"doc":"","ref":"PlausibleWeb.RequireLoggedOutPlug.html#call/2","title":"PlausibleWeb.RequireLoggedOutPlug.call/2","type":"function"},{"doc":"","ref":"PlausibleWeb.RequireLoggedOutPlug.html#init/1","title":"PlausibleWeb.RequireLoggedOutPlug.init/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Router.html","title":"PlausibleWeb.Router","type":"module"},{"doc":"","ref":"PlausibleWeb.Router.html#api/2","title":"PlausibleWeb.Router.api/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Router.html#browser/2","title":"PlausibleWeb.Router.browser/2","type":"function"},{"doc":"Callback invoked by Plug on every request.","ref":"PlausibleWeb.Router.html#call/2","title":"PlausibleWeb.Router.call/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Router.html#csrf/2","title":"PlausibleWeb.Router.csrf/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Router.html#flags/2","title":"PlausibleWeb.Router.flags/2","type":"function"},{"doc":"Callback required by Plug that initializes the router for serving web requests.","ref":"PlausibleWeb.Router.html#init/1","title":"PlausibleWeb.Router.init/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Router.html#internal_stats_api/2","title":"PlausibleWeb.Router.internal_stats_api/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Router.html#kaffy_browser/2","title":"PlausibleWeb.Router.kaffy_browser/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Router.html#public_api/2","title":"PlausibleWeb.Router.public_api/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Router.html#shared_link/2","title":"PlausibleWeb.Router.shared_link/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SessionTimeoutPlug.html","title":"PlausibleWeb.SessionTimeoutPlug","type":"module"},{"doc":"","ref":"PlausibleWeb.SessionTimeoutPlug.html#call/2","title":"PlausibleWeb.SessionTimeoutPlug.call/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SessionTimeoutPlug.html#init/1","title":"PlausibleWeb.SessionTimeoutPlug.init/1","type":"function"},{"doc":"This controller deals with user management via the UI in Site Settings -> People. It's important to enforce permissions in this controller. Owner - Can manage users, can trigger a 'transfer ownership' request Admin - Can manage users Viewer - Can not access user management settings Anyone - Can accept invitations Everything else should be explicitly disallowed.","ref":"PlausibleWeb.Site.MembershipController.html","title":"PlausibleWeb.Site.MembershipController","type":"module"},{"doc":"","ref":"PlausibleWeb.Site.MembershipController.html#invite_member/2","title":"PlausibleWeb.Site.MembershipController.invite_member/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Site.MembershipController.html#invite_member_form/2","title":"PlausibleWeb.Site.MembershipController.invite_member_form/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Site.MembershipController.html#remove_member/2","title":"PlausibleWeb.Site.MembershipController.remove_member/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Site.MembershipController.html#transfer_ownership/2","title":"PlausibleWeb.Site.MembershipController.transfer_ownership/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Site.MembershipController.html#transfer_ownership_form/2","title":"PlausibleWeb.Site.MembershipController.transfer_ownership_form/2","type":"function"},{"doc":"Updates the role of a user. The user being updated could be the same or different from the user taking the action. When updating the role, it's important to enforce permissions: Owner - Can update anyone's role except for themselves. If they want to change their own role, they have to use the 'transfer ownership' feature. Admin - Can update anyone's role except for owners. Can downgrade their own access to 'viewer'. Can promote a viewer to admin.","ref":"PlausibleWeb.Site.MembershipController.html#update_role/2","title":"PlausibleWeb.Site.MembershipController.update_role/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Site.MembershipView.html","title":"PlausibleWeb.Site.MembershipView","type":"module"},{"doc":"The resource name, as an atom, for this view","ref":"PlausibleWeb.Site.MembershipView.html#__resource__/0","title":"PlausibleWeb.Site.MembershipView.__resource__/0","type":"function"},{"doc":"","ref":"PlausibleWeb.Site.MembershipView.html#invite_member_form.html/1","title":"PlausibleWeb.Site.MembershipView.invite_member_form.html/1","type":"function"},{"doc":"Renders the given template locally.","ref":"PlausibleWeb.Site.MembershipView.html#render/2","title":"PlausibleWeb.Site.MembershipView.render/2","type":"function"},{"doc":"Callback invoked when no template is found. By default it raises but can be customized to render a particular template.","ref":"PlausibleWeb.Site.MembershipView.html#template_not_found/2","title":"PlausibleWeb.Site.MembershipView.template_not_found/2","type":"function"},{"doc":"","ref":"PlausibleWeb.Site.MembershipView.html#transfer_ownership_form.html/1","title":"PlausibleWeb.Site.MembershipView.transfer_ownership_form.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html","title":"PlausibleWeb.SiteController","type":"module"},{"doc":"","ref":"PlausibleWeb.SiteController.html#add_monthly_report_recipient/2","title":"PlausibleWeb.SiteController.add_monthly_report_recipient/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#add_snippet/2","title":"PlausibleWeb.SiteController.add_snippet/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#add_snippet_after_domain_change/2","title":"PlausibleWeb.SiteController.add_snippet_after_domain_change/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#add_spike_notification_recipient/2","title":"PlausibleWeb.SiteController.add_spike_notification_recipient/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#add_weekly_report_recipient/2","title":"PlausibleWeb.SiteController.add_weekly_report_recipient/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#change_domain/2","title":"PlausibleWeb.SiteController.change_domain/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#change_domain_submit/2","title":"PlausibleWeb.SiteController.change_domain_submit/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#create_goal/2","title":"PlausibleWeb.SiteController.create_goal/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#create_shared_link/2","title":"PlausibleWeb.SiteController.create_shared_link/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#create_site/2","title":"PlausibleWeb.SiteController.create_site/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#delete_custom_domain/2","title":"PlausibleWeb.SiteController.delete_custom_domain/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#delete_goal/2","title":"PlausibleWeb.SiteController.delete_goal/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#delete_google_auth/2","title":"PlausibleWeb.SiteController.delete_google_auth/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#delete_shared_link/2","title":"PlausibleWeb.SiteController.delete_shared_link/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#delete_site/2","title":"PlausibleWeb.SiteController.delete_site/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#disable_monthly_report/2","title":"PlausibleWeb.SiteController.disable_monthly_report/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#disable_spike_notification/2","title":"PlausibleWeb.SiteController.disable_spike_notification/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#disable_weekly_report/2","title":"PlausibleWeb.SiteController.disable_weekly_report/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#edit_shared_link/2","title":"PlausibleWeb.SiteController.edit_shared_link/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#enable_monthly_report/2","title":"PlausibleWeb.SiteController.enable_monthly_report/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#enable_spike_notification/2","title":"PlausibleWeb.SiteController.enable_spike_notification/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#enable_weekly_report/2","title":"PlausibleWeb.SiteController.enable_weekly_report/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#forget_imported/2","title":"PlausibleWeb.SiteController.forget_imported/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#import_from_google/2","title":"PlausibleWeb.SiteController.import_from_google/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#import_from_google_confirm/2","title":"PlausibleWeb.SiteController.import_from_google_confirm/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#import_from_google_user_metric_notice/2","title":"PlausibleWeb.SiteController.import_from_google_user_metric_notice/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#import_from_google_view_id/2","title":"PlausibleWeb.SiteController.import_from_google_view_id/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#import_from_google_view_id_form/2","title":"PlausibleWeb.SiteController.import_from_google_view_id_form/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#index/2","title":"PlausibleWeb.SiteController.index/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#make_private/2","title":"PlausibleWeb.SiteController.make_private/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#make_public/2","title":"PlausibleWeb.SiteController.make_public/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#new/2","title":"PlausibleWeb.SiteController.new/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#new_goal/2","title":"PlausibleWeb.SiteController.new_goal/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#new_shared_link/2","title":"PlausibleWeb.SiteController.new_shared_link/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#remove_monthly_report_recipient/2","title":"PlausibleWeb.SiteController.remove_monthly_report_recipient/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#remove_spike_notification_recipient/2","title":"PlausibleWeb.SiteController.remove_spike_notification_recipient/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#remove_weekly_report_recipient/2","title":"PlausibleWeb.SiteController.remove_weekly_report_recipient/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#reset_stats/2","title":"PlausibleWeb.SiteController.reset_stats/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#settings/2","title":"PlausibleWeb.SiteController.settings/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#settings_custom_domain/2","title":"PlausibleWeb.SiteController.settings_custom_domain/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#settings_danger_zone/2","title":"PlausibleWeb.SiteController.settings_danger_zone/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#settings_email_reports/2","title":"PlausibleWeb.SiteController.settings_email_reports/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#settings_funnels/2","title":"PlausibleWeb.SiteController.settings_funnels/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#settings_general/2","title":"PlausibleWeb.SiteController.settings_general/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#settings_goals/2","title":"PlausibleWeb.SiteController.settings_goals/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#settings_people/2","title":"PlausibleWeb.SiteController.settings_people/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#settings_search_console/2","title":"PlausibleWeb.SiteController.settings_search_console/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#settings_visibility/2","title":"PlausibleWeb.SiteController.settings_visibility/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#update_feature_visibility/2","title":"PlausibleWeb.SiteController.update_feature_visibility/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#update_google_auth/2","title":"PlausibleWeb.SiteController.update_google_auth/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#update_settings/2","title":"PlausibleWeb.SiteController.update_settings/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#update_shared_link/2","title":"PlausibleWeb.SiteController.update_shared_link/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteController.html#update_spike_notification/2","title":"PlausibleWeb.SiteController.update_spike_notification/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html","title":"PlausibleWeb.SiteView","type":"module"},{"doc":"The resource name, as an atom, for this view","ref":"PlausibleWeb.SiteView.html#__resource__/0","title":"PlausibleWeb.SiteView.__resource__/0","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#base_domain/0","title":"PlausibleWeb.SiteView.base_domain/0","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#change_domain.html/1","title":"PlausibleWeb.SiteView.change_domain.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#edit_shared_link.html/1","title":"PlausibleWeb.SiteView.edit_shared_link.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#goal_name/1","title":"PlausibleWeb.SiteView.goal_name/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#google_logo/1","title":"PlausibleWeb.SiteView.google_logo/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#gravatar/2","title":"PlausibleWeb.SiteView.gravatar/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#import_from_google_confirm.html/1","title":"PlausibleWeb.SiteView.import_from_google_confirm.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#import_from_google_user_metric_form.html/1","title":"PlausibleWeb.SiteView.import_from_google_user_metric_form.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#import_from_google_view_id_form.html/1","title":"PlausibleWeb.SiteView.import_from_google_view_id_form.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#index.html/1","title":"PlausibleWeb.SiteView.index.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#new.html/1","title":"PlausibleWeb.SiteView.new.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#new_goal.html/1","title":"PlausibleWeb.SiteView.new_goal.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#new_shared_link.html/1","title":"PlausibleWeb.SiteView.new_shared_link.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#plausible_url/0","title":"PlausibleWeb.SiteView.plausible_url/0","type":"function"},{"doc":"Renders the given template locally.","ref":"PlausibleWeb.SiteView.html#render/2","title":"PlausibleWeb.SiteView.render/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#render_snippet/1","title":"PlausibleWeb.SiteView.render_snippet/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#settings_custom_domain.html/1","title":"PlausibleWeb.SiteView.settings_custom_domain.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#settings_danger_zone.html/1","title":"PlausibleWeb.SiteView.settings_danger_zone.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#settings_email_reports.html/1","title":"PlausibleWeb.SiteView.settings_email_reports.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#settings_funnels.html/1","title":"PlausibleWeb.SiteView.settings_funnels.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#settings_general.html/1","title":"PlausibleWeb.SiteView.settings_general.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#settings_goals.html/1","title":"PlausibleWeb.SiteView.settings_goals.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#settings_people.html/1","title":"PlausibleWeb.SiteView.settings_people.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#settings_search_console.html/1","title":"PlausibleWeb.SiteView.settings_search_console.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#settings_visibility.html/1","title":"PlausibleWeb.SiteView.settings_visibility.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#shared_link_dest/2","title":"PlausibleWeb.SiteView.shared_link_dest/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#snippet.html/1","title":"PlausibleWeb.SiteView.snippet.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#snippet_after_domain_change.html/1","title":"PlausibleWeb.SiteView.snippet_after_domain_change.html/1","type":"function"},{"doc":"Callback invoked when no template is found. By default it raises but can be customized to render a particular template.","ref":"PlausibleWeb.SiteView.html#template_not_found/2","title":"PlausibleWeb.SiteView.template_not_found/2","type":"function"},{"doc":"","ref":"PlausibleWeb.SiteView.html#with_indefinite_article/1","title":"PlausibleWeb.SiteView.with_indefinite_article/1","type":"function"},{"doc":"This controller is responsible for rendering stats dashboards. The stats dashboards are currently the only part of the app that uses client-side rendering. Since the dashboards are heavily interactive, they are built with React which is an appropriate choice for highly interactive browser UIs. sequenceDiagram Browser->>StatsController: GET /mydomain.com StatsController-->>Browser: StatsView.render(\"stats.html\") Note left of Browser: ReactDom.render(Dashboard) Browser -) Api.StatsController: GET /api/stats/mydomain.com/top-stats Api.StatsController --) Browser: {\"top_stats\": [...]} Note left of Browser: TopStats.render() Browser -) Api.StatsController: GET /api/stats/mydomain.com/main-graph Api.StatsController --) Browser: [{\"plot\": [...], \"labels\": [...]}, ...] Note left of Browser: VisitorGraph.render() Browser -) Api.StatsController: GET /api/stats/mydomain.com/sources Api.StatsController --) Browser: [{\"name\": \"Google\", \"visitors\": 292150}, ...] Note left of Browser: Sources.render() Note over Browser,StatsController: And so on, for all reports in the viewport This reasoning for this sequence is as follows: First paint is fast because it doesn't do any data aggregation yet - good UX The basic structure of the dashboard is rendered with spinners before reports are ready - good UX Rendering on the frontend allows for maximum interactivity. Re-rendering and re-fetching can be as granular as needed. Routing on the frontend allows the user to navigate the dashboard without reloading the page and losing context Rendering on the frontend allows caching results in the browser to reduce pressure on backends and storage 3.1 No client-side caching has been implemented yet. This is still theoretical. See https://github.com/plausible/analytics/discussions/1278 3.2 This is a big potential opportunity, because analytics data is mostly immutable. Clients can cache all historical data. Since frontend rendering & navigation is harder to build and maintain than regular server-rendered HTML, we don't use SPA-style rendering anywhere else .The only place currently where the benefits outweigh the costs is the dashboard.","ref":"PlausibleWeb.StatsController.html","title":"PlausibleWeb.StatsController","type":"module"},{"doc":"","ref":"PlausibleWeb.StatsController.html#authenticate_shared_link/2","title":"PlausibleWeb.StatsController.authenticate_shared_link/2","type":"function"},{"doc":"The export is limited to 300 entries for other reports and 100 entries for pages because bigger result sets start causing failures. Since we request data like time on page or bounce_rate for pages in a separate query using the IN filter, it causes the requests to balloon in payload size.","ref":"PlausibleWeb.StatsController.html#csv_export/2","title":"PlausibleWeb.StatsController.csv_export/2","type":"function"},{"doc":"Authorizes and renders a shared link: Shared link with no password protection: needs to just make sure the shared link entry is still in our database. This check makes sure shared link access can be revoked by the site admins. If the shared link exists, render it directly. Shared link with password protection: Same checks as without the password, but an extra step is taken to protect the page with a password. When the user passes the password challenge, a cookie is set with Plausible.Auth.Token.sign_shared_link(). The cookie allows the user to access the dashboard for 24 hours without entering the password again. ### Backwards compatibility The URL format for shared links was changed in this pull request in order to make the URLs easier to bookmark. The old format is supported along with the new in order to not break old links. See: https://plausible.io/docs/shared-links","ref":"PlausibleWeb.StatsController.html#shared_link/2","title":"PlausibleWeb.StatsController.shared_link/2","type":"function"},{"doc":"","ref":"PlausibleWeb.StatsController.html#stats/2","title":"PlausibleWeb.StatsController.stats/2","type":"function"},{"doc":"","ref":"PlausibleWeb.StatsView.html","title":"PlausibleWeb.StatsView","type":"module"},{"doc":"The resource name, as an atom, for this view","ref":"PlausibleWeb.StatsView.html#__resource__/0","title":"PlausibleWeb.StatsView.__resource__/0","type":"function"},{"doc":"","ref":"PlausibleWeb.StatsView.html#base_domain/0","title":"PlausibleWeb.StatsView.base_domain/0","type":"function"},{"doc":"","ref":"PlausibleWeb.StatsView.html#large_number_format/1","title":"PlausibleWeb.StatsView.large_number_format/1","type":"function"},{"doc":"","ref":"PlausibleWeb.StatsView.html#plausible_url/0","title":"PlausibleWeb.StatsView.plausible_url/0","type":"function"},{"doc":"Returns a readable stats URL. Native Phoenix router functions percent-encode all diacritics, resulting in ugly URLs, e.g. https://plausible.io/café.com transforms into https://plausible.io/caf%C3%A9.com . This function encodes only the slash ( / ) character from the site's domain. Examples iex> PlausibleWeb.StatsView.pretty_stats_url(%Plausible.Site{domain: "user.gittea.io/repo"}) " http://localhost:8000/user.gittea.io%2Frepo" iex> PlausibleWeb.StatsView.pretty_stats_url(%Plausible.Site{domain: "anakin.test"}) " http://localhost:8000/anakin.test" iex> PlausibleWeb.StatsView.pretty_stats_url(%Plausible.Site{domain: "café.test"}) " http://localhost:8000/café.test"","ref":"PlausibleWeb.StatsView.html#pretty_stats_url/1","title":"PlausibleWeb.StatsView.pretty_stats_url/1","type":"function"},{"doc":"Renders the given template locally.","ref":"PlausibleWeb.StatsView.html#render/2","title":"PlausibleWeb.StatsView.render/2","type":"function"},{"doc":"","ref":"PlausibleWeb.StatsView.html#shared_link_password.html/1","title":"PlausibleWeb.StatsView.shared_link_password.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.StatsView.html#site_locked.html/1","title":"PlausibleWeb.StatsView.site_locked.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.StatsView.html#stats.html/1","title":"PlausibleWeb.StatsView.stats.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.StatsView.html#stats_container_class/1","title":"PlausibleWeb.StatsView.stats_container_class/1","type":"function"},{"doc":"Callback invoked when no template is found. By default it raises but can be customized to render a particular template.","ref":"PlausibleWeb.StatsView.html#template_not_found/2","title":"PlausibleWeb.StatsView.template_not_found/2","type":"function"},{"doc":"","ref":"PlausibleWeb.StatsView.html#waiting_first_pageview.html/1","title":"PlausibleWeb.StatsView.waiting_first_pageview.html/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Tracker.html","title":"PlausibleWeb.Tracker","type":"module"},{"doc":"","ref":"PlausibleWeb.Tracker.html#call/2","title":"PlausibleWeb.Tracker.call/2","type":"function"},{"doc":"Returns a specification to start this module under a supervisor. See Supervisor .","ref":"PlausibleWeb.Tracker.html#child_spec/1","title":"PlausibleWeb.Tracker.child_spec/1","type":"function"},{"doc":"","ref":"PlausibleWeb.Tracker.html#init/1","title":"PlausibleWeb.Tracker.init/1","type":"function"},{"doc":"","ref":"PlausibleWeb.UnsubscribeController.html","title":"PlausibleWeb.UnsubscribeController","type":"module"},{"doc":"","ref":"PlausibleWeb.UnsubscribeController.html#monthly_report/2","title":"PlausibleWeb.UnsubscribeController.monthly_report/2","type":"function"},{"doc":"","ref":"PlausibleWeb.UnsubscribeController.html#weekly_report/2","title":"PlausibleWeb.UnsubscribeController.weekly_report/2","type":"function"},{"doc":"","ref":"PlausibleWeb.UnsubscribeView.html","title":"PlausibleWeb.UnsubscribeView","type":"module"},{"doc":"The resource name, as an atom, for this view","ref":"PlausibleWeb.UnsubscribeView.html#__resource__/0","title":"PlausibleWeb.UnsubscribeView.__resource__/0","type":"function"},{"doc":"Renders the given template locally.","ref":"PlausibleWeb.UnsubscribeView.html#render/2","title":"PlausibleWeb.UnsubscribeView.render/2","type":"function"},{"doc":"","ref":"PlausibleWeb.UnsubscribeView.html#success.html/1","title":"PlausibleWeb.UnsubscribeView.success.html/1","type":"function"},{"doc":"Callback invoked when no template is found. By default it raises but can be customized to render a particular template.","ref":"PlausibleWeb.UnsubscribeView.html#template_not_found/2","title":"PlausibleWeb.UnsubscribeView.template_not_found/2","type":"function"},{"doc":"Simple Metrics | Lightweight Script | Privacy Focused | Open Source | Docs | Contributing Plausible Analytics is a simple, lightweight (< 1 KB), open source and privacy-friendly alternative to Google Analytics. It doesn’t use cookies and is fully compliant with GDPR, CCPA and PECR. You can self-host or have us run Plausible for you in the cloud. Here's the live demo of our own website stats . Made and hosted in the EU 🇪🇺 We are dedicated to making web analytics more privacy-friendly. Our mission is to reduce corporate surveillance by providing an alternative web analytics tool which doesn’t come from the AdTech world. We are completely independent and solely funded by our subscribers.","ref":"readme.html","title":"Introduction","type":"extras"},{"doc":"Here's what makes Plausible a great Google Analytics alternative and why we're trusted by thousands of paying subscribers to deliver their website and business insights: Clutter Free : Plausible Analytics provides simple web analytics and it cuts through the noise. No layers of menus, no need for custom reports. Get all the important insights on one single page. No training necessary. GDPR/CCPA/PECR compliant : Measure traffic, not individuals. No personal data or IP addresses are ever stored in our database. We don't use cookies or any other persistent identifiers. Read more about our data policy Lightweight : Plausible Analytics works by loading a script on your website, like Google Analytics. Our script is 45x smaller , making your website quicker to load. Email or Slack reports : Keep an eye on your traffic with weekly and/or monthly email or Slack reports. You can also get traffic spike notifications. Open website stats : You have the option to be transparent and open your web analytics to everyone. Your website stats are private by default but you can choose to make them public so anyone with your custom link can view them. Define key goals and track conversions : Set custom events or page URLs as your goals and see how they convert over time to understand and identify the trends that matter. Includes easy ways to track outbound link clicks and 404 error pages. Search keywords : Integrate your dashboard with Google Search Console to get the most accurate reporting on your search keywords. SPA support : Plausible is built with modern web frameworks in mind and it works automatically with any pushState based router on the frontend. We also support frameworks that use the URL hash for routing. See our documentation . Interested to learn more? Read more on our website , learn more about the team and the goals of the project on our about page or explore the documentation .","ref":"readme.html#why-plausible","title":"Introduction - Why Plausible?","type":"extras"},{"doc":"Plausible Analytics is an independently owned and actively developed project. To keep the project development going, to stay in business, to continue putting effort into building a better product and to cover our costs, we need to charge a fee. Google Analytics is free because Google has built their company and their wealth by collecting and analyzing huge amounts of personal information from web users and using these personal and behavioral insights to sell advertisements. Plausible has no part in that business model. No personal data is being collected and analyzed either. With Plausible, you 100% own and control all of your website data. This data is not being shared with or sold to any third-parties. We choose the subscription business model rather than the business model of surveillance capitalism. See reasons why we believe you should stop using Google Analytics on your website .","ref":"readme.html#why-is-plausible-analytics-cloud-not-free-like-google-analytics","title":"Introduction - Why is Plausible Analytics Cloud not free like Google Analytics?","type":"extras"},{"doc":"The easiest way to get started with Plausible is with our official managed service in the cloud . It takes 2 minutes to start counting your stats with a worldwide CDN, high availability, backups, security and maintenance all done for you by us. In order to be compliant with the GDPR and the Schrems II ruling, all visitor data for our managed service in the cloud is exclusively processed on servers and cloud infrastructure owned and operated by European providers. Your website data never leaves the EU. Our managed hosting can save a substantial amount of developer time and resources. For most sites this ends up being the best value option and the revenue goes to funding the maintenance and further development of Plausible. So you’ll be supporting open source software and getting a great service! Can Plausible Analytics be self-hosted? Plausible is fully open source web analytics and we have a free as in beer Plausible Analytics Self-Hosted solution. It’s exactly the same product as our cloud solution with a less frequent release schedule (think of it as a long term support release). Bug fixes and new features are released to the cloud version several times per week. Features are battle-tested in the cloud which allows us to fix any bugs before the general self-hosted release. Every six months or so we combine all the changes into a new self-hosted release. The main difference between the two is that the self-hosted version you have to install, host and manage yourself on your own infrastructure while the cloud version we manage everything for your ease and convenience. Here's the overview of all the differences: Plausible Cloud Self-Hosting Hosting Easy and convenient. It takes 2 minutes to start counting your stats with a worldwide CDN, high availability, backups, security and maintenance all done for you by us. We manage everything so you don’t have to worry about anything and can focus on your stats. You do it all yourself. You need to get a server and you need to manage your infrastructure. You are responsible for installation, maintenance, upgrades, server capacity, uptime, backup, security, stability, consistency, loading time and so on. Storage All visitor data is exclusively processed on EU-owned cloud infrastructure. We keep your site data on a secure, encrypted and green energy powered server in Germany. This ensures that your site data is protected by the strict European Union data privacy laws and ensures compliance with GDPR. Your website data never leaves the EU. You have full control and can host your instance on any server in any country that you wish. Host it on a server in your basement or host it with any cloud provider wherever you want, even those that are not GDPR compliant. Releases Continuously developed and improved with new features and updates multiple times per week. It's a long term release published approximately twice per year so latest features won't be immediately available. You can see all the currently unreleased features in the changelog . Raw data You see all your site stats and metrics on our modern-looking, simple to use and fast loading dashboard. You can only see the stats aggregated in the dashboard. You can download the stats using the CSV export , stats API or tools such as the Data Studio Connector . Do you want access to the raw data? Self-hosting gives you that option. You can take the data directly from the ClickHouse database. Premium Support Real support delivered by real human beings who build and maintain Plausible. Premium support is not included. Self-hosting is community supported only. Costs There's a cost associated with providing an analytics service so we charge a subscription fee. We choose the subscription business model rather than the business model of surveillance capitalism. Your money funds further development of Plausible. You need to pay for your server, CDN, backups and whatever other cost there is associated with running the infrastructure. You never have to pay any fees to us. Your money goes to 3rd party companies with no connection to us. Interested in self-hosting Plausible on your server? Take a look at our self-hosting installation instructions . Plausible Self-Hosted is a community supported project and there are no guarantees that you will get support from the creators of Plausible to troubleshoot your self-hosting issues. There is a community supported forum where you can ask for help. Our only source of funding is our premium, managed service for running Plausible in the cloud. If you're looking for an alternative way to support the project, we've put together some sponsorship packages. If you choose to self-host Plausible you can become a sponsor which is a great way to give back to the community and to contribute to the long-term sustainability of the project.","ref":"readme.html#getting-started-with-plausible","title":"Introduction - Getting started with Plausible","type":"extras"},{"doc":"Plausible Analytics is a standard Elixir/Phoenix application backed by a PostgreSQL database for general data and a Clickhouse database for stats. On the frontend we use TailwindCSS for styling and React to make the dashboard interactive.","ref":"readme.html#technology","title":"Introduction - Technology","type":"extras"},{"doc":"For anyone wishing to contribute to Plausible, we recommend taking a look at our contributor guide .","ref":"readme.html#contributors","title":"Introduction - Contributors","type":"extras"},{"doc":"We welcome feedback from our community. We have a public roadmap driven by the features suggested by the community members. Take a look at our feedback board directly here on GitHub. Please let us know if you have any requests and vote on open issues so we can better prioritize. To stay up to date with all the latest news and product updates, make sure to follow us on Twitter , LinkedIn or Mastodon .","ref":"readme.html#feedback-roadmap","title":"Introduction - Feedback & Roadmap","type":"extras"},{"doc":"Plausible is open-source under the GNU Affero General Public License Version 3 (AGPLv3) or any later version. You can find it here . The only exception is our JavaScript tracker which gets included on your website. To avoid issues with AGPL virality, we've released the tracker under the MIT license. You can find it here .","ref":"readme.html#license","title":"Introduction - License","type":"extras"},{"doc":"We welcome everyone to contribute to Plausible. This document is to help you on setting up your environment, finding a task, and opening pull requests.","ref":"contributing.html","title":"Contributing","type":"extras"},{"doc":"The easiest way to get up and running is to install and use Docker for running both Postgres and Clickhouse. Make sure Docker, Elixir, Erlang and Node.js are all installed on your development machine. The .tool-versions file is available to use with asdf or similar tools. Start the environment Run both make postgres and make clickhouse . You can set up everything with make install , alternatively run each command separately: Run mix deps.get . This will download the required Elixir dependencies. Run mix ecto.create . This will create the required databases in both Postgres and Clickhouse. Run mix ecto.migrate to build the database schema. Run mix run priv/repo/seeds.exs to seed the database. Check the Seeds section for more. Run npm ci --prefix assets to install the required client-side dependencies. Run npm ci --prefix tracker to install the required tracker dependencies. Run npm run deploy --prefix tracker to generate tracker files in priv/tracker/js Run mix download_country_database to fetch geolocation database Run make server or mix phx.server to start the Phoenix server. The system is now available on localhost:8000 . Seeds You can optionally seed your database to automatically create an account and a site with stats: Run mix run priv/repo/seeds.exs to seed the database. Start the server with make server and navigate to http://localhost:8000/login . Log in with the following e-mail and password combination: user@plausible.test and plausible . You should now have a dummy.site site with generated stats. Alternatively, you can manually create a new account: Navigate to http://localhost:8000/register and fill in the form. Fill in the rest of the forms and for the domain use dummy.site Skip the JS snippet and click start collecting data. Run mix send_pageview from the terminal to generate a fake pageview event for the dummy site. You should now be all set! Stopping Docker containers Stop and remove the Postgres container with make postgres-stop . Stop and remove the Clickhouse container with make clickhouse-stop . Volumes are preserved. You'll find that the Postgres and Clickhouse state are retained when you bring them up again the next time: no need to re-register and so on. Note: Since we are deleting the containers, be careful when deleting volumes with docker volume prune . You might accidentally delete the database and would have to go through re-registration process. Pre-commit hooks pre-commit requires Python to be available locally and covers Elixir, JavaScript, and CSS. Set up with pip install --user pre-commit followed by pre-commit install . Conversely, if the prompts are far too bothersome, remove with pre-commit uninstall .","ref":"contributing.html#development-setup","title":"Contributing - Development setup","type":"extras"},{"doc":"Bugs can be found in our issue tracker . Issues are usually up for grabs. New features need to be discussed with the core team and the community first. If you're tackling a feature, please make sure it has been already discussed in the Discussions tab . We kindly ask contributors to use the discussion comment section to propose a solution before opening a pull request. Pull requests without an associated issue or discussion may still be merged, but we will focus on changes that have already been talked through.","ref":"contributing.html#finding-a-task","title":"Contributing - Finding a task","type":"extras"},{"doc":"This document explains the account locking feature from a technical perspective. Account locking happens when users have outgrown their accounts, and despite e-mail and dashboard alerts, don't upgrade after a grace period.","ref":"account-locking.html","title":"Account locking","type":"extras"},{"doc":"The Plausible.Workers.CheckUsage daily background job alerts users they have reached their subscription limits. This runs for outgrown users one day after their last billing date. When users reach the number of sites limit, or use >110% of their pageview limit for 2 consecutive billing cycles, the background job sends them an e-mail alert. The e-mail suggests a suitable subscription plan based on usage. For enterprise users, only an internal e-mail is sent to enterprise@plausible.io . The user is given 7 days to upgrade their account after the alert, and this is called grace period. The background starts this grace period by adding a users.grace_period JSON to the user record: // SELECT grace_period FROM users LIMIT 1 { "id": "1aa855bd-022d-4dfc-b572-6853442c3f19", "is_over": true, "end_date": "2022-03-09", "allowance_required": 100, "manual_lock": false } During this period, the following alert pops up on the dashboard for both standard and enterprise users: If the user upgrades to a suitable plan, the grace period is removed (check Plausible.Billing.subscription_updated/1 ), otherwise Account locking ) follows. For enterprise users, the grace period has a manual lock flag set to true, meaning enterprise accounts can only be locked/unlocked through the internal CRM.","ref":"account-locking.html#usage-alert-and-grace-period","title":"Account locking - Usage alert and grace period","type":"extras"},{"doc":"The grace period is checked daily by the Plausible.Workers.LockSites background job. For users that expired their grace period, sites.locked is is set to true , restricting access to dashboards. This does not stop event ingestion, so users can have their stats up to date when they finally upgrade.","ref":"account-locking.html#account-locking","title":"Account locking - Account locking","type":"extras"}] |