Plausible

v0.0.1

Plausible Analytics

Simple Metrics | Lightweight Script | Privacy Focused | Open Source | Docs | Contributing

Plausible Analytics is an easy to use, 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.

Why Plausible?

Here's what makes Plausible a great Google Analytics alternative and why we're trusted by 11,000+ 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. You can also send events directly to our events API.

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.

Invite team members and share 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. You can invite team members and assign user roles too.

Define key goals and track conversions: Create custom events with custom dimensions to track conversions and attribution to understand and identify the trends that matter. Includes easy ways to track outbound link clicks, file downloads 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.

Smooth transition from Google Analytics: There's a realtime dashboard, entry pages report and integration with Search Console. You can track your paid campaigns and conversions. You can invite team members. You can even import your historical Google Analytics stats. Learn how to get the most out of your Plausible experience and join thousands who have already migrated from Google Analytics.

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.

Why is Plausible Analytics Cloud not free like Google Analytics?

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.

Getting started with Plausible

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 open source web analytics and we have a free as in beer self-hosted solution. Here are the differences between Plausible Analytics managed hosting in the cloud and the self-hosting:

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.

Features
Continuously developed and improved with new features and updates multiple times per week.
It's a long term release published twice per year. Selected premium features are not available as we aim to ensure a protective barrier around our cloud offering.

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.

Technology

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.

Contributors

For anyone wishing to contribute to Plausible, we recommend taking a look at our contributor guide.

Feedback & Roadmap

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. 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 X (formerly Twitter), LinkedIn or Mastodon.

License & Trademarks

Plausible is open source under the GNU Affero General Public License Version 3 (AGPLv3) or any later version. You can find it here.

To avoid issues with AGPL virality, we've released the JavaScript tracker which gets included on your website under the MIT license. You can find it here.

Copyright (c) 2018-present Plausible Insights OÜ. Plausible Analytics name and logo are trademarks of Plausible Insights OÜ. Please see our trademark guidelines for info on acceptable usage.

Contributing

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.

Development setup

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.

Finding a task

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.

Account locking

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.

Usage alert and grace period

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.

Account locking

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.

ObanErrorReporter

Summary

Functions

handle_event(list, measure, meta, _)

Functions

Link to this function

handle_event(list, measure, meta, _)

View Source

Plausible

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.

Plausible.AsyncInsertRepo

Clickhouse access with async inserts enabled

Summary

Functions

aggregate(queryable, aggregate, opts \\ [])

Callback implementation for Ecto.Repo.aggregate/3.

aggregate(queryable, aggregate, field, opts)

Callback implementation for Ecto.Repo.aggregate/4.

all(queryable, opts \\ [])

Callback implementation for Ecto.Repo.all/2.

checked_out?()

Callback implementation for Ecto.Repo.checked_out?/0.

checkout(fun, opts \\ [])

Callback implementation for Ecto.Repo.checkout/2.

child_spec(opts)

config()

Callback implementation for Ecto.Repo.config/0.

default_options(operation)

Callback implementation for Ecto.Repo.default_options/1.

delete(struct, opts \\ [])

Callback implementation for Ecto.Repo.delete/2.

delete!(struct, opts \\ [])

Callback implementation for Ecto.Repo.delete!/2.

delete_all(queryable, opts \\ [])

Callback implementation for Ecto.Repo.delete_all/2.

disconnect_all(interval, opts \\ [])

A convenience function for SQL-based repositories that forces all connections in the pool to disconnect within the given interval.

exists?(queryable, opts \\ [])

Callback implementation for Ecto.Repo.exists?/2.

get(queryable, id, opts \\ [])

Callback implementation for Ecto.Repo.get/3.

get!(queryable, id, opts \\ [])

Callback implementation for Ecto.Repo.get!/3.

get_by(queryable, clauses, opts \\ [])

Callback implementation for Ecto.Repo.get_by/3.

get_by!(queryable, clauses, opts \\ [])

Callback implementation for Ecto.Repo.get_by!/3.

get_dynamic_repo()

Callback implementation for Ecto.Repo.get_dynamic_repo/0.

insert(struct, opts \\ [])

Callback implementation for Ecto.Repo.insert/2.

insert!(struct, opts \\ [])

Callback implementation for Ecto.Repo.insert!/2.

insert_all(schema_or_source, entries, opts \\ [])

Callback implementation for Ecto.Repo.insert_all/3.

insert_or_update(changeset, opts \\ [])

Callback implementation for Ecto.Repo.insert_or_update/2.

insert_or_update!(changeset, opts \\ [])

Callback implementation for Ecto.Repo.insert_or_update!/2.

insert_stream(source_or_schema, rows, opts \\ [])

Similar to insert_all/2 but with the following differences

load(schema_or_types, data)

Callback implementation for Ecto.Repo.load/2.

one(queryable, opts \\ [])

Callback implementation for Ecto.Repo.one/2.

one!(queryable, opts \\ [])

Callback implementation for Ecto.Repo.one!/2.

preload(struct_or_structs_or_nil, preloads, opts \\ [])

Callback implementation for Ecto.Repo.preload/3.

prepare_query(operation, query, opts)

Callback implementation for Ecto.Repo.prepare_query/3.

put_dynamic_repo(dynamic)

Callback implementation for Ecto.Repo.put_dynamic_repo/1.

query(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given query.

query!(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given query.

reload(queryable, opts \\ [])

Callback implementation for Ecto.Repo.reload/2.

reload!(queryable, opts \\ [])

Callback implementation for Ecto.Repo.reload!/2.

start_link(opts \\ [])

Callback implementation for Ecto.Repo.start_link/1.

stop(timeout \\ 5000)

Callback implementation for Ecto.Repo.stop/1.

stream(queryable, opts \\ [])

Callback implementation for Ecto.Repo.stream/2.

to_sql(operation, queryable)

A convenience function for SQL-based repositories that translates the given query to SQL.

update(struct, opts \\ [])

Callback implementation for Ecto.Repo.update/2.

update!(struct, opts \\ [])

Callback implementation for Ecto.Repo.update!/2.

update_all(queryable, updates, opts \\ [])

Callback implementation for Ecto.Repo.update_all/3.

Functions

Link to this function

aggregate(queryable, aggregate, opts \\ [])

View Source

Callback implementation for Ecto.Repo.aggregate/3.

Link to this function

aggregate(queryable, aggregate, field, opts)

View Source

Callback implementation for Ecto.Repo.aggregate/4.

Link to this function

all(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.all/2.

Link to this function

checked_out?()

View Source

Callback implementation for Ecto.Repo.checked_out?/0.

Link to this function

checkout(fun, opts \\ [])

View Source

Callback implementation for Ecto.Repo.checkout/2.

Link to this function

child_spec(opts)

View Source

Link to this function

config()

View Source

Callback implementation for Ecto.Repo.config/0.

Link to this function

default_options(operation)

View Source

Callback implementation for Ecto.Repo.default_options/1.

Link to this function

delete(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete/2.

Link to this function

delete!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete!/2.

Link to this function

delete_all(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete_all/2.

Link to this function

disconnect_all(interval, opts \\ [])

View Source

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.

Link to this function

exists?(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.exists?/2.

Link to this function

get(queryable, id, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get/3.

Link to this function

get!(queryable, id, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get!/3.

Link to this function

get_by(queryable, clauses, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get_by/3.

Link to this function

get_by!(queryable, clauses, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get_by!/3.

Link to this function

get_dynamic_repo()

View Source

Callback implementation for Ecto.Repo.get_dynamic_repo/0.

Link to this function

insert(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert/2.

Link to this function

insert!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert!/2.

Link to this function

insert_all(schema_or_source, entries, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_all/3.

Link to this function

insert_or_update(changeset, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_or_update/2.

Link to this function

insert_or_update!(changeset, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_or_update!/2.

Link to this function

insert_stream(source_or_schema, rows, opts \\ [])

View Source

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])

Link to this function

load(schema_or_types, data)

View Source

Callback implementation for Ecto.Repo.load/2.

Link to this function

one(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.one/2.

Link to this function

one!(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.one!/2.

Link to this function

preload(struct_or_structs_or_nil, preloads, opts \\ [])

View Source

Callback implementation for Ecto.Repo.preload/3.

Link to this function

prepare_query(operation, query, opts)

View Source

Callback implementation for Ecto.Repo.prepare_query/3.

Link to this function

put_dynamic_repo(dynamic)

View Source

Callback implementation for Ecto.Repo.put_dynamic_repo/1.

Link to this function

query(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given query.

See Ecto.Adapters.SQL.query/4 for more information.

Link to this function

query!(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given query.

See Ecto.Adapters.SQL.query!/4 for more information.

Link to this function

reload(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.reload/2.

Link to this function

reload!(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.reload!/2.

Link to this function

start_link(opts \\ [])

View Source

Callback implementation for Ecto.Repo.start_link/1.

Link to this function

stop(timeout \\ 5000)

View Source

Callback implementation for Ecto.Repo.stop/1.

Link to this function

stream(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.stream/2.

Link to this function

to_sql(operation, queryable)

View Source

A convenience function for SQL-based repositories that translates the given query to SQL.

See Ecto.Adapters.SQL.to_sql/3 for more information.

Link to this function

update(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update/2.

Link to this function

update!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update!/2.

Link to this function

update_all(queryable, updates, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update_all/3.

Plausible.Auth

Summary

Functions

create_api_key(user, name, key)

create_user(name, email, pwd)

delete_api_key(user, id)

delete_user(user)

enterprise_configured?(user)

find_api_key(raw_key)

find_user_by(opts)

has_active_sites?(user, roles \\ [:owner, :admin, :viewer])

is_super_admin?(user_id)

user_owns_sites?(user)

Functions

Link to this function

create_api_key(user, name, key)

View Source

@spec create_api_key(Plausible.Auth.User.t(), String.t(), String.t()) ::
  {:ok, Plausible.Auth.ApiKey.t()} | {:error, Ecto.Changeset.t()}

Link to this function

create_user(name, email, pwd)

View Source

Link to this function

delete_api_key(user, id)

View Source

@spec delete_api_key(Plausible.Auth.User.t(), integer()) :: :ok | {:error, :not_found}

Link to this function

delete_user(user)

View Source

Link to this function

enterprise_configured?(user)

View Source

Link to this function

find_api_key(raw_key)

View Source

@spec find_api_key(String.t()) ::
  {:ok, Plausible.Auth.ApiKey.t()} | {:error, :invalid_api_key}

Link to this function

find_user_by(opts)

View Source

Link to this function

has_active_sites?(user, roles \\ [:owner, :admin, :viewer])

View Source

Link to this function

is_super_admin?(user_id)

View Source

Link to this function

user_owns_sites?(user)

View Source

Plausible.Auth.ApiKey

Summary

Types

t()

Functions

changeset(schema, attrs \\ %{})

do_hash(key)

process_key(changeset)

update(schema, attrs \\ %{})

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Auth.ApiKey{
  __meta__: term(),
  hourly_request_limit: term(),
  id: term(),
  inserted_at: term(),
  key: term(),
  key_hash: term(),
  key_prefix: term(),
  name: term(),
  scopes: term(),
  updated_at: term(),
  user: term(),
  user_id: term()
}

Functions

Link to this function

changeset(schema, attrs \\ %{})

View Source

Link to this function

do_hash(key)

View Source

Link to this function

process_key(changeset)

View Source

Link to this function

update(schema, attrs \\ %{})

View Source

Plausible.Auth.ApiKeyAdmin

Summary

Functions

create_changeset(schema, attrs)

custom_index_query(conn, schema, query)

form_fields(_)

index(_)

search_fields(schema)

update_changeset(schema, attrs)

Functions

Link to this function

create_changeset(schema, attrs)

View Source

Link to this function

custom_index_query(conn, schema, query)

View Source

Link to this function

form_fields(_)

View Source

Link to this function

index(_)

View Source

Link to this function

search_fields(schema)

View Source

Link to this function

update_changeset(schema, attrs)

View Source

Plausible.Auth.EmailActivationCode

Schema for email activation codes.

Summary

Types

t()

Functions

generate_code()

new(user, now)

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Auth.EmailActivationCode{
  __meta__: term(),
  code: term(),
  id: term(),
  issued_at: term(),
  user: term(),
  user_id: term()
}

Functions

Link to this function

generate_code()

View Source

@spec generate_code() :: String.t()

Link to this function

new(user, now)

View Source

@spec new(Plausible.Auth.User.t(), NaiveDateTime.t()) :: Ecto.Changeset.t()

Plausible.Auth.EmailVerification

API for verifying emails.

Summary

Functions

any?(user)

expired?(verification)

issue_code(user, now \\ NaiveDateTime.utc_now())

verify_code(user, code)

Functions

Link to this function

any?(user)

View Source

@spec any?(Plausible.Auth.User.t()) :: boolean()

Link to this function

expired?(verification)

View Source

@spec expired?(Plausible.Auth.EmailActivationCode.t()) :: boolean()

Link to this function

issue_code(user, now \\ NaiveDateTime.utc_now())

View Source

@spec issue_code(Plausible.Auth.User.t(), NaiveDateTime.t()) ::
  {:ok, Plausible.Auth.EmailActivationCode.t()}
  | {:error, :hard_bounce | :unknown_error}

Link to this function

verify_code(user, code)

View Source

@spec verify_code(Plausible.Auth.User.t(), String.t() | non_neg_integer()) ::
  :ok | {:error, :incorrect | :expired}

Plausible.Auth.GracePeriod

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.

Summary

Types

t()

Functions

active?(user)

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.

end_changeset(user)

Ends an existing grace period by setting users.grace_period.is_over to true. This means the grace period has expired.

expired?(user)

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.

remove_changeset(user)

Removes the grace period from the User completely.

start_changeset(user, allowance_required)

Starts a account locking grace period of 7 days by changing the User struct.

start_manual_lock_changeset(user, allowance_required)

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.

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Auth.GracePeriod{
  allowance_required: non_neg_integer(),
  end_date: Date.t() | nil,
  id: term(),
  is_over: boolean(),
  manual_lock: boolean()
}

Functions

Link to this function

active?(user)

View Source

@spec active?(Plausible.Auth.User.t()) :: boolean()

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.

Link to this function

end_changeset(user)

View Source

@spec end_changeset(Plausible.Auth.User.t()) :: Ecto.Changeset.t()

Ends an existing grace period by setting users.grace_period.is_over to true. This means the grace period has expired.

Link to this function

expired?(user)

View Source

@spec expired?(Plausible.Auth.User.t()) :: boolean()

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.

Link to this function

remove_changeset(user)

View Source

@spec remove_changeset(Plausible.Auth.User.t()) :: Ecto.Changeset.t()

Removes the grace period from the User completely.

Link to this function

start_changeset(user, allowance_required)

View Source

@spec start_changeset(Plausible.Auth.User.t(), non_neg_integer()) ::
  Ecto.Changeset.t()

Starts a account locking grace period of 7 days by changing the User struct.

Link to this function

start_manual_lock_changeset(user, allowance_required)

View Source

@spec start_manual_lock_changeset(Plausible.Auth.User.t(), non_neg_integer()) ::
  Ecto.Changeset.t()

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.

Plausible.Auth.Invitation

Summary

Types

t()

Functions

new(attrs \\ %{})

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Auth.Invitation{
  __meta__: term(),
  email: term(),
  id: term(),
  inserted_at: term(),
  invitation_id: term(),
  inviter: term(),
  inviter_id: term(),
  role: term(),
  site: term(),
  site_id: term(),
  updated_at: term()
}

Functions

Link to this function

new(attrs \\ %{})

View Source

Plausible.Auth.Password

Summary

Functions

dummy_calculation()

hash(password)

match?(password, hash)

Functions

Link to this function

dummy_calculation()

View Source

Link to this function

hash(password)

View Source

Link to this function

match?(password, hash)

View Source

Plausible.Auth.Token

Summary

Functions

sign_password_reset(email)

sign_shared_link(slug)

verify_password_reset(token)

verify_shared_link(token)

Functions

Link to this function

sign_password_reset(email)

View Source

Link to this function

sign_shared_link(slug)

View Source

Link to this function

verify_password_reset(token)

View Source

Link to this function

verify_shared_link(token)

View Source

Plausible.Auth.User

Summary

Types

t()

Functions

cancel_email_changeset(user)

changeset(user, attrs \\ %{})

email_changeset(user, attrs \\ %{})

end_trial(user)

hash_password(changeset)

new(attrs \\ %{})

password_strength(changeset)

profile_img_url(user)

remove_trial_expiry(user)

set_password(user, password)

settings_changeset(user, attrs \\ %{})

start_trial(user)

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Auth.User{
  __meta__: term(),
  api_keys: term(),
  email: term(),
  email_verified: term(),
  enterprise_plan: term(),
  google_auth: term(),
  grace_period: term(),
  id: term(),
  inserted_at: term(),
  last_seen: term(),
  name: term(),
  password: term(),
  password_confirmation: term(),
  password_hash: term(),
  previous_email: term(),
  site_memberships: term(),
  sites: term(),
  subscription: term(),
  theme: term(),
  trial_expiry_date: term(),
  updated_at: term()
}

Functions

Link to this function

cancel_email_changeset(user)

View Source

Link to this function

changeset(user, attrs \\ %{})

View Source

Link to this function

email_changeset(user, attrs \\ %{})

View Source

Link to this function

end_trial(user)

View Source

Link to this function

hash_password(changeset)

View Source

Link to this function

new(attrs \\ %{})

View Source

Link to this function

password_strength(changeset)

View Source

Link to this function

profile_img_url(user)

View Source

Link to this function

remove_trial_expiry(user)

View Source

Link to this function

set_password(user, password)

View Source

Link to this function

settings_changeset(user, attrs \\ %{})

View Source

Link to this function

start_trial(user)

View Source

Plausible.Auth.UserAdmin

Summary

Functions

custom_index_query(conn, schema, query)

delete(conn, map)

form_fields(_)

index(_)

resource_actions(_)

Functions

Link to this function

custom_index_query(conn, schema, query)

View Source

Link to this function

delete(conn, map)

View Source

Link to this function

form_fields(_)

View Source

Link to this function

index(_)

View Source

Link to this function

resource_actions(_)

View Source

Plausible.Billing

Summary

Functions

active_subscription_for(user_id)

change_plan(user, new_plan_id)

change_plan_preview(subscription, new_plan_id)

check_needs_to_upgrade(user)

has_active_subscription?(user_id)

last_two_billing_cycles(user, today \\ Timex.today())

last_two_billing_months_usage(user, today \\ Timex.today())

on_trial?(user)

paddle_api()

subscription_cancelled(params)

subscription_created(params)

subscription_payment_succeeded(params)

subscription_updated(params)

trial_days_left(user)

usage_breakdown(user)

Functions

Link to this function

active_subscription_for(user_id)

View Source

@spec active_subscription_for(integer()) :: Plausible.Billing.Subscription.t() | nil

Link to this function

change_plan(user, new_plan_id)

View Source

Link to this function

change_plan_preview(subscription, new_plan_id)

View Source

Link to this function

check_needs_to_upgrade(user)

View Source

@spec check_needs_to_upgrade(Plausible.Auth.User.t()) ::
  {:needs_to_upgrade, :no_trial | :no_active_subscription | :grace_period_ended}
  | :no_upgrade_needed

Link to this function

has_active_subscription?(user_id)

View Source

@spec has_active_subscription?(integer()) :: boolean()

Link to this function

last_two_billing_cycles(user, today \\ Timex.today())

View Source

Link to this function

last_two_billing_months_usage(user, today \\ Timex.today())

View Source

@spec last_two_billing_months_usage(Plausible.Auth.User.t(), Date.t()) ::
  {non_neg_integer(), non_neg_integer()}

Link to this function

on_trial?(user)

View Source

Link to this function

paddle_api()

View Source

Link to this function

subscription_cancelled(params)

View Source

Link to this function

subscription_created(params)

View Source

Link to this function

subscription_payment_succeeded(params)

View Source

Link to this function

subscription_updated(params)

View Source

Link to this function

trial_days_left(user)

View Source

Link to this function

usage_breakdown(user)

View Source

Plausible.Billing.EnterprisePlan

Summary

Functions

changeset(model, attrs \\ %{})

Functions

Link to this function

changeset(model, attrs \\ %{})

View Source

Plausible.Billing.EnterprisePlanAdmin

Summary

Functions

custom_index_query(conn, schema, query)

form_fields(_)

index(_)

search_fields(schema)

Functions

Link to this function

custom_index_query(conn, schema, query)

View Source

Link to this function

form_fields(_)

View Source

Link to this function

index(_)

View Source

Link to this function

search_fields(schema)

View Source

Plausible.Billing.Feature behaviour

This module provides an interface for managing features, e.g. Revenue Goals, Funnels and Custom Properties.

Feature modules have functions for toggling the feature on/off and checking whether the feature is available for a site/user.

When defining new features, the following options are expected by the __using__ macro:

:name - an atom representing the feature name in the plan JSON file (see also Plausible.Billing.Plan).

:display_name - human-readable display name of the feature

:toggle_field - the field in the %Plausible.Site{} schema that toggles the feature. If nil or not set, toggle/2 silently returns :ok

:free - if set to true, makes the check_availability/1 function always return :ok (no matter the user's subscription status)

Functions defined by __using__ can be overridden if needed.

Summary

Callbacks

check_availability(t)

Checks whether the site owner or the user plan includes the given feature.

display_name()

Returns the human-readable display name of the feature.

enabled?(t)

Checks whether a feature is enabled or not. Returns false when the feature is disabled or the user does not have access to it.

name()

Returns the atom representing the feature name in the plan JSON file.

toggle(t, t)

Toggles the feature on and off for a site. Returns {:error, :upgrade_required} when toggling a feature the site owner does not have access to.

toggle_field()

Returns the %Plausible.Site{} field that toggles the feature on and off.

Functions

list()

Lists all available feature modules.

Callbacks

Link to this callback

check_availability(t)

View Source

@callback check_availability(Plausible.Auth.User.t()) ::
  :ok | {:error, :upgrade_required} | {:error, :not_implemented}

Checks whether the site owner or the user plan includes the given feature.

Link to this callback

display_name()

View Source

@callback display_name() :: String.t()

Returns the human-readable display name of the feature.

Link to this callback

enabled?(t)

View Source

@callback enabled?(Plausible.Site.t()) :: boolean()

Checks whether a feature is enabled or not. Returns false when the feature is disabled or the user does not have access to it.

Link to this callback

name()

View Source

@callback name() :: atom()

Returns the atom representing the feature name in the plan JSON file.

Link to this callback

toggle(t, t)

View Source

@callback toggle(Plausible.Site.t(), Keyword.t()) :: :ok | {:error, :upgrade_required}

Toggles the feature on and off for a site. Returns {:error, :upgrade_required} when toggling a feature the site owner does not have access to.

Link to this callback

toggle_field()

View Source

@callback toggle_field() :: atom()

Returns the %Plausible.Site{} field that toggles the feature on and off.

Functions

Link to this function

list()

View Source

Lists all available feature modules.

Plausible.Billing.PaddleApi

Summary

Functions

checkout_domain()

fetch_prices(product_ids)

get_invoices(subscription)

get_subscription(paddle_subscription_id)

update_subscription(paddle_subscription_id, params)

update_subscription_preview(paddle_subscription_id, new_plan_id)

vendors_domain()

Functions

Link to this function

checkout_domain()

View Source

Link to this function

fetch_prices(product_ids)

View Source

Link to this function

get_invoices(subscription)

View Source

@spec get_invoices(Plausible.Billing.Subscription.t()) ::
  {:ok, list()} | {:error, :request_failed} | {:error, :no_invoices}

Link to this function

get_subscription(paddle_subscription_id)

View Source

Link to this function

update_subscription(paddle_subscription_id, params)

View Source

Link to this function

update_subscription_preview(paddle_subscription_id, new_plan_id)

View Source

Link to this function

vendors_domain()

View Source

Plausible.Billing.Plans

Summary

Functions

available_plans_with_prices(user)

business_plans_for(user)

business_tier?(subscription)

get_price_for(enterprise_plan)

get_regular_plan(subscription, opts \\ [])

get_subscription_plan(subscription)

growth_plans_for(user)

Returns a list of growth plans available for the user to choose.

latest_enterprise_plan_with_price(user)

subscription_interval(subscription)

suggest(user, usage_during_cycle)

Returns the most appropriate plan for a user based on their usage during a given cycle.

with_prices(plans)

This function takes a list of plans as an argument, gathers all product IDs in a single list, and makes an API call to Paddle. After a successful response, fills in the monthly_cost and yearly_cost fields for each given plan and returns the new list of plans with completed information.

yearly_product_ids()

List yearly plans product IDs.

Functions

Link to this function

available_plans_with_prices(user)

View Source

Link to this function

business_plans_for(user)

View Source

Link to this function

business_tier?(subscription)

View Source

Link to this function

get_price_for(enterprise_plan)

View Source

Link to this function

get_regular_plan(subscription, opts \\ [])

View Source

Link to this function

get_subscription_plan(subscription)

View Source

Link to this function

growth_plans_for(user)

View Source

@spec growth_plans_for(Plausible.Auth.User.t()) :: [Plausible.Billing.Plan.t()]

Returns a list of growth plans available for the user to choose.

As new versions of plans are introduced, users who were on old plans can still choose from old plans.

Link to this function

latest_enterprise_plan_with_price(user)

View Source

Link to this function

subscription_interval(subscription)

View Source

Link to this function

suggest(user, usage_during_cycle)

View Source

@spec suggest(Plausible.Auth.User.t(), non_neg_integer()) ::
  Plausible.Billing.Plan.t()

Returns the most appropriate plan for a user based on their usage during a given cycle.

If the usage during the cycle exceeds the enterprise-level threshold, or if the user already belongs to an enterprise plan, it suggests the :enterprise plan.

Otherwise, it recommends the plan where the cycle usage falls just under the plan's limit from the available options for the user.

Link to this function

with_prices(plans)

View Source

This function takes a list of plans as an argument, gathers all product IDs in a single list, and makes an API call to Paddle. After a successful response, fills in the monthly_cost and yearly_cost fields for each given plan and returns the new list of plans with completed information.

Link to this function

yearly_product_ids()

View Source

@spec yearly_product_ids() :: [String.t()]

List yearly plans product IDs.

Plausible.Billing.Quota

This module provides functions to work with plans usage and limits.

Summary

Functions

allowed_features_for(user)

Returns a list of features the user can use. Trial users have the ability to use all features during their trial.

features_usage(user)

Returns a list of features the given user is using. At the current stage, the only features that we need to know the usage for are Props, Funnels, and RevenueGoals

monthly_pageview_limit(subscription)

Returns the limit of pageviews for a subscription.

monthly_pageview_usage(user)

Returns the amount of pageviews and custom events sent by the sites the user owns in last 30 days.

site_limit(user)

Returns the limit of sites a user can have.

site_usage(user)

Returns the number of sites the given user owns.

team_member_limit(user)

Returns the limit of team members a user can have in their sites.

team_member_usage(user)

Returns the total count of team members and pending invitations associated with the user's sites.

within_limit?(usage, limit)

Returns whether the limit has been exceeded or not.

Functions

Link to this function

allowed_features_for(user)

View Source

Returns a list of features the user can use. Trial users have the ability to use all features during their trial.

Link to this function

features_usage(user)

View Source

@spec features_usage(Plausible.Auth.User.t()) :: [atom()]

Returns a list of features the given user is using. At the current stage, the only features that we need to know the usage for are Props, Funnels, and RevenueGoals

Link to this function

monthly_pageview_limit(subscription)

View Source

@spec monthly_pageview_limit(Plausible.Billing.Subscription.t()) ::
  non_neg_integer() | :unlimited

Returns the limit of pageviews for a subscription.

Link to this function

monthly_pageview_usage(user)

View Source

@spec monthly_pageview_usage(Plausible.Auth.User.t()) :: non_neg_integer()

Returns the amount of pageviews and custom events sent by the sites the user owns in last 30 days.

Link to this function

site_limit(user)

View Source

@spec site_limit(Plausible.Auth.User.t()) :: non_neg_integer() | :unlimited

Returns the limit of sites a user can have.

For enterprise customers, returns :unlimited. The site limit is checked in a background job so as to avoid service disruption.

Link to this function

site_usage(user)

View Source

@spec site_usage(Plausible.Auth.User.t()) :: non_neg_integer()

Returns the number of sites the given user owns.

Link to this function

team_member_limit(user)

View Source

@spec team_member_limit(Plausible.Auth.User.t()) :: non_neg_integer()

Returns the limit of team members a user can have in their sites.

Link to this function

team_member_usage(user)

View Source

@spec team_member_usage(Plausible.Auth.User.t()) :: integer()

Returns the total count of team members and pending invitations associated with the user's sites.

Link to this function

within_limit?(usage, limit)

View Source

@spec within_limit?(non_neg_integer(), non_neg_integer() | :unlimited) :: boolean()

Returns whether the limit has been exceeded or not.

Plausible.Billing.SiteLocker

Summary

Types

lock_reason()

update_opt()

Functions

send_grace_period_end_email(user)

set_lock_status_for(user, status)

update_sites_for(user, opts \\ [])

Types

Link to this type

lock_reason()

View Source

@type lock_reason() ::
  :grace_period_ended_now
  | :grace_period_ended_already
  | :no_trial
  | :no_active_subscription

Link to this type

update_opt()

View Source

@type update_opt() :: {:send_email?, boolean()}

Functions

Link to this function

send_grace_period_end_email(user)

View Source

@spec send_grace_period_end_email(Plausible.Auth.User.t()) ::
  Plausible.Mailer.result()

Link to this function

set_lock_status_for(user, status)

View Source

@spec set_lock_status_for(Plausible.Auth.User.t(), boolean()) ::
  {:ok, non_neg_integer()}

Link to this function

update_sites_for(user, opts \\ [])

View Source

@spec update_sites_for(Plausible.Auth.User.t(), [update_opt()]) ::
  {:locked, lock_reason()} | :unlocked

Plausible.Billing.Subscription.Status

The subscription statuses are stored in Paddle. They can only be changed through Paddle webhooks, which always send the current subscription status via the payload.

active - All good with the payments. Can access stats.

past_due - The payment has failed, but we're trying to charge the customer again. Access to stats is still granted. There will be three retries - after 3, 5, and 7 days have passed from the first failure. After a failure on the final retry, the subscription status will change to paused. As soon as the customer updates their billing details, Paddle will charge them again, and after a successful payment, the subscription will become active again.

paused - we've tried to charge the customer but all the retries have failed. Stats access restricted. As soon as the customer updates their billing details, Paddle will charge them again, and after a successful payment, the subscription will become active again.

deleted - The customer has triggered the cancel subscription action. Access to stats should be granted for the time the customer has already paid for. If they want to upgrade again, new billing details have to be provided.

Paddle documentation links for reference:

Subscription statuses - https://developer.paddle.com/classic/reference/zg9joji1mzu0mdi2-subscription-status-reference

Payment failures - https://developer.paddle.com/classic/guides/zg9joji1mzu0mduy-payment-failures

Summary

Types

status()

Functions

active()

deleted()

past_due()

paused()

valid_statuses()

Types

Link to this type

status()

View Source

@type status() :: :deleted | :paused | :past_due | :active

Functions

Link to this macro

active()

View Source (macro)

Link to this macro

deleted()

View Source (macro)

Link to this macro

past_due()

View Source (macro)

Link to this macro

paused()

View Source (macro)

Link to this function

valid_statuses()

View Source

Plausible.ChangesetHelpers

Helper function for working with Ecto changesets

Summary

Functions

traverse_errors(changeset)

Functions

Link to this function

traverse_errors(changeset)

View Source

Plausible.Cldr

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.

Summary

Functions

available_locale_name?(locale_name)

See Cldr.available_locale_name?/1.

default_locale()

Returns the default locale.

default_territory()

Returns the default territory when a locale does not specify one and none can be inferred.

ellipsis(string, options \\ [])

Add locale-specific ellipsis to a string.

get_locale()

Return the current locale to be used for Cldr functions that take an optional locale parameter for which a locale is not supplied.

known_calendars()

See Cldr.known_calendars/0.

known_currencies()

See Cldr.known_currencies/0.

known_gettext_locale_name(locale_name)

Returns either the Gettext locale_name in Cldr format or false based upon whether the locale name is configured in Gettext.

known_gettext_locale_name?(locale_name)

Returns a boolean indicating if the specified locale name is configured and available in Gettext.

known_gettext_locale_names()

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.

known_locale_name(locale_name)

Returns either the locale_name or false based upon whether the locale name is configured in Cldr.

known_locale_name?(locale_name)

Returns a boolean indicating if the specified locale name is configured and available in Cldr.

known_locale_names()

Returns a list of the known locale names.

known_number_system_types()

Returns a list of atoms representing the number systems types known to Cldr.

known_number_systems()

See Cldr.known_number_systems/0.

known_rbnf_locale_name(locale_name)

Returns either the RBNF locale_name or false based upon whether the locale name is configured in Cldr and has RBNF rules defined.

known_rbnf_locale_name?(locale_name)

Returns a boolean indicating if the specified locale name is configured and available in Cldr and supports rules based number formats (RBNF).

known_rbnf_locale_names()

Returns a list of locale names which have rules-based number formats (RBNF).

known_territories()

See Cldr.known_territories/0.

normalize_lenient_parse(string, scope, locale \\ get_locale())

Normalizes a string by applying transliteration of common symbols in numbers, currencies and dates

put_locale(locale_name)

Set the current locale to be used for Cldr functions that take an optional locale parameter for which a locale is not supplied.

quote(string, options \\ [])

Add locale-specific quotation marks around a string.

unknown_locale_names()

Returns a list of the locales names that are configured, but not known in CLDR.

validate_calendar(calendar)

See Cldr.validate_calendar/1.

validate_currency(currency)

See Cldr.validate_currency/1.

validate_locale(locale)

Normalise and validate a locale name.

validate_number_system(number_system)

See Cldr.validate_number_system/1.

validate_number_system_type(number_system_type)

Normalise and validate a number system type.

validate_territory(territory)

See Cldr.validate_territory/1.

with_locale(locale, fun)

Execute a function with a locale ensuring that the current locale is restored after the function.

Functions

Link to this function

available_locale_name?(locale_name)

View Source

See Cldr.available_locale_name?/1.

Link to this function

default_locale()

View Source

@spec default_locale() :: Cldr.LanguageTag.t() | no_return()

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: []
}

Link to this function

default_territory()

View Source

@spec default_territory() :: Cldr.Locale.territory_code()

Returns the default territory when a locale does not specify one and none can be inferred.

Example

iex> Plausible.Cldr.default_territory()
:"001"

Link to this function

ellipsis(string, options \\ [])

View Source

@spec ellipsis(String.t() | [String.t()], Keyword.t()) :: String.t()

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"

Link to this function

get_locale()

View Source

@spec get_locale() :: Cldr.LanguageTag.t()

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: []
 }

Link to this function

known_calendars()

View Source

See Cldr.known_calendars/0.

Link to this function

known_currencies()

View Source

See Cldr.known_currencies/0.

Link to this function

known_gettext_locale_name(locale_name)

View Source

@spec known_gettext_locale_name(String.t()) :: String.t() | false

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

Link to this function

known_gettext_locale_name?(locale_name)

View Source

@spec known_gettext_locale_name?(String.t()) :: boolean()

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

Link to this function

known_gettext_locale_names()

View Source

@spec known_gettext_locale_names() :: [String.t()]

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.

Link to this function

known_locale_name(locale_name)

View Source

@spec known_locale_name(Cldr.Locale.locale_name()) :: String.t() | false

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

Link to this function

known_locale_name?(locale_name)

View Source

@spec known_locale_name?(Cldr.Locale.locale_name()) :: boolean()

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

Link to this function

known_locale_names()

View Source

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.

Link to this function

known_number_system_types()

View Source

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]

Link to this function

known_number_systems()

View Source

See Cldr.known_number_systems/0.

Link to this function

known_rbnf_locale_name(locale_name)

View Source

@spec known_rbnf_locale_name(Cldr.Locale.locale_name()) :: String.t() | false

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

Link to this function

known_rbnf_locale_name?(locale_name)

View Source

@spec known_rbnf_locale_name?(Cldr.Locale.locale_name()) :: boolean()

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

Link to this function

known_rbnf_locale_names()

View Source

@spec known_rbnf_locale_names() :: [Cldr.Locale.locale_name()]

Returns a list of locale names which have rules-based number formats (RBNF).

Link to this function

known_territories()

View Source

See Cldr.known_territories/0.

Link to this function

normalize_lenient_parse(string, scope, locale \\ get_locale())

View Source

Normalizes a string by applying transliteration of common symbols in numbers, currencies and dates

Link to this function

put_locale(locale_name)

View Source

@spec put_locale(Cldr.Locale.locale_reference()) ::
  {:ok, Cldr.LanguageTag.t()} | {:error, {module(), String.t()}}

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"}}

Link to this function

quote(string, options \\ [])

View Source

@spec quote(String.t(), Keyword.t()) :: String.t()

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」"

Link to this function

unknown_locale_names()

View Source

@spec unknown_locale_names() :: [Cldr.Locale.locale_name()]

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.

Link to this function

validate_calendar(calendar)

View Source

See Cldr.validate_calendar/1.

Link to this function

validate_currency(currency)

View Source

See Cldr.validate_currency/1.

Link to this function

validate_locale(locale)

View Source

@spec validate_locale(Cldr.Locale.locale_name() | Cldr.LanguageTag.t() | String.t()) ::
  {:ok, Cldr.LanguageTag.t()} | {:error, {module(), String.t()}}

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"}}

Link to this function

validate_number_system(number_system)

View Source

See Cldr.validate_number_system/1.

Link to this function

validate_number_system_type(number_system_type)

View Source

@spec validate_number_system_type(String.t() | atom()) ::
  {:ok, atom()} | {:error, {module(), String.t()}}

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"}
}

Link to this function

validate_territory(territory)

View Source

See Cldr.validate_territory/1.

Link to this function

with_locale(locale, fun)

View Source (since 2.32.0)

@spec with_locale(Cldr.LanguageTag.t(), (... -> any())) :: any()

@spec with_locale(Cldr.Locale.locale_name(), (... -> any())) :: any()

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.

Plausible.Cldr.AcceptLanguage

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*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )

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."

Summary

Functions

best_match(accept_language)

Parse an Accept-Language string and return the best match for a configured Cldr locale.

parse(tokens_or_string)

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.

parse!(accept_language)

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.

Functions

Link to this function

best_match(accept_language)

View Source

@spec best_match(String.t()) ::
  {:ok, Cldr.LanguageTag.t()}
  | {:error, {Cldr.AcceptLanguageError | Cldr.NoMatchingLocale, String.t()}}

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"}}

Link to this function

parse(tokens_or_string)

View Source (since 2.30.0)

@spec parse([{float(), String.t()}, ...] | String.t()) ::
  {:ok,
   [
     {float(), Cldr.LanguageTag.t()}
     | {:error, {Cldr.InvalidLanguageTag, String.t()}},
     ...
   ]}
  | {:error, {Cldr.AcceptLanguageError, String.t()}}

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"}}
 ]}

Link to this function

parse!(accept_language)

View Source

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"}}
]

Plausible.Cldr.Currency

Summary

Functions

currencies_for_locale(locale, only \\ :all, except \\ nil)

Returns a map of the metadata for all currencies for a given locale.

currencies_for_locale!(locale, only \\ :all, except \\ nil)

Returns a map of the metadata for all currencies for a given locale and raises on error.

currency_for_code(currency_or_currency_code, options \\ [locale: Plausible.Cldr.default_locale()])

Returns the currency metadata for the requested currency code.

currency_for_code!(currency_or_currency_code, options \\ [locale: Plausible.Cldr.default_locale()])

Returns the currency metadata for the requested currency code.

currency_from_locale(locale)

Returns the effective currency for a given locale

currency_history_for_locale(language_tag)

Returns a list of historic and the current currency for a given locale.

currency_strings(locale, only \\ :all, except \\ nil)

Returns a map that matches a currency string to a currency code.

currency_strings!(locale_name, only \\ :all, except \\ nil)

Returns a map that matches a currency string to a currency code or raises an exception.

current_currency_from_locale(locale)

Returns the current currency for a given locale.

current_territory_currencies()

Returns a mapping from a territory code to its current currency code.

known_currencies()

See Plausible.Cldr.Currency.known_currency_codes/0.

known_currency?(code)

See Plausible.Cldr.Currency.known_currency_code?/1.

known_currency_code(currency_code)

Returns a 2-tuple indicating if the supplied currency code is known.

known_currency_code?(currency_code)

Returns a boolean indicating if the supplied currency code is known.

known_currency_codes()

Returns a list of all known currency codes.

new(currency, options \\ [])

Returns a Currency struct created from the arguments.

pluralize(number, currency, options \\ [])

Returns the appropriate currency display name for the currency, based on the plural rules in effect for the locale.

strings_for_currency(currency, locale)

Returns the strings associated with a currency in a given locale.

Functions

Link to this function

currencies_for_locale(locale, only \\ :all, except \\ nil)

View Source

@spec currencies_for_locale(
  Cldr.Locale.locale_name() | Cldr.LanguageTag.t(),
  only :: Cldr.Currency.filter(),
  except :: Cldr.Currency.filter()
) :: {:ok, map()} | {:error, {module(), String.t()}}

@spec currencies_for_locale(
  Cldr.Locale.locale_name() | Cldr.LanguageTag.t(),
  only :: Cldr.Currency.filter(),
  except :: Cldr.Currency.filter()
) :: map() | no_return()

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
 },
 ...
}}

Link to this function

currencies_for_locale!(locale, only \\ :all, except \\ nil)

View Source

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
},
...

}

Link to this function

currency_for_code(currency_or_currency_code, options \\ [locale: Plausible.Cldr.default_locale()])

View Source

@spec currency_for_code(Cldr.Currency.code() | Cldr.Currency.t(), Keyword.t()) ::
  {:ok, Cldr.Currency.t()} | {:error, {module(), String.t()}}

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
}}

Link to this function

currency_for_code!(currency_or_currency_code, options \\ [locale: Plausible.Cldr.default_locale()])

View Source (since 2.14.0)

@spec currency_for_code!(Cldr.Currency.code() | Cldr.Currency.t(), Keyword.t()) ::
  Cldr.Currency.t() | no_return()

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
}

Link to this function

currency_from_locale(locale)

View Source

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

Link to this function

currency_history_for_locale(language_tag)

View Source

@spec currency_history_for_locale(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
  map() | {:error, {module(), String.t()}}

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]}
  }
}

Link to this function

currency_strings(locale, only \\ :all, except \\ nil)

View Source

@spec currency_strings(
  Cldr.LanguageTag.t() | Cldr.Locale.locale_name(),
  only :: Cldr.Currency.filter(),
  except :: Cldr.Currency.filter()
) :: {:ok, map()} | {:error, {module(), String.t()}}

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,
   ...
  }}

Link to this function

currency_strings!(locale_name, only \\ :all, except \\ nil)

View Source

@spec currency_strings!(
  Cldr.LanguageTag.t() | Cldr.Locale.locale_name(),
  only :: Cldr.Currency.filter(),
  except :: Cldr.Currency.filter()
) :: map() | no_return()

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,
  ...
 }

Link to this function

current_currency_from_locale(locale)

View Source

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

Link to this function

current_territory_currencies()

View Source (since 2.15.0)

@spec current_territory_currencies() :: %{
  required(Cldr.Locale.territory_code()) => Cldr.Currency.code()
}

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()

Link to this function

known_currencies()

View Source

See Plausible.Cldr.Currency.known_currency_codes/0.

Link to this function

known_currency?(code)

View Source

See Plausible.Cldr.Currency.known_currency_code?/1.

Link to this function

known_currency_code(currency_code)

View Source

@spec known_currency_code(Cldr.Currency.code()) ::
  {:ok, Cldr.Currency.code()} | {:error, {module(), String.t()}}

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"}}

Link to this function

known_currency_code?(currency_code)

View Source

@spec known_currency_code?(Cldr.Currency.code()) :: boolean()

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

Link to this function

known_currency_codes()

View Source

@spec known_currency_codes() :: [atom()]

Returns a list of all known currency codes.

Example

iex> Plausible.Cldr.Currency.known_currency_codes

Link to this function

new(currency, options \\ [])

View Source

@spec new(Cldr.Currency.code(), map() | Keyword.t()) ::
  {:ok, Cldr.Currency.t()} | {:error, {module(), String.t()}}

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."}}

Link to this function

pluralize(number, currency, options \\ [])

View Source

@spec pluralize(pos_integer(), atom(), Keyword.t()) ::
  {:ok, String.t()} | {:error, {module(), String.t()}}

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"}

Link to this function

strings_for_currency(currency, locale)

View Source

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"]

Plausible.Cldr.Locale

Backend module that provides functions to define new locales and display human-readable locale names for presentation purposes.

Summary

Functions

fallback_locale_names(locale)

Returns the list of fallback locale names, starting with the provided locale name.

fallback_locales(locale)

Returns the list of fallback locales, starting with the provided locale name.

locale_for_territory(territory)

Returns the "best fit" locale for a given territory.

locale_from_host(host, options \\ [])

Returns a "best fit" locale for a host name.

new(locale_name)

new!(locale_name)

script_direction_from_locale(locale)

Returns the script direction for a locale.

territory_from_host(host)

Returns the last segment of a host that might be a territory.

territory_from_locale(locale)

Returns the territory from a language tag or locale name.

timezone_from_locale(locale)

Returns the time zone from a language tag or locale name.

Functions

Link to this function

fallback_locale_names(locale)

View Source (since 2.26.0)

@spec fallback_locale_names(Cldr.LanguageTag.t() | Cldr.Locale.locale_reference()) ::
  {:ok, [Cldr.Locale.locale_name(), ...]} | {:error, {module(), String.t()}}

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..

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

iex> Plausible.Cldr.Locale.fallback_locale_names(:"fr-CA")
{:ok, [:"fr-CA", :fr, :und]}

# 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, :und]}

Link to this function

fallback_locales(locale)

View Source (since 2.26.0)

@spec fallback_locales(Cldr.LanguageTag.t() | Cldr.Locale.locale_reference()) ::
  {:ok, [Cldr.LanguageTag.t(), ...]} | {:error, {module(), String.t()}}

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.

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

Plausible.Cldr.Locale.fallback_locales(:"fr-CA")
=> {:ok,
     [#Cldr.LanguageTag<fr-CA [validated]>, #Cldr.LanguageTag<fr [validated]>,
      #Cldr.LanguageTag<und [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<und [validated]>]}

Link to this function

locale_for_territory(territory)

View Source (since 2.26.0)

@spec locale_for_territory(Cldr.Locale.territory_code()) ::
  {:ok, Cldr.LanguageTag.t()} | {:error, {module(), String.t()}}

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"}}

Link to this function

locale_from_host(host, options \\ [])

View Source (since 2.26.0)

@spec locale_from_host(String.t(), Keyword.t()) ::
  {:ok, Cldr.LanguageTag.t()} | {:error, {module(), String.t()}}

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\""}}

Link to this function

new(locale_name)

View Source

Link to this function

new!(locale_name)

View Source

Link to this function

script_direction_from_locale(locale)

View Source (since 2.37.0)

Returns the script direction for a locale.

Arguments

language_tag is any language tag returned by Cldr.Locale.new/2 or any locale_name returned by Cldr.known_locale_names/1.

Returns

The script direction which is either :ltr (for left-to-right scripts) or :rtl (for right-to-left scripts).

Examples

iex> Plausible.Cldr.Locale.script_direction_from_locale "en-US"
:ltr

iex> Plausible.Cldr.Locale.script_direction_from_locale :ar
:rtl

Link to this function

territory_from_host(host)

View Source (since 2.26.0)

@spec territory_from_host(String.t()) ::
  {:ok, Cldr.Locale.territory_code()} | {:error, {module(), String.t()}}

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\""}}

Link to this function

territory_from_locale(locale)

View Source (since 2.18.2)

@spec territory_from_locale(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
  Cldr.Locale.territory_code()

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

Link to this function

timezone_from_locale(locale)

View Source (since 2.19.0)

@spec timezone_from_locale(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
  String.t() | {:error, {module(), String.t()}}

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"

Plausible.Cldr.Number

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.

Summary

Functions

parse(string, options \\ [])

Parse a string locale-aware manner and return a number.

resolve_currencies(list, options \\ [])

Resolve curencies from strings within a list.

resolve_currency(string, options \\ [])

Resolve a currency from a string

resolve_per(string, options \\ [])

Resolve and tokenize percent or permille from the beginning and/or the end of a string

resolve_pers(list, options \\ [])

Resolve and tokenize percent and permille sybols from strings within a list.

scan(string, options \\ [])

Scans a string locale-aware manner and returns a list of strings and numbers.

to_approx_string(number, options \\ [])

Formats a number and applies the :approximately format for a locale and number system.

to_at_least_string(number, options \\ [])

Formats a number and applies the :at_least format for a locale and number system.

to_at_most_string(number, options \\ [])

Formats a number and applies the :at_most format for a locale and number system.

to_range_string(range, options \\ [])

Formats the first and last numbers of a range and applies the :range format for a locale and number system.

to_string(number, options \\ default_options())

Returns a number formatted into a string according to a format pattern and options.

to_string!(number, options \\ default_options())

Same as the execution of to_string/2 but raises an exception if an error would be returned.

validate_number_system(locale, number_system)

Return a valid number system from a provided locale and number system name or type.

Functions

Link to this function

parse(string, options \\ [])

View Source

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"}}

Link to this function

resolve_currencies(list, options \\ [])

View Source

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]

Link to this function

resolve_currency(string, options \\ [])

View Source

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"}}

Link to this function

resolve_per(string, options \\ [])

View Source (since 2.22.0)

@spec resolve_per(String.t(), Keyword.t()) ::
  Cldr.Number.Parser.per()
  | [Cldr.Number.Parser.per() | String.t()]
  | {:error, {module(), String.t()}}

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]

Link to this function

resolve_pers(list, options \\ [])

View Source (since 2.22.0)

@spec resolve_pers([String.t(), ...], Keyword.t()) :: [
  Cldr.Number.Parser.per() | String.t()
]

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]

Link to this function

scan(string, options \\ [])

View Source

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"]

Link to this function

to_approx_string(number, options \\ [])

View Source

@spec to_approx_string(number() | Decimal.t(), Keyword.t() | Keyword.t() | map()) ::
  {:ok, String.t()} | {:error, {module(), String.t()}}

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"}

Link to this function

to_at_least_string(number, options \\ [])

View Source

@spec to_at_least_string(number() | Decimal.t(), Keyword.t() | Keyword.t() | map()) ::
  {:ok, String.t()} | {:error, {module(), String.t()}}

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+"}

Link to this function

to_at_most_string(number, options \\ [])

View Source

@spec to_at_most_string(number() | Decimal.t(), Keyword.t() | Keyword.t() | map()) ::
  {:ok, String.t()} | {:error, {module(), String.t()}}

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"}

Link to this function

to_range_string(range, options \\ [])

View Source

@spec to_range_string(Range.t(), Keyword.t() | Keyword.t() | map()) ::
  {:ok, String.t()} | {:error, {module(), String.t()}}

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"}

Link to this function

to_string(number, options \\ default_options())

View Source

@spec to_string(number() | Decimal.t(), Keyword.t() | map()) ::
  {:ok, String.t()} | {:error, {atom(), String.t()}}

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 isCldr.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"}}

Link to this function

to_string!(number, options \\ default_options())

View Source

@spec to_string!(number() | Decimal.t(), Keyword.t() | map()) :: String.t() | module()

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"

Link to this function

validate_number_system(locale, number_system)

View Source

@spec validate_number_system(
  Cldr.Locale.locale_name() | Cldr.LanguageTag.t(),
  Cldr.Number.System.system_name() | Cldr.Number.System.types()
) :: {:ok, Cldr.Number.System.system_name()} | {:error, {module(), String.t()}}

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"}}

Plausible.Cldr.Number.Cardinal

Implements cardinal plural rules for numbers.

Summary

Functions

available_locale_names()

The locale names for which plural rules are defined.

known_locale_names()

The configured locales for which plural rules are defined.

plural_rule(number, locale, rounding \\ Math.default_rounding())

Return the plural key for a given number in a given locale

plural_rules()

Returns all the plural rules defined in CLDR.

plural_rules_for(locale_name)

Return the plural rules for a locale.

pluralize(number, locale_name, substitutions)

Pluralize a number using cardinal plural rules and a substitution map.

Functions

Link to this function

available_locale_names()

View Source

The locale names for which plural rules are defined.

Link to this function

known_locale_names()

View Source

@spec known_locale_names() :: [Cldr.Locale.locale_name(), ...]

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.

Link to this function

plural_rule(number, locale, rounding \\ Math.default_rounding())

View Source

@spec plural_rule(
  Cldr.Math.number_or_decimal(),
  Cldr.Locale.locale_name() | Cldr.LanguageTag.t(),
  atom() | pos_integer()
) :: Cldr.Number.PluralRule.plural_type()

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

Link to this function

plural_rules()

View Source

@spec plural_rules() :: map()

Returns all the plural rules defined in CLDR.

Link to this function

plural_rules_for(locale_name)

View Source

@spec plural_rules_for(Cldr.Locale.locale_name() | Cldr.LanguageTag.t()) :: [
  {atom(), list()},
  ...
]

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.

Link to this function

pluralize(number, locale_name, substitutions)

View Source

@spec pluralize(
  Cldr.Math.number_or_decimal() | Range.t(),
  Cldr.Locale.locale_reference(),
  %{}
) :: any()

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"

Plausible.Cldr.Number.Format

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

Summary

Functions

all_formats_for(locale \\ Plausible.Cldr.get_locale())

Returns the decimal formats defined for a given locale.

all_formats_for!(locale \\ Plausible.Cldr.get_locale())

Returns the decimal formats defined for a given locale.

currency_spacing(locale, number_system)

Returns the currency space for a given locale and number system.

decimal_format_list()

Returns the list of decimal formats in the configured locales including the list of locales configured for precompilation in config.exs.

decimal_format_list_for(locale \\ Plausible.Cldr.get_locale())

Returns the list of decimal formats for a configured locale.

default_grouping_for(locale \\ Plausible.Cldr.get_locale())

Returns the default grouping for a locale as a map.

default_grouping_for!(locale)

Returns the default grouping for a locale or raises on error.

formats_for(locale \\ Plausible.Cldr.default_locale(), number_system \\ Cldr.Number.System.default_number_system_type())

Return the predfined formats for a given locale and number_system.

formats_for!(locale \\ Plausible.Cldr.default_locale(), number_system \\ Cldr.Number.System.default_number_system_type())

minimum_grouping_digits_for(locale \\ Plausible.Cldr.get_locale())

Returns the minimum grouping digits for a locale.

minimum_grouping_digits_for!(locale)

Returns the minimum grouping digits for a locale or raises on error.

Functions

Link to this function

all_formats_for(locale \\ Plausible.Cldr.get_locale())

View Source

@spec all_formats_for(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
  {:ok, map()} | {:error, {module(), String.t()}}

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}}

Link to this function

all_formats_for!(locale \\ Plausible.Cldr.get_locale())

View Source

@spec all_formats_for!(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
  map() | no_return()

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.

Link to this function

currency_spacing(locale, number_system)

View Source

@spec currency_spacing(
  Cldr.LanguageTag.t() | Cldr.Locale.locale_name(),
  Cldr.Number.System.system_name()
) :: map() | {:error, {module(), String.t()}}

Returns the currency space for a given locale and number system.

Link to this function

decimal_format_list()

View Source

@spec decimal_format_list() :: [Cldr.Number.Format.format()]

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 ¤", ...]

Link to this function

decimal_format_list_for(locale \\ Plausible.Cldr.get_locale())

View Source

@spec decimal_format_list_for(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
  {:ok, [String.t()]} | {:error, {module(), String.t()}}

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"]}

Link to this function

default_grouping_for(locale \\ Plausible.Cldr.get_locale())

View Source

@spec default_grouping_for(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
  {:ok, map()} | {:error, {module(), String.t()}}

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}}}

Link to this function

default_grouping_for!(locale)

View Source

@spec default_grouping_for!(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
  map() | no_return()

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}}

Link to this function

formats_for(locale \\ Plausible.Cldr.default_locale(), number_system \\ Cldr.Number.System.default_number_system_type())

View Source

@spec formats_for(Cldr.LanguageTag.t() | binary(), atom() | String.t()) ::
  {:ok, map()} | {:error, {module(), String.t()}}

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 ¤"]}],
   ...
  }

Link to this function

formats_for!(locale \\ Plausible.Cldr.default_locale(), number_system \\ Cldr.Number.System.default_number_system_type())

View Source

@spec formats_for!(
  Cldr.LanguageTag.t() | Cldr.Locale.locale_name(),
  Cldr.Number.System.system_name()
) ::
  map() | no_return()

Link to this function

minimum_grouping_digits_for(locale \\ Plausible.Cldr.get_locale())

View Source

@spec minimum_grouping_digits_for(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
  {:ok, non_neg_integer()} | {:error, {module(), String.t()}}

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}

Link to this function

minimum_grouping_digits_for!(locale)

View Source

@spec minimum_grouping_digits_for!(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
  non_neg_integer() | no_return()

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

Plausible.Cldr.Number.Formatter.Decimal

Summary

Functions

metadata!(format)

to_string(number, format, options \\ [])

Formats a number according to a decimal format string.

Functions

Link to this function

metadata!(format)

View Source

Link to this function

to_string(number, format, options \\ [])

View Source

@spec to_string(
  Cldr.Math.number_or_decimal(),
  String.t() | Cldr.Number.Format.Meta.t(),
  Keyword.t() | Cldr.Number.Format.Options.t()
) :: {:ok, String.t()} | {:error, {module(), String.t()}}

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.

Plausible.Cldr.Number.Ordinal

Implements ordinal plural rules for numbers.

Summary

Functions

available_locale_names()

The locale names for which plural rules are defined.

known_locale_names()

The configured locales for which plural rules are defined.

plural_rule(number, locale, rounding \\ Math.default_rounding())

Return the plural key for a given number in a given locale

plural_rules()

Returns all the plural rules defined in CLDR.

plural_rules_for(locale_name)

Return the plural rules for a locale.

pluralize(number, locale_name, substitutions)

Pluralize a number using ordinal plural rules and a substitution map.

Functions

Link to this function

available_locale_names()

View Source

The locale names for which plural rules are defined.

Link to this function

known_locale_names()

View Source

@spec known_locale_names() :: [Cldr.Locale.locale_name(), ...]

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.

Link to this function

plural_rule(number, locale, rounding \\ Math.default_rounding())

View Source

@spec plural_rule(
  Cldr.Math.number_or_decimal(),
  Cldr.Locale.locale_name() | Cldr.LanguageTag.t(),
  atom() | pos_integer()
) :: Cldr.Number.PluralRule.plural_type()

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

Link to this function

plural_rules()

View Source

@spec plural_rules() :: map()

Returns all the plural rules defined in CLDR.

Link to this function

plural_rules_for(locale_name)

View Source

@spec plural_rules_for(Cldr.Locale.locale_name() | Cldr.LanguageTag.t()) :: [
  {atom(), list()},
  ...
]

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.

Link to this function

pluralize(number, locale_name, substitutions)

View Source

@spec pluralize(
  Cldr.Math.number_or_decimal() | Range.t(),
  Cldr.Locale.locale_reference(),
  %{}
) :: any()

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"

Plausible.Cldr.Number.PluralRule.Range

Implements plural rules for ranges

Summary

Functions

plural_rule(first, last, locale)

Returns a final plural type for a start-of-range plural type, an end-of-range plural type and a locale.

Functions

Link to this function

plural_rule(first, last, locale)

View Source

@spec plural_rule(
  first :: Cldr.Number.PluralRule.plural_type(),
  last :: Cldr.Number.PluralRule.plural_type(),
  locale :: Cldr.Locale.locale_name() | Cldr.LanguageTag.t()
) :: Cldr.Number.PluralRule.plural_type()

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

Plausible.Cldr.Number.Symbol

Summary

Functions

all_decimal_symbols()

Returns a list of all decimal symbols defined by the locales configured in this backend as a list.

all_decimal_symbols_class()

Returns a list of all decimal symbols defined by the locales configured in this backend as a string.

all_grouping_symbols()

Returns a list of all grouping symbols defined by the locales configured in this backend as a list.

all_grouping_symbols_class()

Returns a list of all grouping symbols defined by the locales configured in this backend as a string.

number_symbols_for(locale \\ Plausible.Cldr.get_locale())

Returns a map of Cldr.Number.Symbol.t structs of the number symbols for each of the number systems of a locale.

number_symbols_for(locale, number_system)

Functions

Link to this function

all_decimal_symbols()

View Source

Returns a list of all decimal symbols defined by the locales configured in this backend as a list.

Link to this function

all_decimal_symbols_class()

View Source

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.

Link to this function

all_grouping_symbols()

View Source

Returns a list of all grouping symbols defined by the locales configured in this backend as a list.

Link to this function

all_grouping_symbols_class()

View Source

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.

Link to this function

number_symbols_for(locale \\ Plausible.Cldr.get_locale())

View Source

@spec number_symbols_for(Cldr.LanguageTag.t() | Cldr.Locale.locale_name()) ::
  {:ok, map()} | {:error, {module(), String.t()}}

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: ":"
   }
 }}

Link to this function

number_symbols_for(locale, number_system)

View Source

Plausible.Cldr.Number.System

Summary

Functions

number_system_for(locale, system_name)

Returns the actual number system from a number system type.

number_system_from_locale(locale)

Returns the number system from a language tag or locale name.

number_system_names_for(locale)

Returns the number systems available for a locale or {:error, message} if the locale is not known.

number_system_names_for!(locale)

number_system_types_for(locale)

number_systems_for(locale)

Returns the number systems available for a locale or {:error, message} if the locale is not known.

number_systems_for!(locale)

number_systems_like(locale, number_system)

system_name_from(system_name, locale)

Returns a number system name for a given locale and number system reference.

to_system(number, system)

Converts a number into the representation of a non-latin number system.

to_system!(number, system_name)

Converts a number into the representation of a non-latin number system. Returns a converted string or raises on error.

Functions

Link to this function

number_system_for(locale, system_name)

View Source

@spec number_system_for(
  Cldr.Locale.locale_reference(),
  Cldr.Number.System.system_name()
) ::
  {:ok, [atom()]} | {:error, {module(), String.t()}}

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}"}
}

Link to this function

number_system_from_locale(locale)

View Source

@spec number_system_from_locale(Cldr.Locale.locale_reference()) ::
  Cldr.Number.System.system_name()

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

Link to this function

number_system_names_for(locale)

View Source

@spec number_system_names_for(Cldr.Locale.locale_reference()) ::
  {:ok, [atom()]} | {:error, {module(), String.t()}}

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"}}

Link to this function

number_system_names_for!(locale)

View Source

Link to this function

number_system_types_for(locale)

View Source

Link to this function

number_systems_for(locale)

View Source

@spec number_systems_for(Cldr.Locale.locale_reference()) ::
  {:ok, map()} | {:error, {module(), String.t()}}

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"}}

Link to this function

number_systems_for!(locale)

View Source

Link to this function

number_systems_like(locale, number_system)

View Source

@spec number_systems_like(
  Cldr.Locale.locale_reference(),
  Cldr.Number.System.system_name()
) ::
  {:ok, list()} | {:error, tuple()}

Link to this function

system_name_from(system_name, locale)

View Source

@spec system_name_from(
  Cldr.Number.System.system_name(),
  Cldr.Locale.locale_name() | Cldr.LanguageTag.t()
) :: {:ok, atom()} | {:error, {module(), String.t()}}

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.

Link to this function

to_system(number, system)

View Source

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, "壹佰贰拾叁"}

Link to this function

to_system!(number, system_name)

View Source

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
"壹佰贰拾叁"

Plausible.Cldr.Number.Transliterate

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.

Summary

Functions

transliterate(sequence, locale \\ Plausible.Cldr.get_locale(), number_system \\ System.default_number_system_type())

Transliterates from latin digits to another number system's digits.

transliterate!(sequence, locale, number_system)

transliterate_digits(digits, from_system, to_system)

Transliterates digits from one number system to another number system

Functions

Link to this function

transliterate(sequence, locale \\ Plausible.Cldr.get_locale(), number_system \\ System.default_number_system_type())

View Source

@spec transliterate(
  String.t(),
  Cldr.LanguageTag.t() | Cldr.Locale.locale_name(),
  Cldr.Number.System.system_name() | Cldr.Number.System.types()
) :: String.t() | {:error, {module(), String.t()}}

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: ๑๒๓๕๕๖"

Link to this function

transliterate!(sequence, locale, number_system)

View Source

Link to this function

transliterate_digits(digits, from_system, to_system)

View Source

@spec transliterate_digits(
  String.t(),
  Cldr.Number.System.system_name(),
  Cldr.Number.System.system_name()
) :: String.t()

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"

Plausible.Cldr.Rbnf.NumberSystem

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)
...> |> Enum.sort()
[
  :armenian_lower,
  :armenian_upper,
  :cyrillic_lower,
  :ethiopic,
  :georgian,
  :greek_lower,
  :greek_upper,
  :hebrew,
  :hebrew_item,
  :roman_lower,
  :roman_upper,
  :tamil,
  :zz_default
]

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"}

Summary

Functions

all_rule_sets()

armenian_lower(number)

armenian_lower(number, locale)

armenian_upper(number)

armenian_upper(number, locale)

cyrillic_lower(number)

cyrillic_lower(number, locale)

cyrillic_lower_1_10(number, language_tag)

cyrillic_lower_final(number, language_tag)

cyrillic_lower_post(number, language_tag)

cyrillic_lower_thousands(number, language_tag)

ethiopic(number)

ethiopic(number, locale)

ethiopic_p1(number, language_tag)

ethiopic_p2(number, language_tag)

ethiopic_p3(number, language_tag)

ethiopic_p(number, language_tag)

georgian(number)

georgian(number, locale)

greek_lower(number)

greek_lower(number, locale)

greek_numeral_majuscules(number, language_tag)

greek_numeral_minuscules(number, language_tag)

greek_upper(number)

greek_upper(number, locale)

hebrew(number)

hebrew(number, locale)

hebrew_0_99(number, language_tag)

hebrew_item(number)

hebrew_item(number, locale)

hebrew_item_hundreds(number, language_tag)

hebrew_thousands(number, language_tag)

roman_lower(number)

roman_lower(number, locale)

roman_upper(number)

roman_upper(number, locale)

rule_sets()

rule_sets(rbnf_locale_name)

tamil(number)

tamil(number, locale)

tamil_thousands(number, language_tag)

zz_default(number)

zz_default(number, locale)

Functions

Link to this function

all_rule_sets()

View Source

Link to this function

armenian_lower(number)

View Source

Link to this function

armenian_lower(number, locale)

View Source

Link to this function

armenian_upper(number)

View Source

Link to this function

armenian_upper(number, locale)

View Source

Link to this function

cyrillic_lower(number)

View Source

Link to this function

cyrillic_lower(number, locale)

View Source

Link to this function

cyrillic_lower_1_10(number, language_tag)

View Source

Link to this function

cyrillic_lower_final(number, language_tag)

View Source

Link to this function

cyrillic_lower_post(number, language_tag)

View Source

Link to this function

cyrillic_lower_thousands(number, language_tag)

View Source

Link to this function

ethiopic(number)

View Source

Link to this function

ethiopic(number, locale)

View Source

Link to this function

ethiopic_p1(number, language_tag)

View Source

Link to this function

ethiopic_p2(number, language_tag)

View Source

Link to this function

ethiopic_p3(number, language_tag)

View Source

Link to this function

ethiopic_p(number, language_tag)

View Source

Link to this function

georgian(number)

View Source

Link to this function

georgian(number, locale)

View Source

Link to this function

greek_lower(number)

View Source

Link to this function

greek_lower(number, locale)

View Source

Link to this function

greek_numeral_majuscules(number, language_tag)

View Source

Link to this function

greek_numeral_minuscules(number, language_tag)

View Source

Link to this function

greek_upper(number)

View Source

Link to this function

greek_upper(number, locale)

View Source

Link to this function

hebrew(number)

View Source

Link to this function

hebrew(number, locale)

View Source

Link to this function

hebrew_0_99(number, language_tag)

View Source

Link to this function

hebrew_item(number)

View Source

Link to this function

hebrew_item(number, locale)

View Source

Link to this function

hebrew_item_hundreds(number, language_tag)

View Source

Link to this function

hebrew_thousands(number, language_tag)

View Source

Link to this function

roman_lower(number)

View Source

Link to this function

roman_lower(number, locale)

View Source

Link to this function

roman_upper(number)

View Source

Link to this function

roman_upper(number, locale)

View Source

Link to this function

rule_sets()

View Source

Link to this function

rule_sets(rbnf_locale_name)

View Source

Link to this function

tamil(number)

View Source

Link to this function

tamil(number, locale)

View Source

Link to this function

tamil_thousands(number, language_tag)

View Source

Link to this function

zz_default(number)

View Source

Link to this function

zz_default(number, locale)

View Source

Plausible.Cldr.Rbnf.Ordinal

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")
...> |> Enum.sort()
[
  :digits_ordinal,
  :digits_ordinal_feminine,
  :digits_ordinal_feminine_plural,
  :digits_ordinal_masculine,
  :digits_ordinal_masculine_plural
]

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"}

Summary

Functions

all_rule_sets()

digits_ordinal(number, locale)

rule_sets()

rule_sets(rbnf_locale_name)

Functions

Link to this function

all_rule_sets()

View Source

Link to this function

digits_ordinal(number, locale)

View Source

Link to this function

rule_sets()

View Source

Link to this function

rule_sets(rbnf_locale_name)

View Source

Plausible.Cldr.Rbnf.Spellout

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")
...> |> Enum.sort()
[
  :spellout_cardinal,
  :spellout_cardinal_verbose,
  :spellout_numbering,
  :spellout_numbering_verbose,
  :spellout_numbering_year,
  :spellout_ordinal,
  :spellout_ordinal_verbose
]

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"}

Summary

Functions

all_rule_sets()

number and language_tag

and_o(number, language_tag)

commas(number, language_tag)

commas_o(number, language_tag)

r2d_year(number, language_tag)

rule_sets()

rule_sets(rbnf_locale_name)

spellout_cardinal(number, locale)

spellout_cardinal_verbose(number, locale)

spellout_numbering(number, locale)

spellout_numbering_verbose(number, locale)

spellout_numbering_year(number, locale)

spellout_ordinal(number, locale)

spellout_ordinal_verbose(number, locale)

th(number, language_tag)

tieth(number, language_tag)

Functions

Link to this function

all_rule_sets()

View Source

Link to this function

number and language_tag

View Source

Link to this function

and_o(number, language_tag)

View Source

Link to this function

commas(number, language_tag)

View Source

Link to this function

commas_o(number, language_tag)

View Source

Link to this function

r2d_year(number, language_tag)

View Source

Link to this function

rule_sets()

View Source

Link to this function

rule_sets(rbnf_locale_name)

View Source

Link to this function

spellout_cardinal(number, locale)

View Source

Link to this function

spellout_cardinal_verbose(number, locale)

View Source

Link to this function

spellout_numbering(number, locale)

View Source

Link to this function

spellout_numbering_verbose(number, locale)

View Source

Link to this function

spellout_numbering_year(number, locale)

View Source

Link to this function

spellout_ordinal(number, locale)

View Source

Link to this function

spellout_ordinal_verbose(number, locale)

View Source

Link to this function

th(number, language_tag)

View Source

Link to this function

tieth(number, language_tag)

View Source

Plausible.ClickhouseEventV2

Event schema for when NumericIDs migration is complete

Summary

Functions

new(attrs)

Functions

Link to this function

new(attrs)

View Source

Plausible.ClickhouseRepo

Summary

Functions

aggregate(queryable, aggregate, opts \\ [])

Callback implementation for Ecto.Repo.aggregate/3.

aggregate(queryable, aggregate, field, opts)

Callback implementation for Ecto.Repo.aggregate/4.

all(queryable, opts \\ [])

Callback implementation for Ecto.Repo.all/2.

checked_out?()

Callback implementation for Ecto.Repo.checked_out?/0.

checkout(fun, opts \\ [])

Callback implementation for Ecto.Repo.checkout/2.

child_spec(opts)

config()

Callback implementation for Ecto.Repo.config/0.

default_options(operation)

Callback implementation for Ecto.Repo.default_options/1.

disconnect_all(interval, opts \\ [])

A convenience function for SQL-based repositories that forces all connections in the pool to disconnect within the given interval.

exists?(queryable, opts \\ [])

Callback implementation for Ecto.Repo.exists?/2.

get(queryable, id, opts \\ [])

Callback implementation for Ecto.Repo.get/3.

get!(queryable, id, opts \\ [])

Callback implementation for Ecto.Repo.get!/3.

get_by(queryable, clauses, opts \\ [])

Callback implementation for Ecto.Repo.get_by/3.

get_by!(queryable, clauses, opts \\ [])

Callback implementation for Ecto.Repo.get_by!/3.

get_dynamic_repo()

Callback implementation for Ecto.Repo.get_dynamic_repo/0.

insert_stream(source_or_schema, rows, opts \\ [])

Similar to insert_all/2 but with the following differences

load(schema_or_types, data)

Callback implementation for Ecto.Repo.load/2.

one(queryable, opts \\ [])

Callback implementation for Ecto.Repo.one/2.

one!(queryable, opts \\ [])

Callback implementation for Ecto.Repo.one!/2.

parallel_tasks(queries)

preload(struct_or_structs_or_nil, preloads, opts \\ [])

Callback implementation for Ecto.Repo.preload/3.

prepare_query(operation, query, opts)

Callback implementation for Ecto.Repo.prepare_query/3.

put_dynamic_repo(dynamic)

Callback implementation for Ecto.Repo.put_dynamic_repo/1.

query(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given query.

query!(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given query.

reload(queryable, opts \\ [])

Callback implementation for Ecto.Repo.reload/2.

reload!(queryable, opts \\ [])

Callback implementation for Ecto.Repo.reload!/2.

start_link(opts \\ [])

Callback implementation for Ecto.Repo.start_link/1.

stop(timeout \\ 5000)

Callback implementation for Ecto.Repo.stop/1.

stream(queryable, opts \\ [])

Callback implementation for Ecto.Repo.stream/2.

to_sql(operation, queryable)

A convenience function for SQL-based repositories that translates the given query to SQL.

Functions

Link to this function

aggregate(queryable, aggregate, opts \\ [])

View Source

Callback implementation for Ecto.Repo.aggregate/3.

Link to this function

aggregate(queryable, aggregate, field, opts)

View Source

Callback implementation for Ecto.Repo.aggregate/4.

Link to this function

all(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.all/2.

Link to this function

checked_out?()

View Source

Callback implementation for Ecto.Repo.checked_out?/0.

Link to this function

checkout(fun, opts \\ [])

View Source

Callback implementation for Ecto.Repo.checkout/2.

Link to this function

child_spec(opts)

View Source

Link to this function

config()

View Source

Callback implementation for Ecto.Repo.config/0.

Link to this function

default_options(operation)

View Source

Callback implementation for Ecto.Repo.default_options/1.

Link to this function

disconnect_all(interval, opts \\ [])

View Source

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.

Link to this function

exists?(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.exists?/2.

Link to this function

get(queryable, id, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get/3.

Link to this function

get!(queryable, id, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get!/3.

Link to this function

get_by(queryable, clauses, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get_by/3.

Link to this function

get_by!(queryable, clauses, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get_by!/3.

Link to this function

get_dynamic_repo()

View Source

Callback implementation for Ecto.Repo.get_dynamic_repo/0.

Link to this function

insert_stream(source_or_schema, rows, opts \\ [])

View Source

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])

Link to this function

load(schema_or_types, data)

View Source

Callback implementation for Ecto.Repo.load/2.

Link to this function

one(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.one/2.

Link to this function

one!(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.one!/2.

Link to this function

parallel_tasks(queries)

View Source

Link to this function

preload(struct_or_structs_or_nil, preloads, opts \\ [])

View Source

Callback implementation for Ecto.Repo.preload/3.

Link to this function

prepare_query(operation, query, opts)

View Source

Callback implementation for Ecto.Repo.prepare_query/3.

Link to this function

put_dynamic_repo(dynamic)

View Source

Callback implementation for Ecto.Repo.put_dynamic_repo/1.

Link to this function

query(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given query.

See Ecto.Adapters.SQL.query/4 for more information.

Link to this function

query!(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given query.

See Ecto.Adapters.SQL.query!/4 for more information.

Link to this function

reload(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.reload/2.

Link to this function

reload!(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.reload!/2.

Link to this function

start_link(opts \\ [])

View Source

Callback implementation for Ecto.Repo.start_link/1.

Link to this function

stop(timeout \\ 5000)

View Source

Callback implementation for Ecto.Repo.stop/1.

Link to this function

stream(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.stream/2.

Link to this function

to_sql(operation, queryable)

View Source

A convenience function for SQL-based repositories that translates the given query to SQL.

See Ecto.Adapters.SQL.to_sql/3 for more information.

Plausible.ClickhouseSessionV2

Session schema for when NumericIDs migration is complete

Summary

Functions

random_uint64()

Functions

Link to this function

random_uint64()

View Source

Plausible.ClickhouseSessionV2.BoolUInt8

Custom type to cast Bool as UInt8

Summary

Functions

embed_as(_)

Callback implementation for Ecto.Type.embed_as/1.

equal?(term1, term2)

Callback implementation for Ecto.Type.equal?/2.

Functions

Link to this function

embed_as(_)

View Source

Callback implementation for Ecto.Type.embed_as/1.

Link to this function

equal?(term1, term2)

View Source

Callback implementation for Ecto.Type.equal?/2.

Plausible.ConfigHelpers

Summary

Functions

get_int_from_path_or_env(config_dir, var_name, default \\ nil)

get_var_from_path_or_env(config_dir, var_name, default \\ nil)

Functions

Link to this function

get_int_from_path_or_env(config_dir, var_name, default \\ nil)

View Source

Link to this function

get_var_from_path_or_env(config_dir, var_name, default \\ nil)

View Source

Plausible.DataCase

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.

Plausible.DataMigration

Base module for coordinated Clickhouse data migrations run via remote shell or otherwise (TBD).

Plausible.DataMigration.NumericIDs

Numeric IDs migration, SQL files available at: priv/data_migrations/NumericIDs/sql

Summary

Functions

confirm(message, func, default_choice \\ :yes)

run(opts \\ [])

run_sql(name, assigns \\ [])

run_sql_confirm(name, options \\ [])

Functions

Link to this function

confirm(message, func, default_choice \\ :yes)

View Source

Link to this function

run(opts \\ [])

View Source

Link to this function

run_sql(name, assigns \\ [])

View Source

Link to this function

run_sql_confirm(name, options \\ [])

View Source

Plausible.DataMigration.Repo

Ecto.Repo for Clickhouse data migrations, to be started manually, outside of the main application supervision tree.

Summary

Functions

aggregate(queryable, aggregate, opts \\ [])

Callback implementation for Ecto.Repo.aggregate/3.

aggregate(queryable, aggregate, field, opts)

Callback implementation for Ecto.Repo.aggregate/4.

all(queryable, opts \\ [])

Callback implementation for Ecto.Repo.all/2.

checked_out?()

Callback implementation for Ecto.Repo.checked_out?/0.

checkout(fun, opts \\ [])

Callback implementation for Ecto.Repo.checkout/2.

child_spec(opts)

config()

Callback implementation for Ecto.Repo.config/0.

default_options(operation)

Callback implementation for Ecto.Repo.default_options/1.

delete(struct, opts \\ [])

Callback implementation for Ecto.Repo.delete/2.

delete!(struct, opts \\ [])

Callback implementation for Ecto.Repo.delete!/2.

delete_all(queryable, opts \\ [])

Callback implementation for Ecto.Repo.delete_all/2.

disconnect_all(interval, opts \\ [])

A convenience function for SQL-based repositories that forces all connections in the pool to disconnect within the given interval.

exists?(queryable, opts \\ [])

Callback implementation for Ecto.Repo.exists?/2.

get(queryable, id, opts \\ [])

Callback implementation for Ecto.Repo.get/3.

get!(queryable, id, opts \\ [])

Callback implementation for Ecto.Repo.get!/3.

get_by(queryable, clauses, opts \\ [])

Callback implementation for Ecto.Repo.get_by/3.

get_by!(queryable, clauses, opts \\ [])

Callback implementation for Ecto.Repo.get_by!/3.

get_dynamic_repo()

Callback implementation for Ecto.Repo.get_dynamic_repo/0.

insert(struct, opts \\ [])

Callback implementation for Ecto.Repo.insert/2.

insert!(struct, opts \\ [])

Callback implementation for Ecto.Repo.insert!/2.

insert_all(schema_or_source, entries, opts \\ [])

Callback implementation for Ecto.Repo.insert_all/3.

insert_or_update(changeset, opts \\ [])

Callback implementation for Ecto.Repo.insert_or_update/2.

insert_or_update!(changeset, opts \\ [])

Callback implementation for Ecto.Repo.insert_or_update!/2.

insert_stream(source_or_schema, rows, opts \\ [])

Similar to insert_all/2 but with the following differences

load(schema_or_types, data)

Callback implementation for Ecto.Repo.load/2.

one(queryable, opts \\ [])

Callback implementation for Ecto.Repo.one/2.

one!(queryable, opts \\ [])

Callback implementation for Ecto.Repo.one!/2.

preload(struct_or_structs_or_nil, preloads, opts \\ [])

Callback implementation for Ecto.Repo.preload/3.

prepare_query(operation, query, opts)

Callback implementation for Ecto.Repo.prepare_query/3.

put_dynamic_repo(dynamic)

Callback implementation for Ecto.Repo.put_dynamic_repo/1.

query(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given query.

query!(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given query.

reload(queryable, opts \\ [])

Callback implementation for Ecto.Repo.reload/2.

reload!(queryable, opts \\ [])

Callback implementation for Ecto.Repo.reload!/2.

start(url, max_threads)

start_link(opts \\ [])

Callback implementation for Ecto.Repo.start_link/1.

stop(timeout \\ 5000)

Callback implementation for Ecto.Repo.stop/1.

stream(queryable, opts \\ [])

Callback implementation for Ecto.Repo.stream/2.

to_sql(operation, queryable)

A convenience function for SQL-based repositories that translates the given query to SQL.

update(struct, opts \\ [])

Callback implementation for Ecto.Repo.update/2.

update!(struct, opts \\ [])

Callback implementation for Ecto.Repo.update!/2.

update_all(queryable, updates, opts \\ [])

Callback implementation for Ecto.Repo.update_all/3.

Functions

Link to this function

aggregate(queryable, aggregate, opts \\ [])

View Source

Callback implementation for Ecto.Repo.aggregate/3.

Link to this function

aggregate(queryable, aggregate, field, opts)

View Source

Callback implementation for Ecto.Repo.aggregate/4.

Link to this function

all(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.all/2.

Link to this function

checked_out?()

View Source

Callback implementation for Ecto.Repo.checked_out?/0.

Link to this function

checkout(fun, opts \\ [])

View Source

Callback implementation for Ecto.Repo.checkout/2.

Link to this function

child_spec(opts)

View Source

Link to this function

config()

View Source

Callback implementation for Ecto.Repo.config/0.

Link to this function

default_options(operation)

View Source

Callback implementation for Ecto.Repo.default_options/1.

Link to this function

delete(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete/2.

Link to this function

delete!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete!/2.

Link to this function

delete_all(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete_all/2.

Link to this function

disconnect_all(interval, opts \\ [])

View Source

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.

Link to this function

exists?(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.exists?/2.

Link to this function

get(queryable, id, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get/3.

Link to this function

get!(queryable, id, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get!/3.

Link to this function

get_by(queryable, clauses, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get_by/3.

Link to this function

get_by!(queryable, clauses, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get_by!/3.

Link to this function

get_dynamic_repo()

View Source

Callback implementation for Ecto.Repo.get_dynamic_repo/0.

Link to this function

insert(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert/2.

Link to this function

insert!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert!/2.

Link to this function

insert_all(schema_or_source, entries, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_all/3.

Link to this function

insert_or_update(changeset, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_or_update/2.

Link to this function

insert_or_update!(changeset, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_or_update!/2.

Link to this function

insert_stream(source_or_schema, rows, opts \\ [])

View Source

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])

Link to this function

load(schema_or_types, data)

View Source

Callback implementation for Ecto.Repo.load/2.

Link to this function

one(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.one/2.

Link to this function

one!(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.one!/2.

Link to this function

preload(struct_or_structs_or_nil, preloads, opts \\ [])

View Source

Callback implementation for Ecto.Repo.preload/3.

Link to this function

prepare_query(operation, query, opts)

View Source

Callback implementation for Ecto.Repo.prepare_query/3.

Link to this function

put_dynamic_repo(dynamic)

View Source

Callback implementation for Ecto.Repo.put_dynamic_repo/1.

Link to this function

query(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given query.

See Ecto.Adapters.SQL.query/4 for more information.

Link to this function

query!(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given query.

See Ecto.Adapters.SQL.query!/4 for more information.

Link to this function

reload(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.reload/2.

Link to this function

reload!(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.reload!/2.

Link to this function

start(url, max_threads)

View Source

Link to this function

start_link(opts \\ [])

View Source

Callback implementation for Ecto.Repo.start_link/1.

Link to this function

stop(timeout \\ 5000)

View Source

Callback implementation for Ecto.Repo.stop/1.

Link to this function

stream(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.stream/2.

Link to this function

to_sql(operation, queryable)

View Source

A convenience function for SQL-based repositories that translates the given query to SQL.

See Ecto.Adapters.SQL.to_sql/3 for more information.

Link to this function

update(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update/2.

Link to this function

update!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update!/2.

Link to this function

update_all(queryable, updates, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update_all/3.

Plausible.DataMigration.RewriteFunnelDupes

A data fix migration that seeks funnels having steps whose goals are equally named. It then tries to rewrite the duplicate goals using the oldest goal available. In extreme cases, e.g. when multiple duplicates are found for a single funnel, it will either reduce or completely remove the funnel. This enables us to run a migration later on that will delete duplicate goals and enforce goal uniqueness at the database level via a CHECK constraint.

To run, just call the run function.

Summary

Functions

apply_change(funnel_id, change)

confirm(message, func, default_choice \\ :yes)

execute(data)

run(_ \\ [])

run_sql(name, assigns \\ [])

run_sql_confirm(name, options \\ [])

to_db_ops(meta)

to_map(row)

translate_to_db_ops(data)

Functions

Link to this function

apply_change(funnel_id, change)

View Source

Link to this function

confirm(message, func, default_choice \\ :yes)

View Source

Link to this function

execute(data)

View Source

Link to this function

run(_ \\ [])

View Source

Link to this function

run_sql(name, assigns \\ [])

View Source

Link to this function

run_sql_confirm(name, options \\ [])

View Source

Link to this function

to_db_ops(meta)

View Source

Link to this function

to_map(row)

View Source

Link to this function

translate_to_db_ops(data)

View Source

Plausible.DebugReplayInfo

Function execution context (with arguments) to Sentry reports.

Summary

Functions

deserialize(replay_info)

include_sentry_replay_info()

Functions

Link to this function

deserialize(replay_info)

View Source

@spec deserialize(String.t()) :: any()

Link to this macro

include_sentry_replay_info()

View Source (macro)

Plausible.Ecto.EventName

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.

Summary

Functions

cast(val)

Callback implementation for Ecto.Type.cast/1.

dump(val)

Callback implementation for Ecto.Type.dump/1.

embed_as(_)

Callback implementation for Ecto.Type.embed_as/1.

equal?(term1, term2)

Callback implementation for Ecto.Type.equal?/2.

load(val)

Callback implementation for Ecto.Type.load/1.

type()

Callback implementation for Ecto.Type.type/0.

Functions

Link to this function

cast(val)

View Source

Callback implementation for Ecto.Type.cast/1.

Link to this function

dump(val)

View Source

Callback implementation for Ecto.Type.dump/1.

Link to this function

embed_as(_)

View Source

Callback implementation for Ecto.Type.embed_as/1.

Link to this function

equal?(term1, term2)

View Source

Callback implementation for Ecto.Type.equal?/2.

Link to this function

load(val)

View Source

Callback implementation for Ecto.Type.load/1.

Link to this function

type()

View Source

Callback implementation for Ecto.Type.type/0.

Plausible.Event.WriteBuffer

Summary

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

flush()

init(buffer)

Callback implementation for GenServer.init/1.

insert(event)

start_link(opts)

Functions

Link to this function

child_spec(init_arg)

View Source

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

flush()

View Source

Link to this function

init(buffer)

View Source

Callback implementation for GenServer.init/1.

Link to this function

insert(event)

View Source

Link to this function

start_link(opts)

View Source

Plausible.Factory

Summary

Functions

api_key_factory()

build(factory_name, attrs \\ %{})

build_list(number_of_records, factory_name, attrs \\ %{})

build_pair(factory_name, attrs \\ %{})

business_subscription_factory()

ch_session_factory()

create(_)

create(_, _)

create_list(_, _, _)

create_pair(_, _)

custom_domain_factory()

enterprise_plan_factory()

event_factory()

factory(factory_name)

Raises a helpful error if no factory is defined.

goal_factory()

google_auth_factory()

growth_subscription_factory()

imported_browsers_factory()

imported_devices_factory()

imported_entry_pages_factory()

imported_exit_pages_factory()

imported_locations_factory()

imported_operating_systems_factory()

imported_pages_factory()

imported_sources_factory()

imported_visitors_factory()

insert(already_built_record)

insert(already_built_record, function_opts)

insert(factory_name, attrs, opts)

insert_list(number_of_records, factory_name, attrs \\ %{})

insert_list(number_of_records, factory_name, attrs, opts)

insert_pair(factory_name, attrs \\ %{})

insert_pair(factory_name, attrs, opts)

invitation_factory()

monthly_report_factory()

pageview_factory()

params_for(factory_name, attrs \\ %{})

params_with_assocs(factory_name, attrs \\ %{})

shared_link_factory()

site_factory(attrs)

site_membership_factory()

spike_notification_factory()

string_params_for(factory_name, attrs \\ %{})

string_params_with_assocs(factory_name, attrs \\ %{})

subscription_factory()

user_factory(attrs)

weekly_report_factory()

Functions

Link to this function

api_key_factory()

View Source

Link to this function

build(factory_name, attrs \\ %{})

View Source

Link to this function

build_list(number_of_records, factory_name, attrs \\ %{})

View Source

Link to this function

build_pair(factory_name, attrs \\ %{})

View Source

Link to this function

business_subscription_factory()

View Source

Link to this function

ch_session_factory()

View Source

Link to this function

create(_)

View Source

@spec create(any()) :: no_return()

Link to this function

create(_, _)

View Source

@spec create(any(), any()) :: no_return()

Link to this function

create_list(_, _, _)

View Source

@spec create_list(any(), any(), any()) :: no_return()

Link to this function

create_pair(_, _)

View Source

@spec create_pair(any(), any()) :: no_return()

Link to this function

custom_domain_factory()

View Source

Link to this function

enterprise_plan_factory()

View Source

Link to this function

event_factory()

View Source

Link to this function

factory(factory_name)

View Source

@spec factory(any()) :: no_return()

Raises a helpful error if no factory is defined.

Link to this function

goal_factory()

View Source

Link to this function

google_auth_factory()

View Source

Link to this function

growth_subscription_factory()

View Source

Link to this function

imported_browsers_factory()

View Source

Link to this function

imported_devices_factory()

View Source

Link to this function

imported_entry_pages_factory()

View Source

Link to this function

imported_exit_pages_factory()

View Source

Link to this function

imported_locations_factory()

View Source

Link to this function

imported_operating_systems_factory()

View Source

Link to this function

imported_pages_factory()

View Source

Link to this function

imported_sources_factory()

View Source

Link to this function

imported_visitors_factory()

View Source

Link to this function

insert(already_built_record)

View Source

Link to this function

insert(already_built_record, function_opts)

View Source

Link to this function

insert(factory_name, attrs, opts)

View Source

Link to this function

insert_list(number_of_records, factory_name, attrs \\ %{})

View Source

Link to this function

insert_list(number_of_records, factory_name, attrs, opts)

View Source

Link to this function

insert_pair(factory_name, attrs \\ %{})

View Source

Link to this function

insert_pair(factory_name, attrs, opts)

View Source

Link to this function

invitation_factory()

View Source

Link to this function

monthly_report_factory()

View Source

Link to this function

pageview_factory()

View Source

Link to this function

params_for(factory_name, attrs \\ %{})

View Source

Link to this function

params_with_assocs(factory_name, attrs \\ %{})

View Source

Link to this function

shared_link_factory()

View Source

Link to this function

site_factory(attrs)

View Source

Link to this function

site_membership_factory()

View Source

Link to this function

spike_notification_factory()

View Source

Link to this function

string_params_for(factory_name, attrs \\ %{})

View Source

Link to this function

string_params_with_assocs(factory_name, attrs \\ %{})

View Source

Link to this function

subscription_factory()

View Source

Link to this function

user_factory(attrs)

View Source

Link to this function

weekly_report_factory()

View Source

Plausible.Funnel

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.

Summary

Types

t()

Functions

changeset(funnel \\ %__MODULE__{}, attrs \\ %{})

max_steps()

min_steps()

put_step_orders(changeset)

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Funnel{
  __meta__: term(),
  goals: term(),
  id: term(),
  inserted_at: term(),
  name: term(),
  site: term(),
  site_id: term(),
  steps: term(),
  updated_at: term()
}

Functions

Link to this function

changeset(funnel \\ %__MODULE__{}, attrs \\ %{})

View Source

Link to this macro

max_steps()

View Source (macro)

Link to this macro

min_steps()

View Source (macro)

Link to this function

put_step_orders(changeset)

View Source

Plausible.Funnel.Step

This module defines the database schema for a single Funnel step. See: Plausible.Funnel for more information.

Summary

Types

t()

Functions

changeset(step, attrs \\ %{})

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Funnel.Step{
  __meta__: term(),
  funnel: term(),
  funnel_id: term(),
  goal: term(),
  goal_id: term(),
  id: term(),
  inserted_at: term(),
  step_order: term(),
  updated_at: term()
}

Functions

Link to this function

changeset(step, attrs \\ %{})

View Source

Plausible.Funnels

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.

Summary

Functions

create(site, name, steps)

create_changeset(site, name, steps)

delete(site_id, funnel_id)

ephemeral_definition(site, name, steps)

get(site_id, by)

list(site)

Functions

Link to this function

create(site, name, steps)

View Source

@spec create(Plausible.Site.t(), String.t(), [map()]) ::
  {:ok, Plausible.Funnel.t()}
  | {:error, Ecto.Changeset.t() | :invalid_funnel_size}

Link to this function

create_changeset(site, name, steps)

View Source

@spec create_changeset(Plausible.Site.t(), String.t(), [map()]) :: Ecto.Changeset.t()

Link to this function

delete(site_id, funnel_id)

View Source

@spec delete(Plausible.Site.t() | pos_integer(), pos_integer()) :: :ok

Link to this function

ephemeral_definition(site, name, steps)

View Source

@spec ephemeral_definition(Plausible.Site.t(), String.t(), [map()]) ::
  Plausible.Funnel.t()

Link to this function

get(site_id, by)

View Source

@spec get(Plausible.Site.t() | pos_integer(), pos_integer()) ::
  Plausible.Funnel.t() | nil

Link to this function

list(site)

View Source

@spec list(Plausible.Site.t()) :: [
  %{name: String.t(), id: pos_integer(), steps_count: pos_integer()}
]

Plausible.Geo

This module provides an API for fetching IP geolocation.

Summary

Functions

await_loader()

Waits for the database to start after calling load_db/1 with the async option.

database_type()

Returns geodatabase type.

load_db(opts)

Starts the geodatabase loading process. Two modes are supported: local file and MaxMind license key.

lookup(ip_address)

Looks up geo info about an IP address.

Functions

Link to this function

await_loader()

View Source

Waits for the database to start after calling load_db/1 with the async option.

Link to this function

database_type()

View Source

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"

Link to this function

load_db(opts)

View Source

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

Link to this function

lookup(ip_address)

View Source

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" => "加州"
      }
    }
  ]
}

Plausible.Goal

Summary

Types

t()

Functions

changeset(goal, attrs \\ %{})

currency_options()

revenue?(goal)

valid_currencies()

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Goal{
  __meta__: term(),
  currency: term(),
  event_name: term(),
  funnels: term(),
  id: term(),
  inserted_at: term(),
  page_path: term(),
  site: term(),
  site_id: term(),
  updated_at: term()
}

Functions

Link to this function

changeset(goal, attrs \\ %{})

View Source

Link to this function

currency_options()

View Source

Link to this function

revenue?(goal)

View Source

Link to this function

valid_currencies()

View Source

Plausible.Goals

Summary

Functions

count(site)

create(site, params, opts \\ [])

Creates a Goal for a site.

delete(id, site_id)

If a goal belongs to funnel(s), we need to inspect their number of steps.

find_or_create(site, map)

for_site(site, opts \\ [])

for_site_query(site, opts \\ [])

Functions

Link to this function

count(site)

View Source

@spec count(Plausible.Site.t()) :: non_neg_integer()

Link to this function

create(site, params, opts \\ [])

View Source

@spec create(Plausible.Site.t(), map(), Keyword.t()) ::
  {:ok, Plausible.Goal.t()}
  | {:error, Ecto.Changeset.t()}
  | {:error, :upgrade_required}

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.

Link to this function

delete(id, site_id)

View Source

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.

Link to this function

find_or_create(site, map)

View Source

Link to this function

for_site(site, opts \\ [])

View Source

Link to this function

for_site_query(site, opts \\ [])

View Source

Plausible.Google.Api

Summary

Types

google_analytics_view()

import_auth()

Functions

fetch_and_persist(site, report_request, opts \\ [])

fetch_stats(site, map, limit)

fetch_verified_properties(auth)

get_view(access_token, lookup_id)

Returns a single Google Analytics view if the user has access to it.

import_analytics(site, date_range, view_id, auth)

Imports stats from a Google Analytics UA view to a Plausible site.

import_authorize_url(site_id, redirect_to)

list_views(access_token)

Lists Google Analytics views grouped by hostname.

search_console_authorize_url(site_id, redirect_to)

Types

Link to this type

google_analytics_view()

View Source

@type google_analytics_view() :: {view_name :: String.t(), view_id :: String.t()}

Link to this type

import_auth()

View Source

@type import_auth() ::
  {access_token :: String.t(), refresh_token :: String.t(),
   expires_at :: String.t()}

Functions

Link to this function

fetch_and_persist(site, report_request, opts \\ [])

View Source

@spec fetch_and_persist(
  Plausible.Site.t(),
  Plausible.Google.ReportRequest.t(),
  Keyword.t()
) ::
  :ok | {:error, term()}

Link to this function

fetch_stats(site, map, limit)

View Source

Link to this function

fetch_verified_properties(auth)

View Source

Link to this function

get_view(access_token, lookup_id)

View Source

@spec get_view(access_token :: String.t(), lookup_id :: String.t()) ::
  {:ok, google_analytics_view()} | {:ok, nil} | {:error, term()}

Returns a single Google Analytics view if the user has access to it.

Link to this function

import_analytics(site, date_range, view_id, auth)

View Source

@spec import_analytics(Plausible.Site.t(), Date.Range.t(), String.t(), import_auth()) ::
  :ok | {:error, term()}

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

Link to this function

import_authorize_url(site_id, redirect_to)

View Source

Link to this function

list_views(access_token)

View Source

@spec list_views(access_token :: String.t()) ::
  {:ok, %{required(hostname :: String.t()) => [google_analytics_view()]}}
  | {:error, term()}

Lists Google Analytics views grouped by hostname.

Link to this function

search_console_authorize_url(site_id, redirect_to)

View Source

Plausible.Google.Api.Mock

Summary

Functions

fetch_stats(auth, query, limit)

Functions

Link to this function

fetch_stats(auth, query, limit)

View Source

Plausible.Google.Buffer

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.

Summary

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

flush(pid, timeout \\ :infinity)

Flushes all table buffers to Clickhouse.

handle_continue(arg, state)

Callback implementation for GenServer.handle_continue/2.

init(opts)

Callback implementation for GenServer.init/1.

insert_many(pid, table_name, records)

Puts the given records into the table buffer.

size(pid, table_name)

Returns the total count of items in the given table buffer.

start_link()

stop(pid)

Functions

Link to this function

child_spec(init_arg)

View Source

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

flush(pid, timeout \\ :infinity)

View Source

Flushes all table buffers to Clickhouse.

Link to this function

handle_continue(arg, state)

View Source

Callback implementation for GenServer.handle_continue/2.

Link to this function

init(opts)

View Source

Callback implementation for GenServer.init/1.

Link to this function

insert_many(pid, table_name, records)

View Source

@spec insert_many(pid(), term(), [map()]) :: :ok

Puts the given records into the table buffer.

Link to this function

size(pid, table_name)

View Source

@spec size(pid(), term()) :: non_neg_integer()

Returns the total count of items in the given table buffer.

Link to this function

start_link()

View Source

Link to this function

stop(pid)

View Source

Plausible.Google.HTTP

Summary

Functions

fetch_access_token(code)

get_analytics_start_date(view_id, access_token)

get_report(report_request)

list_sites(access_token)

list_stats(access_token, property, date_range, limit, page \\ nil)

list_views_for_user(access_token)

refresh_auth_token(refresh_token)

Functions

Link to this function

fetch_access_token(code)

View Source

Link to this function

get_analytics_start_date(view_id, access_token)

View Source

Link to this function

get_report(report_request)

View Source

@spec get_report(Plausible.Google.ReportRequest.t()) ::
  {:ok, {[map()], String.t() | nil}} | {:error, any()}

Link to this function

list_sites(access_token)

View Source

Link to this function

list_stats(access_token, property, date_range, limit, page \\ nil)

View Source

Link to this function

list_views_for_user(access_token)

View Source

Link to this function

refresh_auth_token(refresh_token)

View Source

Plausible.Google.ReportRequest

Summary

Types

t()

Functions

full_report()

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Google.ReportRequest{
  access_token: String.t(),
  dataset: String.t(),
  date_range: Date.Range.t(),
  dimensions: [String.t()],
  metrics: [String.t()],
  page_size: non_neg_integer(),
  page_token: String.t() | nil,
  view_id: term()
}

Functions

Link to this function

full_report()

View Source

Plausible.HTTPClient

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.

Summary

Functions

get(url, headers \\ [], params \\ nil)

Make a GET request

impl()

post(url, headers \\ [], params \\ nil, finch_req_opts \\ [])

Make a POST request

Functions

Link to this function

get(url, headers \\ [], params \\ nil)

View Source

Make a GET request

Link to this function

impl()

View Source

@spec impl() :: Plausible.HTTPClient

Link to this function

post(url, headers \\ [], params \\ nil, finch_req_opts \\ [])

View Source

Make a POST request

Plausible.HTTPClient.Interface behaviour

Summary

Types

finch_request_opts()

headers()

params()

response()

url()

Callbacks

get(url)

get(url, headers)

get(url, headers, params)

post(url, headers, params)

post(url, headers, params, finch_request_opts)

Types

Link to this type

finch_request_opts()

View Source

@type finch_request_opts() :: Keyword.t()

Link to this type

headers()

View Source

@type headers() :: Finch.Request.headers()

Link to this type

params()

View Source

@type params() :: Finch.Request.body() | map()

Link to this type

response()

View Source

@type response() ::
  {:ok, Finch.Response.t()}
  | {:error,
     Mint.Types.error() | Finch.Error.t() | Plausible.HTTPClient.Non200Error.t()}

Link to this type

url()

View Source

@type url() :: Finch.Request.url()

Callbacks

Link to this callback

get(url)

View Source

@callback get(url()) :: response()

Link to this callback

get(url, headers)

View Source

@callback get(url(), headers()) :: response()

Link to this callback

get(url, headers, params)

View Source

@callback get(url(), headers(), params()) :: response()

Link to this callback

post(url, headers, params)

View Source

@callback post(url(), headers(), params()) :: response()

Link to this callback

post(url, headers, params, finch_request_opts)

View Source

@callback post(url(), headers(), params(), finch_request_opts()) :: response()

Plausible.HTTPClient.Non200Error

Summary

Types

t()

Functions

new(response)

Types

Link to this type

t()

View Source

@type t() :: %Plausible.HTTPClient.Non200Error{reason: Finch.Response.t()}

Functions

Link to this function

new(response)

View Source

@spec new(Finch.Response.t()) :: t()

Plausible.ImportDeletionRepo

A dedicated repo for import related mutations

Summary

Functions

aggregate(queryable, aggregate, opts \\ [])

Callback implementation for Ecto.Repo.aggregate/3.

aggregate(queryable, aggregate, field, opts)

Callback implementation for Ecto.Repo.aggregate/4.

all(queryable, opts \\ [])

Callback implementation for Ecto.Repo.all/2.

checked_out?()

Callback implementation for Ecto.Repo.checked_out?/0.

checkout(fun, opts \\ [])

Callback implementation for Ecto.Repo.checkout/2.

child_spec(opts)

config()

Callback implementation for Ecto.Repo.config/0.

default_options(operation)

Callback implementation for Ecto.Repo.default_options/1.

delete(struct, opts \\ [])

Callback implementation for Ecto.Repo.delete/2.

delete!(struct, opts \\ [])

Callback implementation for Ecto.Repo.delete!/2.

delete_all(queryable, opts \\ [])

Callback implementation for Ecto.Repo.delete_all/2.

disconnect_all(interval, opts \\ [])

A convenience function for SQL-based repositories that forces all connections in the pool to disconnect within the given interval.

exists?(queryable, opts \\ [])

Callback implementation for Ecto.Repo.exists?/2.

get(queryable, id, opts \\ [])

Callback implementation for Ecto.Repo.get/3.

get!(queryable, id, opts \\ [])

Callback implementation for Ecto.Repo.get!/3.

get_by(queryable, clauses, opts \\ [])

Callback implementation for Ecto.Repo.get_by/3.

get_by!(queryable, clauses, opts \\ [])

Callback implementation for Ecto.Repo.get_by!/3.

get_dynamic_repo()

Callback implementation for Ecto.Repo.get_dynamic_repo/0.

insert(struct, opts \\ [])

Callback implementation for Ecto.Repo.insert/2.

insert!(struct, opts \\ [])

Callback implementation for Ecto.Repo.insert!/2.

insert_all(schema_or_source, entries, opts \\ [])

Callback implementation for Ecto.Repo.insert_all/3.

insert_or_update(changeset, opts \\ [])

Callback implementation for Ecto.Repo.insert_or_update/2.

insert_or_update!(changeset, opts \\ [])

Callback implementation for Ecto.Repo.insert_or_update!/2.

insert_stream(source_or_schema, rows, opts \\ [])

Similar to insert_all/2 but with the following differences

load(schema_or_types, data)

Callback implementation for Ecto.Repo.load/2.

one(queryable, opts \\ [])

Callback implementation for Ecto.Repo.one/2.

one!(queryable, opts \\ [])

Callback implementation for Ecto.Repo.one!/2.

preload(struct_or_structs_or_nil, preloads, opts \\ [])

Callback implementation for Ecto.Repo.preload/3.

prepare_query(operation, query, opts)

Callback implementation for Ecto.Repo.prepare_query/3.

put_dynamic_repo(dynamic)

Callback implementation for Ecto.Repo.put_dynamic_repo/1.

query(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given query.

query!(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given query.

reload(queryable, opts \\ [])

Callback implementation for Ecto.Repo.reload/2.

reload!(queryable, opts \\ [])

Callback implementation for Ecto.Repo.reload!/2.

start_link(opts \\ [])

Callback implementation for Ecto.Repo.start_link/1.

stop(timeout \\ 5000)

Callback implementation for Ecto.Repo.stop/1.

stream(queryable, opts \\ [])

Callback implementation for Ecto.Repo.stream/2.

to_sql(operation, queryable)

A convenience function for SQL-based repositories that translates the given query to SQL.

update(struct, opts \\ [])

Callback implementation for Ecto.Repo.update/2.

update!(struct, opts \\ [])

Callback implementation for Ecto.Repo.update!/2.

update_all(queryable, updates, opts \\ [])

Callback implementation for Ecto.Repo.update_all/3.

Functions

Link to this function

aggregate(queryable, aggregate, opts \\ [])

View Source

Callback implementation for Ecto.Repo.aggregate/3.

Link to this function

aggregate(queryable, aggregate, field, opts)

View Source

Callback implementation for Ecto.Repo.aggregate/4.

Link to this function

all(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.all/2.

Link to this function

checked_out?()

View Source

Callback implementation for Ecto.Repo.checked_out?/0.

Link to this function

checkout(fun, opts \\ [])

View Source

Callback implementation for Ecto.Repo.checkout/2.

Link to this function

child_spec(opts)

View Source

Link to this function

config()

View Source

Callback implementation for Ecto.Repo.config/0.

Link to this function

default_options(operation)

View Source

Callback implementation for Ecto.Repo.default_options/1.

Link to this function

delete(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete/2.

Link to this function

delete!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete!/2.

Link to this function

delete_all(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete_all/2.

Link to this function

disconnect_all(interval, opts \\ [])

View Source

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.

Link to this function

exists?(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.exists?/2.

Link to this function

get(queryable, id, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get/3.

Link to this function

get!(queryable, id, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get!/3.

Link to this function

get_by(queryable, clauses, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get_by/3.

Link to this function

get_by!(queryable, clauses, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get_by!/3.

Link to this function

get_dynamic_repo()

View Source

Callback implementation for Ecto.Repo.get_dynamic_repo/0.

Link to this function

insert(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert/2.

Link to this function

insert!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert!/2.

Link to this function

insert_all(schema_or_source, entries, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_all/3.

Link to this function

insert_or_update(changeset, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_or_update/2.

Link to this function

insert_or_update!(changeset, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_or_update!/2.

Link to this function

insert_stream(source_or_schema, rows, opts \\ [])

View Source

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])

Link to this function

load(schema_or_types, data)

View Source

Callback implementation for Ecto.Repo.load/2.

Link to this function

one(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.one/2.

Link to this function

one!(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.one!/2.

Link to this function

preload(struct_or_structs_or_nil, preloads, opts \\ [])

View Source

Callback implementation for Ecto.Repo.preload/3.

Link to this function

prepare_query(operation, query, opts)

View Source

Callback implementation for Ecto.Repo.prepare_query/3.

Link to this function

put_dynamic_repo(dynamic)

View Source

Callback implementation for Ecto.Repo.put_dynamic_repo/1.

Link to this function

query(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given query.

See Ecto.Adapters.SQL.query/4 for more information.

Link to this function

query!(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given query.

See Ecto.Adapters.SQL.query!/4 for more information.

Link to this function

reload(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.reload/2.

Link to this function

reload!(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.reload!/2.

Link to this function

start_link(opts \\ [])

View Source

Callback implementation for Ecto.Repo.start_link/1.

Link to this function

stop(timeout \\ 5000)

View Source

Callback implementation for Ecto.Repo.stop/1.

Link to this function

stream(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.stream/2.

Link to this function

to_sql(operation, queryable)

View Source

A convenience function for SQL-based repositories that translates the given query to SQL.

See Ecto.Adapters.SQL.to_sql/3 for more information.

Link to this function

update(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update/2.

Link to this function

update!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update!/2.

Link to this function

update_all(queryable, updates, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update_all/3.

Plausible.Imported

Summary

Functions

forget(site)

from_google_analytics(data, site_id, table)

tables()

Functions

Link to this function

forget(site)

View Source

Link to this function

from_google_analytics(data, site_id, table)

View Source

Link to this function

tables()

View Source

@spec tables() :: [String.t()]

Plausible.IngestRepo

Write-centric Clickhouse access interface

Summary

Functions

aggregate(queryable, aggregate, opts \\ [])

Callback implementation for Ecto.Repo.aggregate/3.

aggregate(queryable, aggregate, field, opts)

Callback implementation for Ecto.Repo.aggregate/4.

all(queryable, opts \\ [])

Callback implementation for Ecto.Repo.all/2.

checked_out?()

Callback implementation for Ecto.Repo.checked_out?/0.

checkout(fun, opts \\ [])

Callback implementation for Ecto.Repo.checkout/2.

child_spec(opts)

config()

Callback implementation for Ecto.Repo.config/0.

default_options(operation)

Callback implementation for Ecto.Repo.default_options/1.

delete(struct, opts \\ [])

Callback implementation for Ecto.Repo.delete/2.

delete!(struct, opts \\ [])

Callback implementation for Ecto.Repo.delete!/2.

delete_all(queryable, opts \\ [])

Callback implementation for Ecto.Repo.delete_all/2.

disconnect_all(interval, opts \\ [])

A convenience function for SQL-based repositories that forces all connections in the pool to disconnect within the given interval.

exists?(queryable, opts \\ [])

Callback implementation for Ecto.Repo.exists?/2.

get(queryable, id, opts \\ [])

Callback implementation for Ecto.Repo.get/3.

get!(queryable, id, opts \\ [])

Callback implementation for Ecto.Repo.get!/3.

get_by(queryable, clauses, opts \\ [])

Callback implementation for Ecto.Repo.get_by/3.

get_by!(queryable, clauses, opts \\ [])

Callback implementation for Ecto.Repo.get_by!/3.

get_dynamic_repo()

Callback implementation for Ecto.Repo.get_dynamic_repo/0.

insert(struct, opts \\ [])

Callback implementation for Ecto.Repo.insert/2.

insert!(struct, opts \\ [])

Callback implementation for Ecto.Repo.insert!/2.

insert_all(schema_or_source, entries, opts \\ [])

Callback implementation for Ecto.Repo.insert_all/3.

insert_or_update(changeset, opts \\ [])

Callback implementation for Ecto.Repo.insert_or_update/2.

insert_or_update!(changeset, opts \\ [])

Callback implementation for Ecto.Repo.insert_or_update!/2.

insert_stream(source_or_schema, rows, opts \\ [])

Similar to insert_all/2 but with the following differences

load(schema_or_types, data)

Callback implementation for Ecto.Repo.load/2.

one(queryable, opts \\ [])

Callback implementation for Ecto.Repo.one/2.

one!(queryable, opts \\ [])

Callback implementation for Ecto.Repo.one!/2.

preload(struct_or_structs_or_nil, preloads, opts \\ [])

Callback implementation for Ecto.Repo.preload/3.

prepare_query(operation, query, opts)

Callback implementation for Ecto.Repo.prepare_query/3.

put_dynamic_repo(dynamic)

Callback implementation for Ecto.Repo.put_dynamic_repo/1.

query(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given query.

query!(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given query.

reload(queryable, opts \\ [])

Callback implementation for Ecto.Repo.reload/2.

reload!(queryable, opts \\ [])

Callback implementation for Ecto.Repo.reload!/2.

start_link(opts \\ [])

Callback implementation for Ecto.Repo.start_link/1.

stop(timeout \\ 5000)

Callback implementation for Ecto.Repo.stop/1.

stream(queryable, opts \\ [])

Callback implementation for Ecto.Repo.stream/2.

to_sql(operation, queryable)

A convenience function for SQL-based repositories that translates the given query to SQL.

update(struct, opts \\ [])

Callback implementation for Ecto.Repo.update/2.

update!(struct, opts \\ [])

Callback implementation for Ecto.Repo.update!/2.

update_all(queryable, updates, opts \\ [])

Callback implementation for Ecto.Repo.update_all/3.

Functions

Link to this function

aggregate(queryable, aggregate, opts \\ [])

View Source

Callback implementation for Ecto.Repo.aggregate/3.

Link to this function

aggregate(queryable, aggregate, field, opts)

View Source

Callback implementation for Ecto.Repo.aggregate/4.

Link to this function

all(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.all/2.

Link to this function

checked_out?()

View Source

Callback implementation for Ecto.Repo.checked_out?/0.

Link to this function

checkout(fun, opts \\ [])

View Source

Callback implementation for Ecto.Repo.checkout/2.

Link to this function

child_spec(opts)

View Source

Link to this function

config()

View Source

Callback implementation for Ecto.Repo.config/0.

Link to this function

default_options(operation)

View Source

Callback implementation for Ecto.Repo.default_options/1.

Link to this function

delete(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete/2.

Link to this function

delete!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete!/2.

Link to this function

delete_all(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete_all/2.

Link to this function

disconnect_all(interval, opts \\ [])

View Source

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.

Link to this function

exists?(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.exists?/2.

Link to this function

get(queryable, id, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get/3.

Link to this function

get!(queryable, id, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get!/3.

Link to this function

get_by(queryable, clauses, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get_by/3.

Link to this function

get_by!(queryable, clauses, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get_by!/3.

Link to this function

get_dynamic_repo()

View Source

Callback implementation for Ecto.Repo.get_dynamic_repo/0.

Link to this function

insert(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert/2.

Link to this function

insert!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert!/2.

Link to this function

insert_all(schema_or_source, entries, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_all/3.

Link to this function

insert_or_update(changeset, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_or_update/2.

Link to this function

insert_or_update!(changeset, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_or_update!/2.

Link to this function

insert_stream(source_or_schema, rows, opts \\ [])

View Source

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])

Link to this function

load(schema_or_types, data)

View Source

Callback implementation for Ecto.Repo.load/2.

Link to this function

one(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.one/2.

Link to this function

one!(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.one!/2.

Link to this function

preload(struct_or_structs_or_nil, preloads, opts \\ [])

View Source

Callback implementation for Ecto.Repo.preload/3.

Link to this function

prepare_query(operation, query, opts)

View Source

Callback implementation for Ecto.Repo.prepare_query/3.

Link to this function

put_dynamic_repo(dynamic)

View Source

Callback implementation for Ecto.Repo.put_dynamic_repo/1.

Link to this function

query(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given query.

See Ecto.Adapters.SQL.query/4 for more information.

Link to this function

query!(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given query.

See Ecto.Adapters.SQL.query!/4 for more information.

Link to this function

reload(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.reload/2.

Link to this function

reload!(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.reload!/2.

Link to this function

start_link(opts \\ [])

View Source

Callback implementation for Ecto.Repo.start_link/1.

Link to this function

stop(timeout \\ 5000)

View Source

Callback implementation for Ecto.Repo.stop/1.

Link to this function

stream(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.stream/2.

Link to this function

to_sql(operation, queryable)

View Source

A convenience function for SQL-based repositories that translates the given query to SQL.

See Ecto.Adapters.SQL.to_sql/3 for more information.

Link to this function

update(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update/2.

Link to this function

update!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update!/2.

Link to this function

update_all(queryable, updates, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update_all/3.

Plausible.Ingestion.Counters

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).

Summary

Functions

child_spec(opts)

enabled?()

stop(pid)

Functions

Link to this function

child_spec(opts)

View Source

@spec child_spec(Keyword.t()) :: Supervisor.child_spec() | :ignore

Link to this function

enabled?()

View Source

@spec enabled?() :: boolean()

Link to this function

stop(pid)

View Source

@spec stop(pid()) :: :ok

Plausible.Ingestion.Counters.Buffer

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.

Summary

Types

bucket_fn_opt()

t()

unix_timestamp()

Functions

aggregate(buffer, metric, domain, timestamp)

bucket_10s(datetime)

flush(buffer, now \\ DateTime.utc_now())

new(buffer_name, opts \\ [])

previous_10s(datetime)

Types

Link to this type

bucket_fn_opt()

View Source

@type bucket_fn_opt() ::
  {:aggregate_bucket_fn, (NaiveDateTime.t() -> unix_timestamp())}
  | {:flush_boundary_fn, (DateTime.t() -> unix_timestamp())}

Link to this type

t()

View Source

@type t() :: %Plausible.Ingestion.Counters.Buffer{
  aggregate_bucket_fn: term(),
  buffer_name: term(),
  flush_boundary_fn: term()
}

Link to this type

unix_timestamp()

View Source

@type unix_timestamp() :: pos_integer()

Functions

Link to this function

aggregate(buffer, metric, domain, timestamp)

View Source

@spec aggregate(t(), binary(), binary(), timestamp :: NaiveDateTime.t()) :: t()

Link to this function

bucket_10s(datetime)

View Source

@spec bucket_10s(NaiveDateTime.t()) :: unix_timestamp()

Link to this function

flush(buffer, now \\ DateTime.utc_now())

View Source

@spec flush(t(), now :: DateTime.t()) :: [Plausible.Ingestion.Counters.Record.t()]

Link to this function

new(buffer_name, opts \\ [])

View Source

@spec new(atom(), [bucket_fn_opt()]) :: t()

Link to this function

previous_10s(datetime)

View Source

@spec previous_10s(DateTime.t()) :: unix_timestamp()

Plausible.Ingestion.Counters.Record

Clickhouse schema for storing ingest counter metrics

Summary

Types

t()

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Ingestion.Counters.Record{
  __meta__: term(),
  domain: term(),
  event_timebucket: term(),
  metric: term(),
  site_id: term(),
  value: term()
}

Plausible.Ingestion.Counters.TelemetryHandler

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.

Summary

Functions

handle_event(list, measurements, map, buffer)

install(buffer)

Functions

Link to this function

handle_event(list, measurements, map, buffer)

View Source

@spec handle_event([atom()], any(), map(), Plausible.Ingestion.Counters.Buffer.t()) ::
  :ok

Link to this function

install(buffer)

View Source

@spec install(Plausible.Ingestion.Counters.Buffer.t()) :: :ok

Plausible.Ingestion.Event

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.

Summary

Types

drop_reason()

t()

Functions

build_and_buffer(request)

emit_telemetry_buffered(event)

emit_telemetry_dropped(event, reason)

telemetry_event_buffered()

telemetry_event_dropped()

Types

Link to this type

drop_reason()

View Source

@type drop_reason() ::
  :bot | :spam_referrer | Plausible.Site.GateKeeper.policy() | :invalid

Link to this type

t()

View Source

@type t() :: %Plausible.Ingestion.Event{
  changeset: %Ecto.Changeset{
    action: term(),
    changes: term(),
    constraints: term(),
    data: term(),
    empty_values: term(),
    errors: term(),
    filters: term(),
    params: term(),
    prepare: term(),
    repo: term(),
    repo_opts: term(),
    required: term(),
    types: term(),
    valid?: term(),
    validations: term()
  },
  clickhouse_event:
    %Plausible.ClickhouseEventV2{
      __meta__: term(),
      browser: term(),
      browser_version: term(),
      city_geoname_id: term(),
      country_code: term(),
      hostname: term(),
      "meta.key": term(),
      "meta.value": term(),
      name: term(),
      operating_system: term(),
      operating_system_version: term(),
      pathname: term(),
      referrer: term(),
      referrer_source: term(),
      revenue_reporting_amount: term(),
      revenue_reporting_currency: term(),
      revenue_source_amount: term(),
      revenue_source_currency: term(),
      screen_size: term(),
      session_id: term(),
      site_id: term(),
      subdivision1_code: term(),
      subdivision2_code: term(),
      timestamp: term(),
      transferred_from: term(),
      user_id: term(),
      utm_campaign: term(),
      utm_content: term(),
      utm_medium: term(),
      utm_source: term(),
      utm_term: term()
    }
    | nil,
  clickhouse_event_attrs: map(),
  domain: String.t() | nil,
  drop_reason: drop_reason(),
  dropped?: boolean(),
  request: Plausible.Ingestion.Request.t(),
  salts: map(),
  site:
    %Plausible.Site{
      __meta__: term(),
      allowed_event_props: term(),
      conversions_enabled: term(),
      custom_domain: term(),
      domain: term(),
      domain_changed_at: term(),
      domain_changed_from: term(),
      from_cache?: term(),
      funnels_enabled: term(),
      goals: term(),
      google_auth: term(),
      id: term(),
      imported_data: term(),
      ingest_rate_limit_scale_seconds: term(),
      ingest_rate_limit_threshold: term(),
      inserted_at: term(),
      invitations: term(),
      locked: term(),
      members: term(),
      memberships: term(),
      monthly_report: term(),
      native_stats_start_at: term(),
      owner: term(),
      ownership: term(),
      props_enabled: term(),
      public: term(),
      revenue_goals: term(),
      spike_notification: term(),
      stats_start_date: term(),
      timezone: term(),
      updated_at: term(),
      weekly_report: term()
    }
    | nil
}

Functions

Link to this function

build_and_buffer(request)

View Source

@spec build_and_buffer(Plausible.Ingestion.Request.t()) ::
  {:ok, %{buffered: [t()], dropped: [t()]}}

Link to this function

emit_telemetry_buffered(event)

View Source

@spec emit_telemetry_buffered(t()) :: :ok

Link to this function

emit_telemetry_dropped(event, reason)

View Source

@spec emit_telemetry_dropped(t(), drop_reason()) :: :ok

Link to this function

telemetry_event_buffered()

View Source

@spec telemetry_event_buffered() :: [atom()]

Link to this function

telemetry_event_dropped()

View Source

@spec telemetry_event_dropped() :: [atom()]

Plausible.Ingestion.Request

The %Plausible.Ingestion.Request{} struct stores all needed fields to create an event downstream. Pre-eliminary validation is made to detect user errors early.

Summary

Types

t()

Functions

build(conn, now \\ NaiveDateTime.utc_now())

Builds and initially validates %Plausible.Ingestion.Request{} struct from %Plug.Conn{}.

sanitize_hostname(hostname)

Removes the "www" part of a hostname.

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Ingestion.Request{
  domains: term(),
  event_name: term(),
  hash_mode: term(),
  hostname: term(),
  pathname: term(),
  props: term(),
  query_params: term(),
  referrer: term(),
  remote_ip: term(),
  revenue_source: term(),
  timestamp: term(),
  uri: term(),
  user_agent: term()
}

Functions

Link to this function

build(conn, now \\ NaiveDateTime.utc_now())

View Source

@spec build(Plug.Conn.t(), NaiveDateTime.t()) ::
  {:ok, t()} | {:error, Ecto.Changeset.t()}

Builds and initially validates %Plausible.Ingestion.Request{} struct from %Plug.Conn{}.

Link to this function

sanitize_hostname(hostname)

View Source

Removes the "www" part of a hostname.

Plausible.Mailer

Summary

Types

result()

Functions

deliver(email)

deliver_later(email, opts \\ [])

deliver_later!(email, opts \\ [])

deliver_now(email, opts \\ [])

deliver_now!(email, opts \\ [])

send(email)

Types

Link to this type

result()

View Source

@type result() :: :ok | {:error, :hard_bounce} | {:error, :unknown_error}

Functions

Link to this function

deliver(email)

View Source

@spec deliver(any()) :: no_return()

Link to this function

deliver_later(email, opts \\ [])

View Source

Link to this function

deliver_later!(email, opts \\ [])

View Source

Link to this function

deliver_now(email, opts \\ [])

View Source

@spec deliver_now(Bamboo.Email.t(), Enum.t()) ::
  {:ok, Bamboo.Email.t()}
  | {:ok, Bamboo.Email.t(), any()}
  | {:error, Exception.t() | String.t()}

Link to this function

deliver_now!(email, opts \\ [])

View Source

@spec deliver_now!(Bamboo.Email.t(), Enum.t()) ::
  Bamboo.Email.t() | {Bamboo.Email.t(), any()}

Link to this function

send(email)

View Source

@spec send(Bamboo.Email.t()) :: result()

Plausible.OpenTelemetry.Sampler

Custom OpenTelemetry sampler implementation that ignores particular traces to reduce noise. Ingestion HTTP requests and queries to Oban tables are ignored, for example.

Plausible.PaddleApi.Mock

Summary

Functions

fetch_prices(product_ids)

get_invoices(subscription)

get_subscription(_)

update_subscription(_, map)

Functions

Link to this function

fetch_prices(product_ids)

View Source

Link to this function

get_invoices(subscription)

View Source

Link to this function

get_subscription(_)

View Source

Link to this function

update_subscription(_, map)

View Source

Plausible.Plugins.API.Goals

Plugins API context module for Goals. All high level Goal operations should be implemented here.

Summary

Types

create_request()

Functions

create(site, goal_or_goals)

get(site, id)

get_goals(site, params)

Types

Link to this type

create_request()

View Source

@type create_request() ::
  PlausibleWeb.Plugins.API.Schemas.Goal.CreateRequest.CustomEvent.t()
  | PlausibleWeb.Plugins.API.Schemas.Goal.CreateRequest.Revenue.t()
  | PlausibleWeb.Plugins.API.Schemas.Goal.CreateRequest.Pageview.t()

Functions

Link to this function

create(site, goal_or_goals)

View Source

@spec create(
  Plausible.Site.t(),
  create_request() | [create_request()]
) ::
  {:ok, [Plausible.Goal.t()]}
  | {:error, Ecto.Changeset.t()}
  | {:error, :upgrade_required}

Link to this function

get(site, id)

View Source

@spec get(Plausible.Site.t(), pos_integer()) :: nil | Plausible.Goal.t()

Link to this function

get_goals(site, params)

View Source

@spec get_goals(Plausible.Site.t(), map()) :: {:ok, Paginator.Page.t()}

Plausible.Plugins.API.Pagination

Cursor-based pagination for the Plugins API. Can be moved to another namespace in case used elsewhere.

Summary

Functions

paginate(queryable, params, opts, repo_opts \\ [])

Functions

Link to this function

paginate(queryable, params, opts, repo_opts \\ [])

View Source

@spec paginate(Ecto.Queryable.t(), map(), Keyword.t(), Keyword.t()) ::
  Paginator.Page.t()

Plausible.Plugins.API.SharedLinks

Plugins API context module for Shared Links. All high level Shared Links operations should be implemented here.

Summary

Functions

get(site, id)

get_or_create(site, name, password \\ nil)

get_shared_links(site, params)

Functions

Link to this function

get(site, id)

View Source

@spec get(Plausible.Site.t(), pos_integer() | String.t()) ::
  nil | Plausible.Site.SharedLink.t()

Link to this function

get_or_create(site, name, password \\ nil)

View Source

@spec get_or_create(Plausible.Site.t(), String.t(), String.t() | nil) ::
  {:ok, Plausible.Site.SharedLink.t()}

Link to this function

get_shared_links(site, params)

View Source

@spec get_shared_links(Plausible.Site.t(), map()) :: {:ok, Paginator.Page.t()}

Plausible.Plugins.API.Token

Ecto schema for Plugins API Tokens. Tokens are stored hashed and require a description.

Tokens are considered secret, although the Plugins API by nature will expose very little, if any, destructive/insecure operations.

The raw token version is meant to be presented to the user upon creation. It is prefixed with a plain text identifier allowing source scanning for leaked secrets.

Summary

Types

t()

Functions

generate(random_bytes \\ random_bytes())

hash(raw)

insert_changeset(site, map, attrs \\ %{})

last_used_humanize(token)

prefix()

Raw tokens are prefixed so that tools like https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning can scan repositories for accidental secret commits.

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Plugins.API.Token{
  __meta__: term(),
  description: term(),
  hint: term(),
  id: term(),
  inserted_at: term(),
  last_used_at: term(),
  site: term(),
  site_id: term(),
  token_hash: term(),
  updated_at: term()
}

Functions

Link to this function

generate(random_bytes \\ random_bytes())

View Source

@spec generate(String.t()) :: map()

Link to this function

hash(raw)

View Source

@spec hash(String.t()) :: binary()

Link to this function

insert_changeset(site, map, attrs \\ %{})

View Source

@spec insert_changeset(Plausible.Site.t(), map(), map()) :: Ecto.Changeset.t()

Link to this function

last_used_humanize(token)

View Source

@spec last_used_humanize(t()) :: String.t()

Link to this function

prefix()

View Source

Raw tokens are prefixed so that tools like https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning can scan repositories for accidental secret commits.

Plausible.Plugins.API.Tokens

Context module for Plugins API Tokens. Exposes high-level operation for token-based authentication flows.

Summary

Functions

any?(site)

create(site, description, generated_token \\ Token.generate())

delete(site, token_id)

find(raw)

list(site)

update_last_seen(token, now \\ NaiveDateTime.utc_now())

Functions

Link to this function

any?(site)

View Source

@spec any?(Plausible.Site.t()) :: boolean()

Link to this function

create(site, description, generated_token \\ Token.generate())

View Source

Link to this function

delete(site, token_id)

View Source

@spec delete(Plausible.Site.t(), String.t()) :: :ok

Link to this function

find(raw)

View Source

@spec find(String.t()) ::
  {:ok, Plausible.Plugins.API.Token.t()} | {:error, :not_found}

Link to this function

list(site)

View Source

@spec list(Plausible.Site.t()) :: {:ok, [Plausible.Plugins.API.Token.t()]}

Link to this function

update_last_seen(token, now \\ NaiveDateTime.utc_now())

View Source

@spec update_last_seen(Plausible.Plugins.API.Token.t(), NaiveDateTime.t()) ::
  {:ok, Plausible.Plugins.API.Token.t()}

Plausible.PromEx

Summary

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

Functions

Link to this function

child_spec(init_arg)

View Source

Returns a specification to start this module under a supervisor.

See Supervisor.

Plausible.PromEx.Plugins.PlausibleMetrics

Custom PromEx plugin for instrumenting code within Plausible app.

Summary

Functions

execute_cache_metrics()

Add telemetry events for Cachex user agents and sessions

execute_write_buffer_metrics()

Add telemetry events for Session and Event write buffers

Functions

Link to this function

execute_cache_metrics()

View Source

Add telemetry events for Cachex user agents and sessions

Link to this function

execute_write_buffer_metrics()

View Source

Add telemetry events for Session and Event write buffers

Plausible.Props

Context module for handling custom event props.

Summary

Types

prop()

Functions

allow(site, prop_or_props)

Allows a prop key or a list of props keys to be included in ClickHouse queries. Allowing prop keys does not affect ingestion, as we don't want any data to be dropped or lost.

allow_changeset(site, prop_or_props)

allow_existing_props(site)

Allows the 300 most frequent props keys for a specific site over the past 6 months.

configured?(site)

Returns whether the site has configured custom props or not.

disallow(site, prop)

Removes a previously allowed prop key from the allow list. This means this prop key won't be included in ClickHouse queries. This doesn't drop any ClickHouse data, nor affects ingestion.

internal_keys()

Lists prop keys used internally.

max_prop_key_length()

max_prop_value_length()

max_props()

suggest_keys_to_allow(site, limit \\ 300)

Queries the events table to fetch the 300 most frequent prop keys for a specific site over the past 6 months, excluding keys that are already allowed.

Types

Link to this type

prop()

View Source

@type prop() :: String.t()

Functions

Link to this function

allow(site, prop_or_props)

View Source

@spec allow(Plausible.Site.t(), [prop()] | prop()) ::
  {:ok, Plausible.Site.t()}
  | {:error, Ecto.Changeset.t()}
  | {:error, :upgrade_required}

Allows a prop key or a list of props keys to be included in ClickHouse queries. Allowing prop keys does not affect ingestion, as we don't want any data to be dropped or lost.

Link to this function

allow_changeset(site, prop_or_props)

View Source

Link to this function

allow_existing_props(site)

View Source

@spec allow_existing_props(Plausible.Site.t()) ::
  {:ok, Plausible.Site.t()} | {:error, :upgrade_required}

Allows the 300 most frequent props keys for a specific site over the past 6 months.

Link to this function

configured?(site)

View Source

Returns whether the site has configured custom props or not.

Link to this function

disallow(site, prop)

View Source

@spec disallow(Plausible.Site.t(), prop()) ::
  {:ok, Plausible.Site.t()} | {:error, Ecto.Changeset.t()}

Removes a previously allowed prop key from the allow list. This means this prop key won't be included in ClickHouse queries. This doesn't drop any ClickHouse data, nor affects ingestion.

Link to this function

internal_keys()

View Source

Lists prop keys used internally.

These props should be allowed by default, and should not be displayed in the props settings page. For example, url is a special prop key used for file downloads and outbound links. It doesn't make sense to remove this prop key from the allow list, or to suggest users to add this prop key.

Link to this function

max_prop_key_length()

View Source

Link to this function

max_prop_value_length()

View Source

Link to this function

max_props()

View Source

Link to this function

suggest_keys_to_allow(site, limit \\ 300)

View Source

@spec suggest_keys_to_allow(Plausible.Site.t(), non_neg_integer()) :: [String.t()]

Queries the events table to fetch the 300 most frequent prop keys for a specific site over the past 6 months, excluding keys that are already allowed.

Plausible.Purge

Deletes data from a site.

Stats are stored on Clickhouse, and unlike other databases data deletion is done asynchronously.

All import tables have MergeTree's deduplication mechanism disabled by setting replicated_deduplication_window from default 100 to 0. When enabled, every insert into a given table is compared against hashes of 100 previous inserts (as complete parts, not concrete rows) and ignored when match is found. The prupose of that mechanism is making inserts of exact same batches idempotent when retrying them shortly after - for instance due to timeout, when the client can't easily tell if previous insert succeeded or not. Deduplication, however, only considers inserts, not mutations. Deletions do not affect stored hashes, so further inserts of parts that were deleted will still be treated as duplicates. That's why this feature is disabled for import tables.

Although deletions are asynchronous, the parts to delete are "remembered", so there's no risk of overlapping deletion causing problems with import following right after it.

IMPORTANT: Deletion requires revision if/when import tables get moved to sharded CH cluster setup. Mutation queries, which have to be run with ON CLUSTER in such setup, dispatch independent queries across shards and those queries can start at different times. This in turn means risk of deletions corrupting data of follow-up inserts in some edge cases. Ideally, imported entries should be unique for a given import

an extra import_id column can be introduced, holding identifier. Last processed import identifier should be stored with other site data and should be used for scoping imported stats queries. No longer used imports can then be safely removed fully asynchronously.

Clickhouse ALTER TABLE ... DELETE Statement

Synchronicity of ALTER Queries

Summary

Functions

delete_imported_stats!(site)

Deletes imported stats from Google Analytics, and clears the stats_start_date field.

delete_native_stats!(site)

Move stats pointers so that no historical stats are available.

reset!(site)

Functions

Link to this function

delete_imported_stats!(site)

View Source

@spec delete_imported_stats!(Plausible.Site.t()) :: :ok

Deletes imported stats from Google Analytics, and clears the stats_start_date field.

Link to this function

delete_native_stats!(site)

View Source

@spec delete_native_stats!(Plausible.Site.t()) :: :ok

Move stats pointers so that no historical stats are available.

Link to this function

reset!(site)

View Source

Plausible.Release

Summary

Functions

configure_ref_inspector()

configure_ua_inspector()

createdb()

migrate()

pending_migrations()

rollback()

seed()

selfhost?()

should_be_first_launch?()

Functions

Link to this function

configure_ref_inspector()

View Source

Link to this function

configure_ua_inspector()

View Source

Link to this function

createdb()

View Source

Link to this function

migrate()

View Source

Link to this function

pending_migrations()

View Source

Link to this function

rollback()

View Source

Link to this function

seed()

View Source

Link to this function

selfhost?()

View Source

@spec selfhost?() :: boolean()

Link to this function

should_be_first_launch?()

View Source

Plausible.Repo

Summary

Functions

aggregate(queryable, aggregate, opts \\ [])

Callback implementation for Ecto.Repo.aggregate/3.

aggregate(queryable, aggregate, field, opts)

Callback implementation for Ecto.Repo.aggregate/4.

all(queryable, opts \\ [])

Callback implementation for Ecto.Repo.all/2.

checked_out?()

Callback implementation for Ecto.Repo.checked_out?/0.

checkout(fun, opts \\ [])

Callback implementation for Ecto.Repo.checkout/2.

child_spec(opts)

config()

Callback implementation for Ecto.Repo.config/0.

default_options(operation)

Callback implementation for Ecto.Repo.default_options/1.

delete(struct, opts \\ [])

Callback implementation for Ecto.Repo.delete/2.

delete!(struct, opts \\ [])

Callback implementation for Ecto.Repo.delete!/2.

delete_all(queryable, opts \\ [])

Callback implementation for Ecto.Repo.delete_all/2.

disconnect_all(interval, opts \\ [])

A convenience function for SQL-based repositories that forces all connections in the pool to disconnect within the given interval.

exists?(queryable, opts \\ [])

Callback implementation for Ecto.Repo.exists?/2.

explain(operation, queryable, opts \\ [])

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.

get(queryable, id, opts \\ [])

Callback implementation for Ecto.Repo.get/3.

get!(queryable, id, opts \\ [])

Callback implementation for Ecto.Repo.get!/3.

get_by(queryable, clauses, opts \\ [])

Callback implementation for Ecto.Repo.get_by/3.

get_by!(queryable, clauses, opts \\ [])

Callback implementation for Ecto.Repo.get_by!/3.

get_dynamic_repo()

Callback implementation for Ecto.Repo.get_dynamic_repo/0.

in_transaction?()

Callback implementation for Ecto.Repo.in_transaction?/0.

insert(struct, opts \\ [])

Callback implementation for Ecto.Repo.insert/2.

insert!(struct, opts \\ [])

Callback implementation for Ecto.Repo.insert!/2.

insert_all(schema_or_source, entries, opts \\ [])

Callback implementation for Ecto.Repo.insert_all/3.

insert_or_update(changeset, opts \\ [])

Callback implementation for Ecto.Repo.insert_or_update/2.

insert_or_update!(changeset, opts \\ [])

Callback implementation for Ecto.Repo.insert_or_update!/2.

load(schema_or_types, data)

Callback implementation for Ecto.Repo.load/2.

one(queryable, opts \\ [])

Callback implementation for Ecto.Repo.one/2.

one!(queryable, opts \\ [])

Callback implementation for Ecto.Repo.one!/2.

paginate(query, params \\ %{}, options \\ [])

preload(struct_or_structs_or_nil, preloads, opts \\ [])

Callback implementation for Ecto.Repo.preload/3.

prepare_query(operation, query, opts)

Callback implementation for Ecto.Repo.prepare_query/3.

put_dynamic_repo(dynamic)

Callback implementation for Ecto.Repo.put_dynamic_repo/1.

query(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given query.

query!(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given query.

query_many(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given multi-result query.

query_many!(sql, params \\ [], opts \\ [])

A convenience function for SQL-based repositories that executes the given multi-result query.

reload(queryable, opts \\ [])

Callback implementation for Ecto.Repo.reload/2.

reload!(queryable, opts \\ [])

Callback implementation for Ecto.Repo.reload!/2.

rollback(value)

Callback implementation for Ecto.Repo.rollback/1.

start_link(opts \\ [])

Callback implementation for Ecto.Repo.start_link/1.

stop(timeout \\ 5000)

Callback implementation for Ecto.Repo.stop/1.

stream(queryable, opts \\ [])

Callback implementation for Ecto.Repo.stream/2.

to_sql(operation, queryable)

A convenience function for SQL-based repositories that translates the given query to SQL.

transaction(fun_or_multi, opts \\ [])

Callback implementation for Ecto.Repo.transaction/2.

update(struct, opts \\ [])

Callback implementation for Ecto.Repo.update/2.

update!(struct, opts \\ [])

Callback implementation for Ecto.Repo.update!/2.

update_all(queryable, updates, opts \\ [])

Callback implementation for Ecto.Repo.update_all/3.

Functions

Link to this function

aggregate(queryable, aggregate, opts \\ [])

View Source

Callback implementation for Ecto.Repo.aggregate/3.

Link to this function

aggregate(queryable, aggregate, field, opts)

View Source

Callback implementation for Ecto.Repo.aggregate/4.

Link to this function

all(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.all/2.

Link to this function

checked_out?()

View Source

Callback implementation for Ecto.Repo.checked_out?/0.

Link to this function

checkout(fun, opts \\ [])

View Source

Callback implementation for Ecto.Repo.checkout/2.

Link to this function

child_spec(opts)

View Source

Link to this function

config()

View Source

Callback implementation for Ecto.Repo.config/0.

Link to this function

default_options(operation)

View Source

Callback implementation for Ecto.Repo.default_options/1.

Link to this function

delete(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete/2.

Link to this function

delete!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete!/2.

Link to this function

delete_all(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.delete_all/2.

Link to this function

disconnect_all(interval, opts \\ [])

View Source

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.

Link to this function

exists?(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.exists?/2.

Link to this function

explain(operation, queryable, opts \\ [])

View Source

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.

Link to this function

get(queryable, id, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get/3.

Link to this function

get!(queryable, id, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get!/3.

Link to this function

get_by(queryable, clauses, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get_by/3.

Link to this function

get_by!(queryable, clauses, opts \\ [])

View Source

Callback implementation for Ecto.Repo.get_by!/3.

Link to this function

get_dynamic_repo()

View Source

Callback implementation for Ecto.Repo.get_dynamic_repo/0.

Link to this function

in_transaction?()

View Source

Callback implementation for Ecto.Repo.in_transaction?/0.

Link to this function

insert(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert/2.

Link to this function

insert!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert!/2.

Link to this function

insert_all(schema_or_source, entries, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_all/3.

Link to this function

insert_or_update(changeset, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_or_update/2.

Link to this function

insert_or_update!(changeset, opts \\ [])

View Source

Callback implementation for Ecto.Repo.insert_or_update!/2.

Link to this function

load(schema_or_types, data)

View Source

Callback implementation for Ecto.Repo.load/2.

Link to this function

one(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.one/2.

Link to this function

one!(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.one!/2.

Link to this function

paginate(query, params \\ %{}, options \\ [])

View Source

Link to this function

preload(struct_or_structs_or_nil, preloads, opts \\ [])

View Source

Callback implementation for Ecto.Repo.preload/3.

Link to this function

prepare_query(operation, query, opts)

View Source

Callback implementation for Ecto.Repo.prepare_query/3.

Link to this function

put_dynamic_repo(dynamic)

View Source

Callback implementation for Ecto.Repo.put_dynamic_repo/1.

Link to this function

query(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given query.

See Ecto.Adapters.SQL.query/4 for more information.

Link to this function

query!(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given query.

See Ecto.Adapters.SQL.query!/4 for more information.

Link to this function

query_many(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given multi-result query.

See Ecto.Adapters.SQL.query_many/4 for more information.

Link to this function

query_many!(sql, params \\ [], opts \\ [])

View Source

A convenience function for SQL-based repositories that executes the given multi-result query.

See Ecto.Adapters.SQL.query_many!/4 for more information.

Link to this function

reload(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.reload/2.

Link to this function

reload!(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.reload!/2.

Link to this function

rollback(value)

View Source

@spec rollback(term()) :: no_return()

Callback implementation for Ecto.Repo.rollback/1.

Link to this function

start_link(opts \\ [])

View Source

Callback implementation for Ecto.Repo.start_link/1.

Link to this function

stop(timeout \\ 5000)

View Source

Callback implementation for Ecto.Repo.stop/1.

Link to this function

stream(queryable, opts \\ [])

View Source

Callback implementation for Ecto.Repo.stream/2.

Link to this function

to_sql(operation, queryable)

View Source

A convenience function for SQL-based repositories that translates the given query to SQL.

See Ecto.Adapters.SQL.to_sql/3 for more information.

Link to this function

transaction(fun_or_multi, opts \\ [])

View Source

Callback implementation for Ecto.Repo.transaction/2.

Link to this function

update(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update/2.

Link to this function

update!(struct, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update!/2.

Link to this function

update_all(queryable, updates, opts \\ [])

View Source

Callback implementation for Ecto.Repo.update_all/3.

Plausible.Sentry.Client

Summary

Functions

child_spec()

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.

post(url, headers, body)

Callback implementation for Sentry.HTTPClient.post/3.

Functions

Link to this function

child_spec()

View Source

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.

Link to this function

post(url, headers, body)

View Source

Callback implementation for Sentry.HTTPClient.post/3.

Plausible.SentryFilter

Sentry callbacks for filtering and grouping events

Summary

Functions

before_send(event)

exclude_exception?(exception, source)

Callback implementation for Sentry.EventFilter.exclude_exception?/2.

Functions

Link to this function

before_send(event)

View Source

@spec before_send(Sentry.Event.t()) :: Sentry.Event.t()

Link to this function

exclude_exception?(exception, source)

View Source

Callback implementation for Sentry.EventFilter.exclude_exception?/2.

Plausible.Session.CacheStore

Summary

Functions

on_event(event, prev_user_id, buffer \\ WriteBuffer)

Functions

Link to this function

on_event(event, prev_user_id, buffer \\ WriteBuffer)

View Source

Plausible.Session.Salts

Summary

Functions

child_spec(arg)

Returns a specification to start this module under a supervisor.

fetch()

rotate()

start_link(opts)

Functions

Link to this function

child_spec(arg)

View Source

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

fetch()

View Source

Link to this function

rotate()

View Source

Link to this function

start_link(opts)

View Source

Plausible.Session.WriteBuffer

Summary

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

flush()

init(buffer)

Callback implementation for GenServer.init/1.

insert(sessions)

start_link(opts)

Functions

Link to this function

child_spec(init_arg)

View Source

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

flush()

View Source

Link to this function

init(buffer)

View Source

Callback implementation for GenServer.init/1.

Link to this function

insert(sessions)

View Source

Link to this function

start_link(opts)

View Source

Plausible.Site

Site schema

Summary

Types

t()

Functions

changeset(site, attrs \\ %{})

crm_changeset(site, attrs)

import_failure(site)

import_success(site)

local_start_date(site)

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

make_private(site)

make_public(site)

remove_imported_data(site)

set_imported_source(site, imported_source)

set_native_stats_start_at(site, val)

set_stats_start_date(site, val)

start_import(site, start_date, end_date, imported_source, status \\ "importing")

tz_offset(site, utc_now \\ DateTime.utc_now())

update_changeset(site, attrs \\ %{}, opts \\ [])

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Site{
  __meta__: term(),
  allowed_event_props: term(),
  conversions_enabled: term(),
  custom_domain: term(),
  domain: term(),
  domain_changed_at: term(),
  domain_changed_from: term(),
  from_cache?: term(),
  funnels_enabled: term(),
  goals: term(),
  google_auth: term(),
  id: term(),
  imported_data: term(),
  ingest_rate_limit_scale_seconds: term(),
  ingest_rate_limit_threshold: term(),
  inserted_at: term(),
  invitations: term(),
  locked: term(),
  members: term(),
  memberships: term(),
  monthly_report: term(),
  native_stats_start_at: term(),
  owner: term(),
  ownership: term(),
  props_enabled: term(),
  public: term(),
  revenue_goals: term(),
  spike_notification: term(),
  stats_start_date: term(),
  timezone: term(),
  updated_at: term(),
  weekly_report: term()
}

Functions

Link to this function

changeset(site, attrs \\ %{})

View Source

Link to this function

crm_changeset(site, attrs)

View Source

Link to this function

import_failure(site)

View Source

Link to this function

import_success(site)

View Source

Link to this function

local_start_date(site)

View Source

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]

Link to this function

make_private(site)

View Source

Link to this function

make_public(site)

View Source

Link to this function

remove_imported_data(site)

View Source

Link to this function

set_imported_source(site, imported_source)

View Source

Link to this function

set_native_stats_start_at(site, val)

View Source

Link to this function

set_stats_start_date(site, val)

View Source

Link to this function

start_import(site, start_date, end_date, imported_source, status \\ "importing")

View Source

Link to this function

tz_offset(site, utc_now \\ DateTime.utc_now())

View Source

Link to this function

update_changeset(site, attrs \\ %{}, opts \\ [])

View Source

Plausible.Site.Cache

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.

Summary

Types

t()

Functions

child_spec(opts)

enabled?()

get(domain, opts \\ [])

get_site_id(domain, opts \\ [])

hit_rate(cache_name \\ :sites_by_domain)

merge(new_items, opts \\ [])

name()

ready?(cache_name \\ :sites_by_domain)

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.

refresh_all(opts \\ [])

refresh_updated_recently(opts \\ [])

size(cache_name \\ :sites_by_domain)

telemetry_event_refresh(cache_name \\ :sites_by_domain, mode)

touch_site!(site, now)

Types

Link to this type

t()

View Source

@type t() :: Plausible.Site.t()

Functions

Link to this function

child_spec(opts)

View Source

@spec child_spec(Keyword.t()) :: Supervisor.child_spec()

Link to this function

enabled?()

View Source

Link to this function

get(domain, opts \\ [])

View Source

@spec get(String.t(), Keyword.t()) :: t() | nil

Link to this function

get_site_id(domain, opts \\ [])

View Source

@spec get_site_id(String.t(), Keyword.t()) :: pos_integer() | nil

Link to this function

hit_rate(cache_name \\ :sites_by_domain)

View Source

Link to this function

merge(new_items, opts \\ [])

View Source

@spec merge(new_items :: [Plausible.Site.t()], opts :: Keyword.t()) :: :ok

Link to this function

name()

View Source

@spec name() :: atom()

Link to this function

ready?(cache_name \\ :sites_by_domain)

View Source

@spec ready?(atom()) :: boolean()

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.

Link to this function

refresh_all(opts \\ [])

View Source

@spec refresh_all(Keyword.t()) :: :ok

Link to this function

refresh_updated_recently(opts \\ [])

View Source

@spec refresh_updated_recently(Keyword.t()) :: :ok

Link to this function

size(cache_name \\ :sites_by_domain)

View Source

Link to this function

telemetry_event_refresh(cache_name \\ :sites_by_domain, mode)

View Source

@spec telemetry_event_refresh(atom(), atom()) :: [atom()]

Link to this function

touch_site!(site, now)

View Source

@spec touch_site!(Plausible.Site.t(), DateTime.t()) :: Plausible.Site.t()

Plausible.Site.Cache.Warmer

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.

Summary

Functions

child_spec(opts)

interval()

Functions

Link to this function

child_spec(opts)

View Source

@spec child_spec(Keyword.t()) :: Supervisor.child_spec() | :ignore

Link to this function

interval()

View Source

@spec interval() :: pos_integer()

Plausible.Site.Cache.Warmer.All

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.

Summary

Functions

child_spec(opts)

See Plausible.Site.Cache.Warmer.child_spec/1.

Functions

Link to this function

child_spec(opts)

View Source

See Plausible.Site.Cache.Warmer.child_spec/1.

Plausible.Site.Cache.Warmer.RecentlyUpdated

A Cache.Warmer adapter that only refreshes the Cache with recently updated sites every 30 seconds.

Summary

Functions

child_spec(opts)

Functions

Link to this function

child_spec(opts)

View Source

@spec child_spec(Keyword.t()) :: Supervisor.child_spec() | :ignore

Plausible.Site.CustomDomain

Plausible.Site.Domain

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.

Summary

Functions

change(site, new_domain, opts \\ [])

expire_change_transitions(expire_threshold_hours \\ 72)

Functions

Link to this function

change(site, new_domain, opts \\ [])

View Source

@spec change(Plausible.Site.t(), String.t(), Keyword.t()) ::
  {:ok, Plausible.Site.t()} | {:error, Ecto.Changeset.t()}

Link to this function

expire_change_transitions(expire_threshold_hours \\ 72)

View Source

@spec expire_change_transitions(integer()) :: {:ok, non_neg_integer()}

Plausible.Site.GateKeeper

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

Summary

Types

policy()

t()

Functions

check(domain, opts \\ [])

key(domain)

Types

Link to this type

policy()

View Source

@type policy() :: :allow | :not_found | :block | :throttle

Link to this type

t()

View Source

@type t() :: {:allow, Plausible.Site.t()} | {:deny, policy()}

Functions

Link to this function

check(domain, opts \\ [])

View Source

@spec check(String.t(), Keyword.t()) :: t()

Link to this function

key(domain)

View Source

@spec key(String.t()) :: String.t()

Plausible.Site.GoogleAuth

Summary

Functions

changeset(auth, attrs \\ %{})

set_property(auth, attrs \\ %{})

Functions

Link to this function

changeset(auth, attrs \\ %{})

View Source

Link to this function

set_property(auth, attrs \\ %{})

View Source

Plausible.Site.ImportedData

Embedded schema for Google Analytics imports

Plausible.Site.Membership

Summary

Types

t()

Functions

new(site, user)

set_role(changeset, role)

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Site.Membership{
  __meta__: term(),
  id: term(),
  inserted_at: term(),
  role: term(),
  site: term(),
  site_id: term(),
  updated_at: term(),
  user: term(),
  user_id: term()
}

Functions

Link to this function

new(site, user)

View Source

Link to this function

set_role(changeset, role)

View Source

Plausible.Site.Memberships

API for site memberships and invitations

Summary

Functions

accept_invitation(invitation_id, user)

See Plausible.Site.Memberships.AcceptInvitation.accept_invitation/2.

any?(user)

has_any_invitations?(email)

reject_invitation(invitation_id, user)

See Plausible.Site.Memberships.RejectInvitation.reject_invitation/2.

remove_invitation(invitation_id, site)

See Plausible.Site.Memberships.RemoveInvitation.remove_invitation/2.

transfer_ownership(site, user)

See Plausible.Site.Memberships.AcceptInvitation.transfer_ownership/2.

Functions

Link to this function

accept_invitation(invitation_id, user)

View Source

See Plausible.Site.Memberships.AcceptInvitation.accept_invitation/2.

Link to this function

any?(user)

View Source

@spec any?(Plausible.Auth.User.t()) :: boolean()

Link to this function

has_any_invitations?(email)

View Source

@spec has_any_invitations?(String.t()) :: boolean()

Link to this function

reject_invitation(invitation_id, user)

View Source

See Plausible.Site.Memberships.RejectInvitation.reject_invitation/2.

Link to this function

remove_invitation(invitation_id, site)

View Source

See Plausible.Site.Memberships.RemoveInvitation.remove_invitation/2.

Link to this function

transfer_ownership(site, user)

View Source

See Plausible.Site.Memberships.AcceptInvitation.transfer_ownership/2.

Plausible.Site.Memberships.AcceptInvitation

Service for accepting invitations, including ownership transfers.

Accepting invitation accounts for the fact that it's possible that accepting user has an existing membership for the site and acts permissively to not unnecessarily disrupt the flow while also maintaining integrity of site memberships. This also applies to cases where users update their email address between issuing the invitation and accepting it.

Summary

Functions

accept_invitation(invitation_id, user, opts \\ [])

transfer_ownership(site, user, opts \\ [])

Functions

Link to this function

accept_invitation(invitation_id, user, opts \\ [])

View Source

@spec accept_invitation(String.t(), Plausible.Auth.User.t(), Keyword.t()) ::
  {:ok, Plausible.Site.Membership.t()}
  | {:error, :invitation_not_found | Ecto.Changeset.t()}

Link to this function

transfer_ownership(site, user, opts \\ [])

View Source

@spec transfer_ownership(Plausible.Site.t(), Plausible.Auth.User.t(), Keyword.t()) ::
  {:ok, Plausible.Site.Membership.t()} | {:error, Ecto.Changeset.t()}

Plausible.Site.Memberships.RejectInvitation

Service for rejecting invitations.

Summary

Functions

reject_invitation(invitation_id, user)

Functions

Link to this function

reject_invitation(invitation_id, user)

View Source

@spec reject_invitation(String.t(), Plausible.Auth.User.t()) ::
  {:ok, Plausible.Auth.Invitation.t()} | {:error, :invitation_not_found}

Plausible.Site.Memberships.RemoveInvitation

Service for removing invitations.

Summary

Functions

remove_invitation(invitation_id, site)

Functions

Link to this function

remove_invitation(invitation_id, site)

View Source

@spec remove_invitation(String.t(), Plausible.Site.t()) ::
  {:ok, Plausible.Auth.Invitation.t()} | {:error, :invitation_not_found}

Plausible.Site.MonthlyReport

Summary

Functions

add_recipient(report, recipient)

changeset(settings, attrs \\ %{})

remove_recipient(report, recipient)

Functions

Link to this function

add_recipient(report, recipient)

View Source

Link to this function

changeset(settings, attrs \\ %{})

View Source

Link to this function

remove_recipient(report, recipient)

View Source

Plausible.Site.Removal

A site deletion service stub.

Summary

Functions

run(domain)

Functions

Link to this function

run(domain)

View Source

@spec run(String.t()) :: {:ok, map()}

Plausible.Site.SharedLink

Summary

Types

t()

Functions

changeset(link, attrs \\ %{})

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Site.SharedLink{
  __meta__: term(),
  id: term(),
  inserted_at: term(),
  name: term(),
  password: term(),
  password_hash: term(),
  site: term(),
  site_id: term(),
  slug: term(),
  updated_at: term()
}

Functions

Link to this function

changeset(link, attrs \\ %{})

View Source

Plausible.Site.SpikeNotification

Summary

Functions

add_recipient(schema, recipient)

changeset(schema, attrs)

remove_recipient(schema, recipient)

was_sent(schema)

Functions

Link to this function

add_recipient(schema, recipient)

View Source

Link to this function

changeset(schema, attrs)

View Source

Link to this function

remove_recipient(schema, recipient)

View Source

Link to this function

was_sent(schema)

View Source

Plausible.Site.WeeklyReport

Summary

Functions

add_recipient(report, recipient)

changeset(settings, attrs \\ %{})

remove_recipient(report, recipient)

Functions

Link to this function

add_recipient(report, recipient)

View Source

Link to this function

changeset(settings, attrs \\ %{})

View Source

Link to this function

remove_recipient(report, recipient)

View Source

Plausible.SiteAdmin

Summary

Functions

create_changeset(schema, attrs)

custom_index_query(conn, schema, query)

form_fields(_)

get_struct_fields(module)

index(_)

list_actions(conn)

ordering(schema)

search_fields(schema)

update_changeset(schema, attrs)

Functions

Link to this function

create_changeset(schema, attrs)

View Source

Link to this function

custom_index_query(conn, schema, query)

View Source

Link to this function

form_fields(_)

View Source

Link to this function

get_struct_fields(module)

View Source

Link to this function

index(_)

View Source

Link to this function

list_actions(conn)

View Source

Link to this function

ordering(schema)

View Source

Link to this function

search_fields(schema)

View Source

Link to this function

update_changeset(schema, attrs)

View Source

Plausible.Sites

Summary

Types

invite_error()

Functions

bulk_transfer_ownership(sites, inviter, invitee_email, opts \\ [])

bulk_transfer_ownership_direct(sites, new_owner)

create(user, params)

create_shared_link(site, name, password \\ nil)

get_by_domain(domain)

get_by_domain!(domain)

get_for_user(user_id, domain, roles \\ [:owner, :admin, :viewer])

get_for_user!(user_id, domain, roles \\ [:owner, :admin, :viewer])

has_admin_access?(user_id, site)

has_goals?(site)

has_stats?(site)

invite(site, inviter, invitee_email, role)

Invites a new team member to the given site. Returns a %Plausible.Auth.Invitation{} struct and sends the invitee an email to accept this invitation.

is_member?(user_id, site)

locked?(site)

owned_site_ids(user)

owned_sites_count(user)

owned_sites_domains(user)

role(user_id, site)

shared_link_url(site, link)

stats_start_date(site)

Returns the date of the first event of the given site, or nil if the site does not have stats yet.

Types

Link to this type

invite_error()

View Source

@type invite_error() ::
  Ecto.Changeset.t()
  | :already_a_member
  | :transfer_to_self
  | {:over_limit, non_neg_integer()}
  | :forbidden

Functions

Link to this function

bulk_transfer_ownership(sites, inviter, invitee_email, opts \\ [])

View Source

@spec bulk_transfer_ownership(
  [Plausible.Site.t()],
  Plausible.Auth.User.t(),
  String.t(),
  Keyword.t()
) :: {:ok, [Plausible.Auth.Invitation.t()]} | {:error, invite_error()}

Link to this function

bulk_transfer_ownership_direct(sites, new_owner)

View Source

@spec bulk_transfer_ownership_direct([Plausible.Site.t()], Plausible.Auth.User.t()) ::
  {:ok, [Plausible.Site.Membership.t()]} | {:error, invite_error()}

Link to this function

create(user, params)

View Source

Link to this function

create_shared_link(site, name, password \\ nil)

View Source

Link to this function

get_by_domain(domain)

View Source

Link to this function

get_by_domain!(domain)

View Source

Link to this function

get_for_user(user_id, domain, roles \\ [:owner, :admin, :viewer])

View Source

Link to this function

get_for_user!(user_id, domain, roles \\ [:owner, :admin, :viewer])

View Source

Link to this function

has_admin_access?(user_id, site)

View Source

Link to this function

has_goals?(site)

View Source

Link to this function

has_stats?(site)

View Source

Link to this function

invite(site, inviter, invitee_email, role)

View Source

@spec invite(Plausible.Site.t(), Plausible.Auth.User.t(), String.t(), atom()) ::
  {:ok, Plausible.Auth.Invitation.t()} | {:error, invite_error()}

Invites a new team member to the given site. Returns a %Plausible.Auth.Invitation{} struct and sends the invitee an email to accept this invitation.

The inviter must have enough permissions to invite the new team member, otherwise this function returns {:error, :forbidden}.

If the new team member role is :owner, this function handles the invitation as an ownership transfer and requires the inviter to be the owner of the site.

Link to this function

is_member?(user_id, site)

View Source

Link to this function

locked?(site)

View Source

Link to this function

owned_site_ids(user)

View Source

Link to this function

owned_sites_count(user)

View Source

Link to this function

owned_sites_domains(user)

View Source

Link to this function

role(user_id, site)

View Source

Link to this function

shared_link_url(site, link)

View Source

Link to this function

stats_start_date(site)

View Source

@spec stats_start_date(Plausible.Site.t()) :: Date.t() | nil

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.

Plausible.Stats

Summary

Functions

aggregate(site, query, metrics)

breakdown(site, query, prop, metrics, pagination)

current_visitors(site)

filter_suggestions(site, query, filter_name, filter_search)

funnel(site, query, funnel)

timeseries(site, query, metrics)

Functions

Link to this function

aggregate(site, query, metrics)

View Source

Link to this function

breakdown(site, query, prop, metrics, pagination)

View Source

Link to this function

current_visitors(site)

View Source

Link to this function

filter_suggestions(site, query, filter_name, filter_search)

View Source

Link to this function

funnel(site, query, funnel)

View Source

Link to this function

timeseries(site, query, metrics)

View Source

Plausible.Stats.Aggregate

Summary

Functions

aggregate(site, query, metrics)

Functions

Link to this function

aggregate(site, query, metrics)

View Source

Plausible.Stats.Base

Summary

Functions

apply_entry_prop_filter(sessions_q, prop_name, arg3)

base_event_query(site, query)

filter_by_entry_props(sessions_q, query)

filter_converted_sessions(db_query, site, query)

page_regex(expr)

query_events(site, query)

query_sessions(site, query)

select_event_metrics(q, list)

select_session_metrics(q, list, query)

utc_boundaries(query, site)

Functions

Link to this function

apply_entry_prop_filter(sessions_q, prop_name, arg3)

View Source

Link to this function

base_event_query(site, query)

View Source

Link to this function

filter_by_entry_props(sessions_q, query)

View Source

Link to this function

filter_converted_sessions(db_query, site, query)

View Source

Link to this function

page_regex(expr)

View Source

Link to this function

query_events(site, query)

View Source

Link to this function

query_sessions(site, query)

View Source

Link to this function

select_event_metrics(q, list)

View Source

Link to this function

select_session_metrics(q, list, query)

View Source

Link to this function

utc_boundaries(query, site)

View Source

Plausible.Stats.Breakdown

Summary

Functions

breakdown(site, query, property, metrics, pagination)

Functions

Link to this function

breakdown(site, query, property, metrics, pagination)

View Source

Plausible.Stats.Clickhouse

Summary

Functions

current_visitors(site, query)

has_pageviews?(site)

imported_pageview_count(site)

last_24h_visitors(sites)

pageview_start_date_local(site)

top_sources(site, query, limit, page, show_noref \\ false, include_details)

usage_breakdown(domains_or_site_ids)

usage_breakdown(domains, date_range)

Functions

Link to this function

current_visitors(site, query)

View Source

Link to this function

has_pageviews?(site)

View Source

Link to this function

imported_pageview_count(site)

View Source

Link to this function

last_24h_visitors(sites)

View Source

Link to this function

pageview_start_date_local(site)

View Source

@spec pageview_start_date_local(Plausible.Site.t()) :: Date.t() | nil

Link to this function

top_sources(site, query, limit, page, show_noref \\ false, include_details)

View Source

Link to this function

usage_breakdown(domains_or_site_ids)

View Source

Link to this function

usage_breakdown(domains, date_range)

View Source

Plausible.Stats.Compare

Summary

Functions

calculate_change(metric, old_stats, new_stats)

Functions

Link to this function

calculate_change(metric, old_stats, new_stats)

View Source

Plausible.Stats.Comparisons

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.

Summary

Types

mode()

Functions

compare(site, source_query, mode, opts \\ [])

Generates a comparison query based on the source query and comparison mode.

Types

Link to this type

mode()

View Source

@type mode() :: String.t() | nil

Functions

Link to this function

compare(site, source_query, mode, opts \\ [])

View Source

@spec compare(Plausible.Site.t(), Plausible.Stats.Query.t(), mode(), [option()]) ::
  {:ok, Plausible.Stats.Query.t()}
  | {:error, :not_supported}
  | {:error, :invalid_dates}

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.

Plausible.Stats.CurrentVisitors

Summary

Functions

current_visitors(site)

Functions

Link to this function

current_visitors(site)

View Source

Plausible.Stats.CustomProps

Module for querying user defined 'custom properties'.

Summary

Functions

fetch_prop_names(site, query)

maybe_allowed_props_only(q, allowed_props)

props_for_all_event_names(site, query)

Returns a breakdown of event names with all existing custom properties for each event name.

Functions

Link to this function

fetch_prop_names(site, query)

View Source

Link to this function

maybe_allowed_props_only(q, allowed_props)

View Source

Link to this function

props_for_all_event_names(site, query)

View Source

Returns a breakdown of event names with all existing custom properties for each event name.

Plausible.Stats.FilterParser

A module for parsing filters used in stat queries.

Summary

Functions

parse_filters(filters)

Parses different filter formats.

Functions

Link to this function

parse_filters(filters)

View Source

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)
%{}

Plausible.Stats.FilterSuggestions

Summary

Functions

filter_suggestions(site, query, filter_name, filter_search)

Functions

Link to this function

filter_suggestions(site, query, filter_name, filter_search)

View Source

Plausible.Stats.Filters

Summary

Functions

add_prefix(query)

visit_props()

Functions

Link to this function

add_prefix(query)

View Source

Link to this function

visit_props()

View Source

Plausible.Stats.Fragments

Summary

Functions

bounce_rate()

coalesce_string(fieldA, fieldB)

sample_percent()

to_timezone(date, timezone)

Converts time or date and time to the specified timezone.

total()

uniq(user_id)

visit_duration()

weekstart_not_before(date, not_before)

Returns the weekstart for date. If the weekstart is before the not_before boundary, not_before is returned.

weekstart_not_before(date, not_before, timezone)

Same as Plausible.Stats.Fragments.weekstart_not_before/2 but converts dates to the specified timezone.

Functions

Link to this macro

bounce_rate()

View Source (macro)

Link to this macro

coalesce_string(fieldA, fieldB)

View Source (macro)

Link to this macro

sample_percent()

View Source (macro)

Link to this macro

to_timezone(date, timezone)

View Source (macro)

Converts time or date and time to the specified timezone.

Reference: https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions/#totimezone

Link to this macro

total()

View Source (macro)

Link to this macro

uniq(user_id)

View Source (macro)

Link to this macro

visit_duration()

View Source (macro)

Link to this macro

weekstart_not_before(date, not_before)

View Source (macro)

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]

Link to this macro

weekstart_not_before(date, not_before, timezone)

View Source (macro)

Same as Plausible.Stats.Fragments.weekstart_not_before/2 but converts dates to the specified timezone.

Plausible.Stats.Funnel

Module responsible for funnel evaluation, i.e. building and executing ClickHouse funnel query based on Plausible.Funnel definition.

Summary

Functions

funnel(site, query, funnel_id)

Functions

Link to this function

funnel(site, query, funnel_id)

View Source

@spec funnel(
  Plausible.Site.t(),
  Plausible.Stats.Query.t(),
  Plausible.Funnel.t() | pos_integer()
) ::
  {:ok, map()} | {:error, :funnel_not_found}

Plausible.Stats.Imported

Summary

Functions

merge_imported(q, site, query, property, metrics)

merge_imported_timeseries(native_q, site, query, metrics)

Functions

Link to this function

merge_imported(q, site, query, property, metrics)

View Source

Link to this function

merge_imported_timeseries(native_q, site, query, metrics)

View Source

Plausible.Stats.Interval

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.

Summary

Types

opt()

opts()

t()

Functions

default_for_date_range(range)

Returns the suggested interval for the given Date.Range struct.

default_for_period(period)

Returns the suggested interval for the given time period.

list()

valid?(interval)

valid_by_period(opts \\ [])

valid_for_period?(period, interval, opts \\ [])

Returns whether the given interval is valid for a time period.

Types

Link to this type

opt()

View Source

@type opt() :: {:site, Plausible.Site.t()} | {:from, Date.t()}

Link to this type

opts()

View Source

@type opts() :: [opt()]

Link to this type

t()

View Source

@type t() :: String.t()

Functions

Link to this function

default_for_date_range(range)

View Source

@spec default_for_date_range(Date.Range.t()) :: t()

Returns the suggested interval for the given Date.Range struct.

Link to this function

default_for_period(period)

View Source

@spec default_for_period(period()) :: t()

Returns the suggested interval for the given time period.

Link to this function

list()

View Source

@spec list() :: [t()]

Link to this function

valid?(interval)

View Source

@spec valid?(term()) :: boolean()

Link to this function

valid_by_period(opts \\ [])

View Source

@spec valid_by_period(opts()) :: map()

Link to this function

valid_for_period?(period, interval, opts \\ [])

View Source

@spec valid_for_period?(period(), t(), opts()) :: boolean()

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.

There are two dynamic states:

custom period is only applicable with month or week intervals, if the opts[:from] and opts[:to] range difference exceeds 12 months

all period's interval options depend on particular site's stats_start_date

daily interval is excluded if the all-time range exceeds 12 months

Plausible.Stats.Props

Summary

Functions

event_props()

valid_prop?(prop)

Functions

Link to this function

event_props()

View Source

Link to this function

valid_prop?(prop)

View Source

Plausible.Stats.Query

Summary

Types

t()

Functions

from(site, params)

get_filter_by_prefix(query, prefix)

has_event_filters?(query)

include_imported?(query, site, requested?)

put_filter(query, key, val)

remove_event_filters(query, opts)

trace(query)

Types

Link to this type

t()

View Source

@type t() :: %Plausible.Stats.Query{
  date_range: term(),
  filters: term(),
  imported_data_requested: term(),
  include_imported: term(),
  interval: term(),
  period: term(),
  sample_threshold: term()
}

Functions

Link to this function

from(site, params)

View Source

Link to this function

get_filter_by_prefix(query, prefix)

View Source

Link to this function

has_event_filters?(query)

View Source

Link to this function

include_imported?(query, site, requested?)

View Source

@spec include_imported?(t(), Plausible.Site.t(), boolean()) :: boolean()

Link to this function

put_filter(query, key, val)

View Source

Link to this function

remove_event_filters(query, opts)

View Source

Link to this function

trace(query)

View Source

@spec trace(%Plausible.Stats.Query{
  date_range: term(),
  filters: term(),
  imported_data_requested: term(),
  include_imported: term(),
  interval: term(),
  period: term(),
  sample_threshold: term()
}) :: %Plausible.Stats.Query{
  date_range: term(),
  filters: term(),
  imported_data_requested: term(),
  include_imported: term(),
  interval: term(),
  period: term(),
  sample_threshold: term()
}

Plausible.Stats.Timeseries

Summary

Types

results()

Functions

timeseries(site, query, metrics)

Types

Link to this type

results()

View Source

@type results() :: [%{:date => Date.t(), required(metric()) => value()}, ...]

Functions

Link to this function

timeseries(site, query, metrics)

View Source

Plausible.Stats.Util

Utilities for modifying stat results

Summary

Functions

cast_revenue_metrics_to_money(results, revenue_goals)

get_revenue_tracking_currency(site, query, metrics)

Returns the common currency for the goal filters in a query. If there are no goal filters, multiple currencies or the site owner does not have access to revenue goals, nil is returned and revenue metrics are dropped.

remove_internal_visits_metric(result)

remove_internal_visits_metric(results, metrics)

__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.

Functions

Link to this function

cast_revenue_metrics_to_money(results, revenue_goals)

View Source

Link to this function

get_revenue_tracking_currency(site, query, metrics)

View Source

@spec get_revenue_tracking_currency(Plausible.Site.t(), Plausible.Stats.Query.t(), [
  atom()
]) ::
  {atom() | nil, [atom()]}

Returns the common currency for the goal filters in a query. If there are no goal filters, multiple currencies or the site owner does not have access to revenue goals, 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.

Link to this function

remove_internal_visits_metric(result)

View Source

Link to this function

remove_internal_visits_metric(results, metrics)

View Source

__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.

Plausible.Test.Support.HTML

Floki wrappers to help make assertions about HTML/DOM structures

Summary

Functions

class_of_element(html, element)

element_exists?(html, selector)

find(html, value)

form_exists?(html, action_path)

name_of(element)

submit_button(html, form)

text(element)

text_of_attr(element, attr)

text_of_element(html, element)

Functions

Link to this function

class_of_element(html, element)

View Source

Link to this function

element_exists?(html, selector)

View Source

Link to this function

find(html, value)

View Source

Link to this function

form_exists?(html, action_path)

View Source

Link to this function

name_of(element)

View Source

Link to this function

submit_button(html, form)

View Source

Link to this function

text(element)

View Source

Link to this function

text_of_attr(element, attr)

View Source

Link to this function

text_of_element(html, element)

View Source

Plausible.Test.Support.HTTPMocker

Currently only supports post request, it's a drop-in replacement for our exvcr usage that wasn't ever needed (e.g. we had no way to re-record the cassettes anyway).

Plausible.TestUtils

Summary

Functions

add_imported_data(map)

await_clickhouse_count(query, expected)

create_api_key(map)

create_events(events)

create_new_site(map)

create_pageviews(pageviews)

create_sessions(sessions)

create_site(map)

create_user(_)

eventually(expectation, wait_time_ms \\ 50, retries \\ 10)

init_session(conn)

log_in(map)

patch_env(env_key, value)

populate_stats(events)

populate_stats(site, events)

random_ip()

relative_time(shifts)

setup_patch_env(env_key, value)

to_naive_truncate(dt)

use_api_key(map)

Functions

Link to this function

add_imported_data(map)

View Source

Link to this function

await_clickhouse_count(query, expected)

View Source

Link to this function

create_api_key(map)

View Source

Link to this function

create_events(events)

View Source

Link to this function

create_new_site(map)

View Source

Link to this function

create_pageviews(pageviews)

View Source

Link to this function

create_sessions(sessions)

View Source

Link to this function

create_site(map)

View Source

Link to this function

create_user(_)

View Source

Link to this function

eventually(expectation, wait_time_ms \\ 50, retries \\ 10)

View Source

Link to this function

init_session(conn)

View Source

Link to this function

log_in(map)

View Source

Link to this macro

patch_env(env_key, value)

View Source (macro)

Link to this function

populate_stats(events)

View Source

Link to this function

populate_stats(site, events)

View Source

Link to this function

random_ip()

View Source

Link to this function

relative_time(shifts)

View Source

Link to this macro

setup_patch_env(env_key, value)

View Source (macro)

Link to this function

to_naive_truncate(dt)

View Source

Link to this function

use_api_key(map)

View Source

Plausible.Themes

Summary

Functions

options()

Functions

Link to this function

options()

View Source

Plausible.Timezones

Summary

Functions

options(now \\ DateTime.utc_now())

Functions

Link to this function

options(now \\ DateTime.utc_now())

View Source

@spec options(DateTime.t()) :: [key: String.t(), value: String.t(), offset: integer()]

Plausible.Users

User context

Summary

Functions

has_email_code?(user)

with_subscription(user)

Functions

Link to this function

has_email_code?(user)

View Source

@spec has_email_code?(Plausible.Auth.User.t()) :: boolean()

Link to this function

with_subscription(user)

View Source

Plausible.Workers.CheckUsage

Summary

Functions

check_enterprise_subscriber(subscriber, billing_mod)

day_of_month(date)

last_day_of_month(day)

least(left, right)

yesterday()

Functions

Link to this function

check_enterprise_subscriber(subscriber, billing_mod)

View Source

Link to this macro

day_of_month(date)

View Source (macro)

Link to this macro

last_day_of_month(day)

View Source (macro)

Link to this macro

least(left, right)

View Source (macro)

Link to this macro

yesterday()

View Source (macro)

Plausible.Workers.CleanInvitations

Plausible.Workers.ExpireDomainChangeTransitions

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.

Plausible.Workers.ImportGoogleAnalytics

Summary

Functions

import_failed(site)

Functions

Link to this function

import_failed(site)

View Source

Plausible.Workers.LockSites

Plausible.Workers.NotifyAnnualRenewal

Summary

Functions

perform(job)

Sends a notification at most 7 days and at least 1 day before the renewal of an annual subscription

Functions

Link to this function

perform(job)

View Source

Sends a notification at most 7 days and at least 1 day before the renewal of an annual subscription

Plausible.Workers.RotateSalts

Plausible.Workers.ScheduleEmailReports

Summary

Functions

first_of_month_9am(timezone)

monday_9am(timezone)

perform(job)

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.

Functions

Link to this function

first_of_month_9am(timezone)

View Source

Link to this function

monday_9am(timezone)

View Source

Link to this function

perform(job)

View Source

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.

Plausible.Workers.SendCheckStatsEmails

Plausible.Workers.SendEmailReport

Plausible.Workers.SendSiteSetupEmails

Plausible.Workers.SendTrialNotifications

Plausible.Workers.SpikeNotifier

PlausibleWeb

Summary

Functions

__using__(which)

When used, dispatch to the appropriate controller/view/etc.

channel()

controller()

open_api_schema()

plugins_api_controller()

plugins_api_view()

router()

view()

Functions

Link to this macro

__using__(which)

View Source (macro)

When used, dispatch to the appropriate controller/view/etc.

Link to this function

channel()

View Source

Link to this function

controller()

View Source

Link to this function

open_api_schema()

View Source

Link to this function

plugins_api_controller()

View Source

Link to this function

plugins_api_view()

View Source

Link to this function

router()

View Source

Link to this function

view()

View Source

PlausibleWeb.Api.ExternalController

Summary

Functions

error(conn, params)

event(conn, params)

health(conn, params)

info(conn, params)

Functions

Link to this function

error(conn, params)

View Source

Link to this function

event(conn, params)

View Source

Link to this function

health(conn, params)

View Source

Link to this function

info(conn, params)

View Source

PlausibleWeb.Api.ExternalSitesController

Summary

Functions

create_site(conn, params)

delete_goal(conn, params)

delete_site(conn, map)

find_or_create_goal(conn, params)

find_or_create_shared_link(conn, params)

get_site(conn, map)

update_site(conn, params)

Functions

Link to this function

create_site(conn, params)

View Source

Link to this function

delete_goal(conn, params)

View Source

Link to this function

delete_site(conn, map)

View Source

Link to this function

find_or_create_goal(conn, params)

View Source

Link to this function

find_or_create_shared_link(conn, params)

View Source

Link to this function

get_site(conn, map)

View Source

Link to this function

update_site(conn, params)

View Source

PlausibleWeb.Api.ExternalStatsController

Summary

Functions

aggregate(conn, params)

breakdown(conn, params)

realtime_visitors(conn, params)

timeseries(conn, params)

Functions

Link to this function

aggregate(conn, params)

View Source

Link to this function

breakdown(conn, params)

View Source

Link to this function

realtime_visitors(conn, params)

View Source

Link to this function

timeseries(conn, params)

View Source

PlausibleWeb.Api.Helpers

Summary

Functions

bad_request(conn, msg)

not_found(conn, msg)

payment_required(conn, msg)

too_many_requests(conn, msg)

unauthorized(conn, msg)

Functions

Link to this function

bad_request(conn, msg)

View Source

Link to this function

not_found(conn, msg)

View Source

Link to this function

payment_required(conn, msg)

View Source

Link to this function

too_many_requests(conn, msg)

View Source

Link to this function

unauthorized(conn, msg)

View Source

PlausibleWeb.Api.InternalController

Summary

Functions

disable_feature(conn, map)

domain_status(conn, map)

sites(conn, params)

Functions

Link to this function

disable_feature(conn, map)

View Source

Link to this function

domain_status(conn, map)

View Source

Link to this function

sites(conn, params)

View Source

PlausibleWeb.Api.PaddleController

Summary

Functions

verified_signature?(params)

verify_signature(conn, opts)

webhook(conn, params)

Functions

Link to this function

verified_signature?(params)

View Source

Link to this function

verify_signature(conn, opts)

View Source

Link to this function

webhook(conn, params)

View Source

PlausibleWeb.Api.StatsController

Summary

Functions

all_custom_prop_values(conn, params)

browser_versions(conn, params)

browsers(conn, params)

cities(conn, params)

conversions(conn, params)

countries(conn, params)

current_visitors(conn, _)

custom_prop_values(conn, params)

entry_pages(conn, params)

exit_pages(conn, params)

filter_suggestions(conn, params)

funnel(conn, params)

main_graph(conn, params)

Returns a time-series based on given parameters.

operating_system_versions(conn, params)

operating_systems(conn, params)

pages(conn, params)

referrer_drilldown(conn, params)

referrers(conn, params)

regions(conn, params)

screen_sizes(conn, params)

sources(conn, params)

top_stats(conn, params)

utm_campaigns(conn, params)

utm_contents(conn, params)

utm_mediums(conn, params)

utm_sources(conn, params)

utm_terms(conn, params)

Functions

Link to this function

all_custom_prop_values(conn, params)

View Source

Link to this function

browser_versions(conn, params)

View Source

Link to this function

browsers(conn, params)

View Source

Link to this function

cities(conn, params)

View Source

Link to this function

conversions(conn, params)

View Source

Link to this function

countries(conn, params)

View Source

Link to this function

current_visitors(conn, _)

View Source

Link to this function

custom_prop_values(conn, params)

View Source

Link to this function

entry_pages(conn, params)

View Source

Link to this function

exit_pages(conn, params)

View Source

Link to this function

filter_suggestions(conn, params)

View Source

Link to this function

funnel(conn, params)

View Source

Link to this function

main_graph(conn, params)

View Source

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
}

Link to this function

operating_system_versions(conn, params)

View Source

Link to this function

operating_systems(conn, params)

View Source

Link to this function

pages(conn, params)

View Source

Link to this function

referrer_drilldown(conn, params)

View Source

Link to this function

referrers(conn, params)

View Source

Link to this function

regions(conn, params)

View Source

Link to this function

screen_sizes(conn, params)

View Source

Link to this function

sources(conn, params)

View Source

Link to this function

top_stats(conn, params)

View Source

Link to this function

utm_campaigns(conn, params)

View Source

Link to this function

utm_contents(conn, params)

View Source

Link to this function

utm_mediums(conn, params)

View Source

Link to this function

utm_sources(conn, params)

View Source

Link to this function

utm_terms(conn, params)

View Source

PlausibleWeb.AuthController

Summary

Functions

activate(conn, map)

activate_form(conn, params)

cancel_update_email(conn, params)

create_api_key(conn, map)

delete_api_key(conn, map)

delete_me(conn, params)

google_auth_callback(conn, params)

login(conn, map)

login_form(conn, params)

logout(conn, params)

new_api_key(conn, params)

password_reset(conn, params)

password_reset_form(conn, params)

password_reset_request(conn, params)

password_reset_request_form(conn, _)

register(conn, map)

register_from_invitation(conn, map)

request_activation_code(conn, params)

save_settings(conn, map)

update_email(conn, map)

user_settings(conn, params)

Functions

Link to this function

activate(conn, map)

View Source

Link to this function

activate_form(conn, params)

View Source

Link to this function

cancel_update_email(conn, params)

View Source

Link to this function

create_api_key(conn, map)

View Source

Link to this function

delete_api_key(conn, map)

View Source

Link to this function

delete_me(conn, params)

View Source

Link to this function

google_auth_callback(conn, params)

View Source

Link to this function

login(conn, map)

View Source

Link to this function

login_form(conn, params)

View Source

Link to this function

logout(conn, params)

View Source

Link to this function

new_api_key(conn, params)

View Source

Link to this function

password_reset(conn, params)

View Source

Link to this function

password_reset_form(conn, params)

View Source

Link to this function

password_reset_request(conn, params)

View Source

Link to this function

password_reset_request_form(conn, _)

View Source

Link to this function

register(conn, map)

View Source

Link to this function

register_from_invitation(conn, map)

View Source

Link to this function

request_activation_code(conn, params)

View Source

Link to this function

save_settings(conn, map)

View Source

Link to this function

update_email(conn, map)

View Source

Link to this function

user_settings(conn, params)

View Source

PlausibleWeb.AuthPlug

Summary

Functions

call(conn, opts)

init(options)

Functions

Link to this function

call(conn, opts)

View Source

Link to this function

init(options)

View Source

PlausibleWeb.AuthView

Summary

Functions

__resource__()

The resource name, as an atom, for this view

activate.html(assigns)

base_domain()

delimit_integer(number)

format_invoices(invoice_list)

login_form.html(assigns)

new_api_key.html(assigns)

password_reset_form.html(assigns)

password_reset_request_form.html(assigns)

password_reset_request_success.html(assigns)

plausible_url()

present_subscription_status(status)

register_success.html(assigns)

render(template, assigns \\ %{})

Renders the given template locally.

subscription_colors(_)

subscription_interval(subscription)

subscription_quota(subscription, options \\ [])

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

user_settings.html(assigns)

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

activate.html(assigns)

View Source

Link to this function

base_domain()

View Source

Link to this function

delimit_integer(number)

View Source

Link to this function

format_invoices(invoice_list)

View Source

Link to this function

login_form.html(assigns)

View Source

Link to this function

new_api_key.html(assigns)

View Source

Link to this function

password_reset_form.html(assigns)

View Source

Link to this function

password_reset_request_form.html(assigns)

View Source

Link to this function

password_reset_request_success.html(assigns)

View Source

Link to this function

plausible_url()

View Source

Link to this function

present_subscription_status(status)

View Source

@spec present_subscription_status(Plausible.Billing.Subscription.Status.status()) ::
  String.t()

Link to this function

register_success.html(assigns)

View Source

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

subscription_colors(_)

View Source

@spec subscription_colors(Plausible.Billing.Subscription.Status.status()) ::
  String.t()

Link to this function

subscription_interval(subscription)

View Source

Link to this function

subscription_quota(subscription, options \\ [])

View Source

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Link to this function

user_settings.html(assigns)

View Source

PlausibleWeb.AuthorizeSiteAccess

Summary

Functions

call(conn, allowed_roles)

init(allowed_roles)

Functions

Link to this function

call(conn, allowed_roles)

View Source

Link to this function

init(allowed_roles)

View Source

PlausibleWeb.AuthorizeSitesApiPlug

Summary

Functions

call(conn, opts)

init(options)

Functions

Link to this function

call(conn, opts)

View Source

Link to this function

init(options)

View Source

PlausibleWeb.AuthorizeStatsApiPlug

Summary

Functions

call(conn, opts)

init(options)

Functions

Link to this function

call(conn, opts)

View Source

Link to this function

init(options)

View Source

PlausibleWeb.AvatarController

This module proxies requests to BASE_URL/avatar/:hash to www.gravatar.com/avatar/:hash.

The purpose is to make use of Gravatar's convenient avatar service without exposing information that could be used for tracking the Plausible user. Compared to requesting the Gravatar directly from the browser, this proxy module protects the Plausible user from disclosing to Gravatar:

The client IP address

User-Agent

Referer header which can be used to track which site the user is visiting (i.e. plausible.io or self-hosted URL)

The downside is the added latency from the request having to go through the Plausible server, rather than contacting the local CDN server operated by Gravatar's service.

Summary

Functions

avatar(conn, params)

Functions

Link to this function

avatar(conn, params)

View Source

PlausibleWeb.BillingController

Summary

Functions

change_enterprise_plan(conn, params)

change_plan(conn, map)

change_plan_form(conn, params)

change_plan_preview(conn, map)

choose_plan(conn, params)

ping_subscription(conn, params)

preview_susbcription(_, _)

upgrade(conn, params)

upgrade_enterprise_plan(conn, params)

upgrade_success(conn, params)

upgrade_to_enterprise_plan(conn, params)

Functions

Link to this function

change_enterprise_plan(conn, params)

View Source

Link to this function

change_plan(conn, map)

View Source

Link to this function

change_plan_form(conn, params)

View Source

Link to this function

change_plan_preview(conn, map)

View Source

Link to this function

choose_plan(conn, params)

View Source

Link to this function

ping_subscription(conn, params)

View Source

Link to this function

preview_susbcription(_, _)

View Source

Link to this function

upgrade(conn, params)

View Source

Link to this function

upgrade_enterprise_plan(conn, params)

View Source

Link to this function

upgrade_success(conn, params)

View Source

Link to this function

upgrade_to_enterprise_plan(conn, params)

View Source

PlausibleWeb.BillingView

Summary

Functions

__resource__()

The resource name, as an atom, for this view

base_domain()

change_enterprise_plan_contact_us.html(assigns)

change_plan.html(assigns)

change_plan_preview.html(assigns)

choose_plan.html(assigns)

plausible_url()

present_currency(arg)

present_date(date)

reccommended_plan(usage)

render(template, assigns \\ %{})

Renders the given template locally.

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

upgrade.html(assigns)

upgrade_success.html(assigns)

upgrade_to_enterprise_plan.html(assigns)

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

base_domain()

View Source

Link to this function

change_enterprise_plan_contact_us.html(assigns)

View Source

Link to this function

change_plan.html(assigns)

View Source

Link to this function

change_plan_preview.html(assigns)

View Source

Link to this function

choose_plan.html(assigns)

View Source

Link to this function

plausible_url()

View Source

Link to this function

present_currency(arg)

View Source

Link to this function

present_date(date)

View Source

Link to this function

reccommended_plan(usage)

View Source

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Link to this function

upgrade.html(assigns)

View Source

Link to this function

upgrade_success.html(assigns)

View Source

Link to this function

upgrade_to_enterprise_plan.html(assigns)

View Source

PlausibleWeb.CRMAuthPlug

Summary

Functions

call(conn, opts)

init(options)

Functions

Link to this function

call(conn, opts)

View Source

Link to this function

init(options)

View Source

PlausibleWeb.Captcha

Summary

Functions

enabled?()

sitekey()

verify(token)

Functions

Link to this function

enabled?()

View Source

Link to this function

sitekey()

View Source

Link to this function

verify(token)

View Source

PlausibleWeb.Components.Generic

Generic reusable components

Summary

Functions

docs_info(assigns)

Attributes

slug (:string) (required)

dropdown(assigns)

Slots

button (required) - Accepts attributes:

class (:string)

panel (required) - Accepts attributes:

class (:string)

dropdown_link(assigns)

Attributes

href (:string) (required)

new_tab (:boolean) - Defaults to false.

Slots

inner_block (required)

notice(assigns)

Attributes

title (:string) - Defaults to "Notice".

size (:atom) - Defaults to :sm.

Global attributes are accepted.

Slots

inner_block

styled_link(assigns)

Attributes

id (:any) - Defaults to nil.

href (:string) (required)

new_tab (:boolean) - Defaults to false.

class (:string) - Defaults to "".

Slots

inner_block

unstyled_link(assigns)

Attributes

href (:string) (required)

new_tab (:boolean) - Defaults to false.

class (:string) - Defaults to "".

id (:any) - Defaults to nil.

Slots

inner_block

Functions

Link to this function

docs_info(assigns)

View Source

Attributes

slug (:string) (required)

Link to this function

dropdown(assigns)

View Source

Slots

button (required) - Accepts attributes:

class (:string)

panel (required) - Accepts attributes:

class (:string)

Link to this function

dropdown_link(assigns)

View Source

Attributes

href (:string) (required)

new_tab (:boolean) - Defaults to false.

Slots

inner_block (required)

Link to this function

notice(assigns)

View Source

Attributes

title (:string) - Defaults to "Notice".

size (:atom) - Defaults to :sm.

Global attributes are accepted.

Slots

inner_block

Link to this function

styled_link(assigns)

View Source

Attributes

id (:any) - Defaults to nil.

href (:string) (required)

new_tab (:boolean) - Defaults to false.

class (:string) - Defaults to "".

Slots

inner_block

Link to this function

unstyled_link(assigns)

View Source

Attributes

href (:string) (required)

new_tab (:boolean) - Defaults to false.

class (:string) - Defaults to "".

id (:any) - Defaults to nil.

Slots

inner_block

PlausibleWeb.Components.Google

Google-related components

Summary

Functions

button(assigns)

Attributes

to (:string) (required)

id (:string) (required)

logo(assigns \\ %{})

Functions

Link to this function

button(assigns)

View Source

Attributes

to (:string) (required)

id (:string) (required)

Link to this function

logo(assigns \\ %{})

View Source

PlausibleWeb.Components.Settings

An umbrella module for the Integrations settings section

Summary

Functions

settings_google_import(assigns)

settings_search_console(assigns)

Functions

Link to this function

settings_google_import(assigns)

View Source

Link to this function

settings_search_console(assigns)

View Source

PlausibleWeb.Components.Site.Feature

Phoenix Component for rendering a user-facing feature toggle capable of flipping booleans in Plausible.Site via the toggle_feature controller action.

Summary

Functions

__resource__()

The resource name, as an atom, for this view

render(template, assigns \\ %{})

Renders the given template locally.

target(site, setting, conn, set_to)

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

toggle(assigns)

Attributes

site (Plausible.Site) (required)

feature_mod (:atom) (required) - Must be one of Plausible.Billing.Feature.Goals, Plausible.Billing.Feature.StatsAPI, Plausible.Billing.Feature.Props, Plausible.Billing.Feature.Funnels, or Plausible.Billing.Feature.RevenueGoals.

conn (Plug.Conn) (required)

Slots

inner_block

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

target(site, setting, conn, set_to)

View Source

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Link to this function

toggle(assigns)

View Source

Attributes

site (Plausible.Site) (required)

feature_mod (:atom) (required) - Must be one of Plausible.Billing.Feature.Goals, Plausible.Billing.Feature.StatsAPI, Plausible.Billing.Feature.Props, Plausible.Billing.Feature.Funnels, or Plausible.Billing.Feature.RevenueGoals.

conn (Plug.Conn) (required)

Slots

inner_block

PlausibleWeb.ConnCase

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.

PlausibleWeb.ControllerHelpers

Summary

Functions

render_error(conn, status)

render_error(conn, status, message)

Functions

Link to this function

render_error(conn, status)

View Source

Link to this function

render_error(conn, status, message)

View Source

PlausibleWeb.Email

Summary

Functions

activation_email(user, code)

base_email()

base_email(map)

cancellation_email(user)

check_stats_email(user)

create_site_email(user)

dashboard_locked(user, usage, last_cycle, suggested_plan)

enterprise_over_limit_internal_email(user, usage, last_cycle, site_usage, site_allowance)

error_report(reported_by, trace_id, feedback)

existing_user_invitation(invitation)

import_failure(user, site)

import_success(user, site)

invitation_accepted(invitation)

invitation_rejected(invitation)

mailer_email_from()

new_user_invitation(invitation)

over_limit_email(user, usage, last_cycle, suggested_plan)

ownership_transfer_accepted(invitation)

ownership_transfer_rejected(invitation)

ownership_transfer_request(invitation, new_owner_account)

password_reset_email(email, reset_link)

priority_email()

Unlike the default 'base' emails, priority emails cannot be unsubscribed from. This is achieved by sending them through a dedicated 'priority' message stream in Postmark.

priority_email(map)

render(email, template, assigns \\ [])

Render an Phoenix template and set the body on the email.

site_member_removed(membership)

site_setup_help(user, site)

site_setup_success(user, site)

spike_notification(email, site, current_visitors, sources, dashboard_link)

trial_one_week_reminder(user)

trial_over_email(user)

trial_upgrade_email(user, day, arg)

weekly_report(email, site, assigns)

welcome_email(user)

yearly_expiration_notification(user)

yearly_renewal_notification(user)

Functions

Link to this function

activation_email(user, code)

View Source

Link to this function

base_email()

View Source

Link to this function

base_email(map)

View Source

Link to this function

cancellation_email(user)

View Source

Link to this function

check_stats_email(user)

View Source

Link to this function

create_site_email(user)

View Source

Link to this function

dashboard_locked(user, usage, last_cycle, suggested_plan)

View Source

Link to this function

enterprise_over_limit_internal_email(user, usage, last_cycle, site_usage, site_allowance)

View Source

Link to this function

error_report(reported_by, trace_id, feedback)

View Source

Link to this function

existing_user_invitation(invitation)

View Source

Link to this function

import_failure(user, site)

View Source

Link to this function

import_success(user, site)

View Source

Link to this function

invitation_accepted(invitation)

View Source

Link to this function

invitation_rejected(invitation)

View Source

Link to this function

mailer_email_from()

View Source

Link to this function

new_user_invitation(invitation)

View Source

Link to this function

over_limit_email(user, usage, last_cycle, suggested_plan)

View Source

Link to this function

ownership_transfer_accepted(invitation)

View Source

Link to this function

ownership_transfer_rejected(invitation)

View Source

Link to this function

ownership_transfer_request(invitation, new_owner_account)

View Source

Link to this function

password_reset_email(email, reset_link)

View Source

Link to this function

priority_email()

View Source

Unlike the default 'base' emails, priority emails cannot be unsubscribed from. This is achieved by sending them through a dedicated 'priority' message stream in Postmark.

Link to this function

priority_email(map)

View Source

Link to this function

render(email, template, assigns \\ [])

View Source

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.

Link to this function

site_member_removed(membership)

View Source

Link to this function

site_setup_help(user, site)

View Source

Link to this function

site_setup_success(user, site)

View Source

Link to this function

spike_notification(email, site, current_visitors, sources, dashboard_link)

View Source

Link to this function

trial_one_week_reminder(user)

View Source

Link to this function

trial_over_email(user)

View Source

Link to this function

trial_upgrade_email(user, day, arg)

View Source

Link to this function

weekly_report(email, site, assigns)

View Source

Link to this function

welcome_email(user)

View Source

Link to this function

yearly_expiration_notification(user)

View Source

Link to this function

yearly_renewal_notification(user)

View Source

PlausibleWeb.EmailView

Summary

Functions

__resource__()

The resource name, as an atom, for this view

activation_email.html(assigns)

base_domain()

cancellation_email.html(assigns)

check_stats_email.html(assigns)

create_site_email.html(assigns)

dashboard_locked.html(assigns)

date_format(date)

enterprise_over_limit_internal.html(assigns)

error_report_email.html(assigns)

existing_user_invitation.html(assigns)

google_analytics_import.html(assigns)

greet_recipient(_)

invitation_accepted.html(assigns)

invitation_rejected.html(assigns)

new_user_invitation.html(assigns)

over_limit.html(assigns)

ownership_transfer_accepted.html(assigns)

ownership_transfer_rejected.html(assigns)

ownership_transfer_request.html(assigns)

password_reset_email.html(assigns)

plausible_url()

render(template, assigns \\ %{})

Renders the given template locally.

sentry_link(trace_id, dsn \\ Sentry.Config.dsn())

site_member_removed.html(assigns)

site_setup_help_email.html(assigns)

site_setup_success_email.html(assigns)

spike_notification.html(assigns)

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

trial_one_week_reminder.html(assigns)

trial_over_email.html(assigns)

trial_upgrade_email.html(assigns)

welcome_email.html(assigns)

yearly_expiration_notification.html(assigns)

yearly_renewal_notification.html(assigns)

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

activation_email.html(assigns)

View Source

Link to this function

base_domain()

View Source

Link to this function

cancellation_email.html(assigns)

View Source

Link to this function

check_stats_email.html(assigns)

View Source

Link to this function

create_site_email.html(assigns)

View Source

Link to this function

dashboard_locked.html(assigns)

View Source

Link to this function

date_format(date)

View Source

Link to this function

enterprise_over_limit_internal.html(assigns)

View Source

Link to this function

error_report_email.html(assigns)

View Source

Link to this function

existing_user_invitation.html(assigns)

View Source

Link to this function

google_analytics_import.html(assigns)

View Source

Link to this function

greet_recipient(_)

View Source

Link to this function

invitation_accepted.html(assigns)

View Source

Link to this function

invitation_rejected.html(assigns)

View Source

Link to this function

new_user_invitation.html(assigns)

View Source

Link to this function

over_limit.html(assigns)

View Source

Link to this function

ownership_transfer_accepted.html(assigns)

View Source

Link to this function

ownership_transfer_rejected.html(assigns)

View Source

Link to this function

ownership_transfer_request.html(assigns)

View Source

Link to this function

password_reset_email.html(assigns)

View Source

Link to this function

plausible_url()

View Source

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

sentry_link(trace_id, dsn \\ Sentry.Config.dsn())

View Source

Link to this function

site_member_removed.html(assigns)

View Source

Link to this function

site_setup_help_email.html(assigns)

View Source

Link to this function

site_setup_success_email.html(assigns)

View Source

Link to this function

spike_notification.html(assigns)

View Source

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Link to this function

trial_one_week_reminder.html(assigns)

View Source

Link to this function

trial_over_email.html(assigns)

View Source

Link to this function

trial_upgrade_email.html(assigns)

View Source

Link to this function

welcome_email.html(assigns)

View Source

Link to this function

yearly_expiration_notification.html(assigns)

View Source

Link to this function

yearly_renewal_notification.html(assigns)

View Source

PlausibleWeb.Endpoint

Summary

Functions

broadcast(topic, event, msg)

Callback implementation for Phoenix.Endpoint.broadcast/3.

broadcast!(topic, event, msg)

Callback implementation for Phoenix.Endpoint.broadcast!/3.

broadcast_from(from, topic, event, msg)

Callback implementation for Phoenix.Endpoint.broadcast_from/4.

broadcast_from!(from, topic, event, msg)

Callback implementation for Phoenix.Endpoint.broadcast_from!/4.

call(conn, opts)

Callback implementation for Plug.call/2.

child_spec(opts)

Returns the child specification to start the endpoint under a supervision tree.

config(key, default \\ nil)

Returns the endpoint configuration for key

config_change(changed, removed)

Reloads the configuration given the application environment changes.

host()

Returns the host for the given endpoint.

init(opts)

Callback implementation for Plug.init/1.

local_broadcast(topic, event, msg)

Callback implementation for Phoenix.Endpoint.local_broadcast/3.

local_broadcast_from(from, topic, event, msg)

Callback implementation for Phoenix.Endpoint.local_broadcast_from/4.

path(path)

Generates the path information when routing to this endpoint.

runtime_session(conn, opts)

runtime_session_opts()

script_name()

Generates the script name.

secure_cookie?()

start_link(opts \\ [])

Starts the endpoint supervision tree.

static_integrity(path)

Generates a base64-encoded cryptographic hash (sha512) to a static file in priv/static. Meant to be used for Subresource Integrity with CDNs.

static_lookup(path)

Returns a two item tuple with the first item being the static_path and the second item being the static_integrity.

static_path(path)

Generates a route to a static file in priv/static.

static_url()

Generates the static URL without any path information.

struct_url()

Generates the endpoint base URL but as a URI struct.

subscribe(topic, opts \\ [])

Callback implementation for Phoenix.Endpoint.subscribe/2.

unsubscribe(topic)

Callback implementation for Phoenix.Endpoint.unsubscribe/1.

url()

Generates the endpoint base URL without any path information.

websocket_url()

Functions

Link to this function

broadcast(topic, event, msg)

View Source

Callback implementation for Phoenix.Endpoint.broadcast/3.

Link to this function

broadcast!(topic, event, msg)

View Source

Callback implementation for Phoenix.Endpoint.broadcast!/3.

Link to this function

broadcast_from(from, topic, event, msg)

View Source

Callback implementation for Phoenix.Endpoint.broadcast_from/4.

Link to this function

broadcast_from!(from, topic, event, msg)

View Source

Callback implementation for Phoenix.Endpoint.broadcast_from!/4.

Link to this function

call(conn, opts)

View Source

Callback implementation for Plug.call/2.

Link to this function

child_spec(opts)

View Source

Returns the child specification to start the endpoint under a supervision tree.

Link to this function

config(key, default \\ nil)

View Source

Returns the endpoint configuration for key

Returns default if the key does not exist.

Link to this function

config_change(changed, removed)

View Source

Reloads the configuration given the application environment changes.

Link to this function

host()

View Source

Returns the host for the given endpoint.

Link to this function

init(opts)

View Source

Callback implementation for Plug.init/1.

Link to this function

local_broadcast(topic, event, msg)

View Source

Callback implementation for Phoenix.Endpoint.local_broadcast/3.

Link to this function

local_broadcast_from(from, topic, event, msg)

View Source

Callback implementation for Phoenix.Endpoint.local_broadcast_from/4.

Link to this function

path(path)

View Source

Generates the path information when routing to this endpoint.

Link to this function

runtime_session(conn, opts)

View Source

Link to this function

runtime_session_opts()

View Source

Link to this function

script_name()

View Source

Generates the script name.

Link to this function

secure_cookie?()

View Source

Link to this function

start_link(opts \\ [])

View Source

Starts the endpoint supervision tree.

All other options are merged into the endpoint configuration.

Link to this function

static_integrity(path)

View Source

Generates a base64-encoded cryptographic hash (sha512) to a static file in priv/static. Meant to be used for Subresource Integrity with CDNs.

Link to this function

static_lookup(path)

View Source

Returns a two item tuple with the first item being the static_path and the second item being the static_integrity.

Link to this function

static_path(path)

View Source

Generates a route to a static file in priv/static.

Link to this function

static_url()

View Source

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.

Link to this function

struct_url()

View Source

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.

Link to this function

subscribe(topic, opts \\ [])

View Source

Callback implementation for Phoenix.Endpoint.subscribe/2.

Link to this function

unsubscribe(topic)

View Source

Callback implementation for Phoenix.Endpoint.unsubscribe/1.

Link to this function

url()

View Source

Generates the endpoint base URL without any path information.

It uses the configuration under :url to generate such.

Link to this function

websocket_url()

View Source

PlausibleWeb.ErrorHelpers

Summary

Functions

error_tag(assigns, field)

translate_error(arg)

Functions

Link to this function

error_tag(assigns, field)

View Source

Link to this function

translate_error(arg)

View Source

PlausibleWeb.ErrorReportController

Summary

Functions

submit_error_report(conn, arg2)

Functions

Link to this function

submit_error_report(conn, arg2)

View Source

PlausibleWeb.ErrorView

Summary

Functions

404_error.html(assigns)

__resource__()

The resource name, as an atom, for this view

generic_error.html(assigns)

render(template, assigns \\ %{})

Renders the given template locally.

server_error.html(assigns)

server_error_report_thanks.html(assigns)

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Functions

Link to this function

404_error.html(assigns)

View Source

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

generic_error.html(assigns)

View Source

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

server_error.html(assigns)

View Source

Link to this function

server_error_report_thanks.html(assigns)

View Source

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

PlausibleWeb.Favicon

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

Summary

Functions

call(conn, list)

Proxies HTTP request to DuckDuckGo favicon service. Swallows hop-by-hop HTTP headers that should not be forwarded as defined in RFC 2616

init(_)

Functions

Link to this function

call(conn, list)

View Source

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>

Link to this function

init(_)

View Source

PlausibleWeb.FirstLaunchPlug

Redirects first-launch users to registration page.

PlausibleWeb.FormHelpers

Summary

Functions

styled_error(error)

styled_label(form, field, text, opts \\ [])

styled_select(form, field, options, opts \\ [])

styled_text_input(form, field, opts \\ [])

Functions

Link to this function

styled_error(error)

View Source

Link to this function

styled_label(form, field, text, opts \\ [])

View Source

Link to this function

styled_select(form, field, options, opts \\ [])

View Source

Link to this function

styled_text_input(form, field, opts \\ [])

View Source

PlausibleWeb.InvitationController

Summary

Functions

accept_invitation(conn, map)

reject_invitation(conn, map)

remove_invitation(conn, map)

Functions

Link to this function

accept_invitation(conn, map)

View Source

Link to this function

reject_invitation(conn, map)

View Source

Link to this function

remove_invitation(conn, map)

View Source

PlausibleWeb.LastSeenPlug

Summary

Functions

call(conn, opts)

init(opts)

Functions

Link to this function

call(conn, opts)

View Source

Link to this function

init(opts)

View Source

PlausibleWeb.LayoutView

Summary

Functions

__resource__()

The resource name, as an atom, for this view

app.html(assigns)

base_domain()

base_email.html(assigns)

base_error.html(assigns)

dogfood_api_destination()

Temporary override to do more testing of the new ingest.plausible.io endpoint for accepting events. In staging and locally will fall back to staging.plausible.io/api/event and localhost:8000/api/event respectively.

dogfood_domain(conn)

dogfood_script_url()

embedded.html(assigns)

feedback_link(user)

focus.html(assigns)

grace_period_end(user)

home_dest(conn)

is_current_tab(conn, tab)

plausible_url()

priority_email.html(assigns)

render(template, assigns \\ %{})

Renders the given template locally.

render_layout(layout, assigns, list)

http://blog.plataformatec.com.br/2018/05/nested-layouts-with-phoenix/

settings_tabs(conn)

site_settings.html(assigns)

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

trial_notificaton(user)

websocket_url()

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

app.html(assigns)

View Source

Link to this function

base_domain()

View Source

Link to this function

base_email.html(assigns)

View Source

Link to this function

base_error.html(assigns)

View Source

Link to this function

dogfood_api_destination()

View Source

Temporary override to do more testing of the new ingest.plausible.io endpoint for accepting events. In staging and locally will fall back to staging.plausible.io/api/event and localhost:8000/api/event respectively.

Link to this function

dogfood_domain(conn)

View Source

Link to this function

dogfood_script_url()

View Source

Link to this function

embedded.html(assigns)

View Source

Link to this function

feedback_link(user)

View Source

Link to this function

focus.html(assigns)

View Source

Link to this function

grace_period_end(user)

View Source

Link to this function

home_dest(conn)

View Source

Link to this function

is_current_tab(conn, tab)

View Source

Link to this function

plausible_url()

View Source

Link to this function

priority_email.html(assigns)

View Source

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

render_layout(layout, assigns, list)

View Source

http://blog.plataformatec.com.br/2018/05/nested-layouts-with-phoenix/

Link to this function

settings_tabs(conn)

View Source

Link to this function

site_settings.html(assigns)

View Source

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Link to this function

trial_notificaton(user)

View Source

Link to this function

websocket_url()

View Source

PlausibleWeb.LayoutView.JWT

Summary

Functions

generate_and_sign(extra_claims \\ %{}, key \\ __default_signer__())

Combines generate_claims/1 and encode_and_sign/2

generate_and_sign!(extra_claims \\ %{}, key \\ __default_signer__())

Same as generate_and_sign/2 but raises if error

verify_and_validate(bearer_token, key \\ __default_signer__(), context \\ %{})

Combines verify/2 and validate/2

verify_and_validate!(bearer_token, key \\ __default_signer__(), context \\ %{})

Same as verify_and_validate/2 but raises if error

Functions

Link to this function

generate_and_sign(extra_claims \\ %{}, key \\ __default_signer__())

View Source

@spec generate_and_sign(Joken.claims(), Joken.signer_arg()) ::
  {:ok, Joken.bearer_token(), Joken.claims()} | {:error, Joken.error_reason()}

Combines generate_claims/1 and encode_and_sign/2

Link to this function

generate_and_sign!(extra_claims \\ %{}, key \\ __default_signer__())

View Source

@spec generate_and_sign!(Joken.claims(), Joken.signer_arg()) :: Joken.bearer_token()

Same as generate_and_sign/2 but raises if error

Link to this function

verify_and_validate(bearer_token, key \\ __default_signer__(), context \\ %{})

View Source

@spec verify_and_validate(Joken.bearer_token(), Joken.signer_arg(), term()) ::
  {:ok, Joken.claims()} | {:error, Joken.error_reason()}

Combines verify/2 and validate/2

Link to this function

verify_and_validate!(bearer_token, key \\ __default_signer__(), context \\ %{})

View Source

@spec verify_and_validate!(Joken.bearer_token(), Joken.signer_arg(), term()) ::
  Joken.claims()

Same as verify_and_validate/2 but raises if error

PlausibleWeb.Live.ChoosePlan

LiveView for upgrading to a plan, or changing an existing plan.

Summary

Functions

handle_event(binary, map, socket)

Callback implementation for Phoenix.LiveView.handle_event/3.

mount(params, map, socket)

Callback implementation for Phoenix.LiveView.mount/3.

render(assigns)

Callback implementation for Phoenix.LiveView.render/1.

render_price_info(assigns)

two_months_free(assigns)

Functions

Link to this function

handle_event(binary, map, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_event/3.

Link to this function

mount(params, map, socket)

View Source

Callback implementation for Phoenix.LiveView.mount/3.

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveView.render/1.

Link to this function

render_price_info(assigns)

View Source

Link to this function

two_months_free(assigns)

View Source

PlausibleWeb.Live.Components.ComboBox

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.

Any function can be supplied via suggest_fun attribute

see the provided ComboBox.StaticSearch.

In most cases the suggest_fun runs an operation that could be deferred, so by default, the async={true} attr calls it in a background Task and updates the suggestions asynchronously. This way, you can render the component without having to wait for suggestions to load.

If you explicitly need to make the operation sychronous, you may pass async={false} option.

If your initial options are not provided up-front at initial render, lack of options attr value combined with async=true calls the suggest_fun.("", []) asynchronously - that special clause can be used to provide the initial set of suggestions updated right after the initial render.

To simplify integration testing, suggestions load up synchronously during tests. This lets you skip waiting for suggestions messages to arrive. The asynchronous behaviour alone is already tested in ComboBox own test suite, so there is no need for additional verification.

Summary

Functions

dropdown(assigns)

Attributes

ref (:string) (required)

suggestions (:list) - Defaults to [].

suggest_fun (:any) (required)

target (:any)

creatable (:boolean) (required)

display_value (:string) (required)

dropdown_anchor(assigns)

Attributes

id (:any) (required)

handle_event(binary, params, socket)

Callback implementation for Phoenix.LiveComponent.handle_event/3.

option(assigns)

Attributes

display_value (:string) (required)

submit_value (:string) (required)

ref (:string) (required)

target (:any)

idx (:integer) (required)

creatable (:boolean) - Defaults to false.

render(assigns)

Attributes

placeholder (:string) - Defaults to "Select option or search by typing".

id (:any) (required)

options (:list) - Defaults to [].

submit_name (:string) (required)

display_value (:string) - Defaults to "".

submit_value (:string) - Defaults to "".

suggest_fun (:any) (required)

suggestions_limit (:integer)

class (:string) - Defaults to "".

required (:boolean) - Defaults to false.

creatable (:boolean) - Defaults to false.

errors (:list) - Defaults to [].

async (:boolean) - Defaults to true.

select_option(js \\ %JS{}, id, submit_value, display_value)

update(assigns, socket)

Callback implementation for Phoenix.LiveComponent.update/2.

Functions

Link to this function

dropdown(assigns)

View Source

Attributes

ref (:string) (required)

suggestions (:list) - Defaults to [].

suggest_fun (:any) (required)

target (:any)

creatable (:boolean) (required)

display_value (:string) (required)

Link to this function

dropdown_anchor(assigns)

View Source

Attributes

id (:any) (required)

Link to this function

handle_event(binary, params, socket)

View Source

Callback implementation for Phoenix.LiveComponent.handle_event/3.

Link to this function

option(assigns)

View Source

Attributes

display_value (:string) (required)

submit_value (:string) (required)

ref (:string) (required)

target (:any)

idx (:integer) (required)

creatable (:boolean) - Defaults to false.

Link to this function

render(assigns)

View Source

Attributes

placeholder (:string) - Defaults to "Select option or search by typing".

id (:any) (required)

options (:list) - Defaults to [].

submit_name (:string) (required)

display_value (:string) - Defaults to "".

submit_value (:string) - Defaults to "".

suggest_fun (:any) (required)

suggestions_limit (:integer)

class (:string) - Defaults to "".

required (:boolean) - Defaults to false.

creatable (:boolean) - Defaults to false.

errors (:list) - Defaults to [].

async (:boolean) - Defaults to true.

Link to this function

select_option(js \\ %JS{}, id, submit_value, display_value)

View Source

Link to this function

update(assigns, socket)

View Source

Callback implementation for Phoenix.LiveComponent.update/2.

PlausibleWeb.Live.Components.ComboBox.StaticSearch

Default suggestion engine for the ComboBox component.

Assumes, the user have already queried the database and the data set is small enough to be kept in state and filtered based on external input.

Favours exact matches. Skips entries shorter than input. Allows fuzzy matching based on Jaro Distance.

Summary

Functions

suggest(input, choices, opts \\ [])

Functions

Link to this function

suggest(input, choices, opts \\ [])

View Source

PlausibleWeb.Live.Components.Form

Generic components stolen from mix phx.new templates

Summary

Functions

error(assigns)

Generates a generic error message.

input(assigns)

Renders an input with label and error messages.

input_with_clipboard(assigns)

Attributes

id (:string) (required)

class (:string) - Defaults to "".

name (:string) (required)

label (:string) (required)

value (:string) - Defaults to "".

Global attributes are accepted.

label(assigns)

Renders a label.

password_input_with_strength(assigns)

Attributes

id (:any) - Defaults to nil.

label (:string) - Defaults to nil.

field (Phoenix.HTML.FormField) (required) - a form field struct retrieved from the form, for example: @form[:password].

strength (:any)

Global attributes are accepted.

password_length_hint(assigns)

Attributes

minimum (:integer) (required)

class (:any)

ok_class (:any)

error_class (:any)

field (Phoenix.HTML.FormField) (required) - a form field struct retrieved from the form, for example: @form[:password].

strength_meter(assigns)

Attributes

score (:integer) - Defaults to 0.

warning (:string) - Defaults to "".

suggestions (:list) - Defaults to [].

translate_error(arg)

Functions

Link to this function

error(assigns)

View Source

Generates a generic error message.

Slots

inner_block (required)

Link to this function

input(assigns)

View Source

Renders an input with label and error messages.

A Phoenix.HTML.FormField may be passed as argument, which is used to retrieve the input name, id, and values. Otherwise all attributes may be passed explicitly.

Examples

<.input field={@form[:email]} type="email" /> <.input name="my-input" errors={["oh no!"]} />

Attributes

id (:any) - Defaults to nil.

name (:any)

label (:string) - Defaults to nil.

value (:any)

type (:string) - Defaults to "text".

field (Phoenix.HTML.FormField) - a form field struct retrieved from the form, for example: @form[:email].

errors (:list) - Defaults to [].

checked (:boolean) - the checked flag for checkbox inputs.

prompt (:string) - the prompt for select inputs. Defaults to nil.

options (:list) - the options to pass to Phoenix.HTML.Form.options_for_select/2.

multiple (:boolean) - the multiple flag for select inputs. Defaults to false.

Global attributes are accepted.

Slots

inner_block

Link to this function

input_with_clipboard(assigns)

View Source

Attributes

id (:string) (required)

class (:string) - Defaults to "".

name (:string) (required)

label (:string) (required)

value (:string) - Defaults to "".

Global attributes are accepted.

Link to this function

label(assigns)

View Source

Renders a label.

Attributes

for (:string) - Defaults to nil.

Slots

inner_block (required)

Link to this function

password_input_with_strength(assigns)

View Source

Attributes

id (:any) - Defaults to nil.

label (:string) - Defaults to nil.

field (Phoenix.HTML.FormField) (required) - a form field struct retrieved from the form, for example: @form[:password].

strength (:any)

Global attributes are accepted.

Link to this function

password_length_hint(assigns)

View Source

Attributes

minimum (:integer) (required)

class (:any)

ok_class (:any)

error_class (:any)

field (Phoenix.HTML.FormField) (required) - a form field struct retrieved from the form, for example: @form[:password].

Link to this function

strength_meter(assigns)

View Source

Attributes

score (:integer) - Defaults to 0.

warning (:string) - Defaults to "".

suggestions (:list) - Defaults to [].

Link to this function

translate_error(arg)

View Source

PlausibleWeb.Live.Flash

Flash component for LiveViews - works also when embedded within dead views

Summary

Functions

clear_flash_button(assigns)

flash(assigns)

Attributes

on_close (:any) - Defaults to "lv:clear-flash".

Slots

icon (required)

title

message (required)

icon_error(assigns)

icon_success(assigns)

render(assigns)

Callback implementation for Phoenix.LiveComponent.render/1.

Functions

Link to this function

clear_flash_button(assigns)

View Source

Link to this function

flash(assigns)

View Source

Attributes

on_close (:any) - Defaults to "lv:clear-flash".

Slots

icon (required)

title

message (required)

Link to this function

icon_error(assigns)

View Source

Link to this function

icon_success(assigns)

View Source

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveComponent.render/1.

PlausibleWeb.Live.FunnelSettings

LiveView allowing listing, creating and deleting funnels.

Summary

Functions

handle_event(binary, arg2, socket)

Callback implementation for Phoenix.LiveView.handle_event/3.

handle_info(arg1, socket)

Callback implementation for Phoenix.LiveView.handle_info/2.

mount(params, map, socket)

Callback implementation for Phoenix.LiveView.mount/3.

render(assigns)

Callback implementation for Phoenix.LiveView.render/1.

Functions

Link to this function

handle_event(binary, arg2, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_event/3.

Link to this function

handle_info(arg1, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_info/2.

Link to this function

mount(params, map, socket)

View Source

Callback implementation for Phoenix.LiveView.mount/3.

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveView.render/1.

PlausibleWeb.Live.FunnelSettings.Form

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.

Summary

Functions

add_step_button(assigns)

evaluation(assigns)

Attributes

at (:integer) (required)

result (:map) (required)

handle_event(binary, arg2, socket)

Callback implementation for Phoenix.LiveView.handle_event/3.

handle_info(arg1, socket)

Callback implementation for Phoenix.LiveView.handle_info/2.

mount(params, map, socket)

Callback implementation for Phoenix.LiveView.mount/3.

remove_step_button(assigns)

Attributes

step_idx (:integer) (required)

render(assigns)

Callback implementation for Phoenix.LiveView.render/1.

submit_button(assigns)

submit_button_inactive(assigns)

Functions

Link to this function

add_step_button(assigns)

View Source

Link to this function

evaluation(assigns)

View Source

Attributes

at (:integer) (required)

result (:map) (required)

Link to this function

handle_event(binary, arg2, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_event/3.

Link to this function

handle_info(arg1, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_info/2.

Link to this function

mount(params, map, socket)

View Source

Callback implementation for Phoenix.LiveView.mount/3.

Link to this function

remove_step_button(assigns)

View Source

Attributes

step_idx (:integer) (required)

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveView.render/1.

Link to this function

submit_button(assigns)

View Source

Link to this function

submit_button_inactive(assigns)

View Source

PlausibleWeb.Live.FunnelSettings.List

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.

Summary

Functions

render(assigns)

Callback implementation for Phoenix.LiveComponent.render/1.

Functions

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveComponent.render/1.

PlausibleWeb.Live.GoalSettings

LiveView allowing listing, creating and deleting goals.

Summary

Functions

handle_event(binary, arg2, socket)

Callback implementation for Phoenix.LiveView.handle_event/3.

handle_info(arg1, socket)

Callback implementation for Phoenix.LiveView.handle_info/2.

mount(params, map, socket)

Callback implementation for Phoenix.LiveView.mount/3.

render(assigns)

Callback implementation for Phoenix.LiveView.render/1.

Functions

Link to this function

handle_event(binary, arg2, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_event/3.

Link to this function

handle_info(arg1, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_info/2.

Link to this function

mount(params, map, socket)

View Source

Callback implementation for Phoenix.LiveView.mount/3.

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveView.render/1.

PlausibleWeb.Live.GoalSettings.Form

Live view for the goal creation form

Summary

Functions

custom_event_fields(assigns)

Attributes

f (Phoenix.HTML.Form)

site (Plausible.Site)

current_user (Plausible.Auth.User)

has_access_to_revenue_goals? (:boolean)

handle_event(binary, arg2, socket)

Callback implementation for Phoenix.LiveView.handle_event/3.

mount(params, map, socket)

Callback implementation for Phoenix.LiveView.mount/3.

pageview_fields(assigns)

Attributes

f (Phoenix.HTML.Form)

site (Plausible.Site)

pageviews_tab(assigns)

render(assigns)

Callback implementation for Phoenix.LiveView.render/1.

suggest_page_paths(input, options, site)

tabs(assigns)

Functions

Link to this function

custom_event_fields(assigns)

View Source

Attributes

f (Phoenix.HTML.Form)

site (Plausible.Site)

current_user (Plausible.Auth.User)

has_access_to_revenue_goals? (:boolean)

Link to this function

handle_event(binary, arg2, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_event/3.

Link to this function

mount(params, map, socket)

View Source

Callback implementation for Phoenix.LiveView.mount/3.

Link to this function

pageview_fields(assigns)

View Source

Attributes

f (Phoenix.HTML.Form)

site (Plausible.Site)

Link to this function

pageviews_tab(assigns)

View Source

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveView.render/1.

Link to this function

suggest_page_paths(input, options, site)

View Source

Link to this function

tabs(assigns)

View Source

PlausibleWeb.Live.GoalSettings.List

Phoenix LiveComponent module that renders a list of goals

Summary

Functions

render(assigns)

Attributes

goals (:list) (required)

domain (:string) (required)

filter_text (:string)

Functions

Link to this function

render(assigns)

View Source

Attributes

goals (:list) (required)

domain (:string) (required)

filter_text (:string)

PlausibleWeb.Live.Plugins.API.Settings

LiveView allowing listing, creating and revoking Plugins API tokens.

Summary

Functions

handle_event(binary, arg2, socket)

Callback implementation for Phoenix.LiveView.handle_event/3.

handle_info(arg1, socket)

Callback implementation for Phoenix.LiveView.handle_info/2.

mount(params, session, socket)

Callback implementation for Phoenix.LiveView.mount/3.

render(assigns)

Callback implementation for Phoenix.LiveView.render/1.

Functions

Link to this function

handle_event(binary, arg2, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_event/3.

Link to this function

handle_info(arg1, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_info/2.

Link to this function

mount(params, session, socket)

View Source

Callback implementation for Phoenix.LiveView.mount/3.

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveView.render/1.

PlausibleWeb.Live.Plugins.API.TokenForm

Live view for the goal creation form

Summary

Functions

handle_event(binary, arg2, socket)

Callback implementation for Phoenix.LiveView.handle_event/3.

mount(params, map, socket)

Callback implementation for Phoenix.LiveView.mount/3.

render(assigns)

Callback implementation for Phoenix.LiveView.render/1.

Functions

Link to this function

handle_event(binary, arg2, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_event/3.

Link to this function

mount(params, map, socket)

View Source

Callback implementation for Phoenix.LiveView.mount/3.

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveView.render/1.

PlausibleWeb.Live.PropsSettings

LiveView allowing listing, allowing and disallowing custom event properties.

Summary

Functions

handle_event(binary, arg2, socket)

Callback implementation for Phoenix.LiveView.handle_event/3.

handle_info(arg1, socket)

Callback implementation for Phoenix.LiveView.handle_info/2.

mount(params, map, socket)

Callback implementation for Phoenix.LiveView.mount/3.

render(assigns)

Callback implementation for Phoenix.LiveView.render/1.

Functions

Link to this function

handle_event(binary, arg2, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_event/3.

Link to this function

handle_info(arg1, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_info/2.

Link to this function

mount(params, map, socket)

View Source

Callback implementation for Phoenix.LiveView.mount/3.

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveView.render/1.

PlausibleWeb.Live.PropsSettings.Form

Live view for the custom props creation form

Summary

Functions

handle_event(binary, arg2, socket)

Callback implementation for Phoenix.LiveView.handle_event/3.

handle_info(arg, socket)

Callback implementation for Phoenix.LiveView.handle_info/2.

mount(params, map, socket)

Callback implementation for Phoenix.LiveView.mount/3.

render(assigns)

Callback implementation for Phoenix.LiveView.render/1.

Functions

Link to this function

handle_event(binary, arg2, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_event/3.

Link to this function

handle_info(arg, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_info/2.

Link to this function

mount(params, map, socket)

View Source

Callback implementation for Phoenix.LiveView.mount/3.

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveView.render/1.

PlausibleWeb.Live.PropsSettings.List

Phoenix LiveComponent module that renders a list of custom properties

Summary

Functions

render(assigns)

Attributes

props (:list) (required)

domain (:string) (required)

filter_text (:string)

Functions

Link to this function

render(assigns)

View Source

Attributes

props (:list) (required)

domain (:string) (required)

filter_text (:string)

PlausibleWeb.Live.RegisterForm

LiveView for registration form.

Summary

Functions

handle_event(binary, params, socket)

Callback implementation for Phoenix.LiveView.handle_event/3.

mount(params, session, socket)

Callback implementation for Phoenix.LiveView.mount/3.

render(assigns)

Callback implementation for Phoenix.LiveView.render/1.

Functions

Link to this function

handle_event(binary, params, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_event/3.

Link to this function

mount(params, session, socket)

View Source

Callback implementation for Phoenix.LiveView.mount/3.

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveView.render/1.

PlausibleWeb.Live.ResetPasswordForm

LiveView for password reset form.

Summary

Functions

handle_event(binary, map, socket)

Callback implementation for Phoenix.LiveView.handle_event/3.

mount(params, map, socket)

Callback implementation for Phoenix.LiveView.mount/3.

render(assigns)

Callback implementation for Phoenix.LiveView.render/1.

Functions

Link to this function

handle_event(binary, map, socket)

View Source

Callback implementation for Phoenix.LiveView.handle_event/3.

Link to this function

mount(params, map, socket)

View Source

Callback implementation for Phoenix.LiveView.mount/3.

Link to this function

render(assigns)

View Source

Callback implementation for Phoenix.LiveView.render/1.

PlausibleWeb.MJML.WeeklyReport

MJML rendered for the weekly report e-mail

Summary

Functions

debug_mjml_template()

Returns the raw MJML template. Useful for debugging rendering issues.

render(assigns)

Safely render the MJML template using Phoenix.HTML

Functions

Link to this function

debug_mjml_template()

View Source

Returns the raw MJML template. Useful for debugging rendering issues.

Link to this function

render(assigns)

View Source

Safely render the MJML template using Phoenix.HTML

PlausibleWeb.PageController

Summary

Functions

index(conn, params)

The root path is never accessible in Plausible.Cloud because it is handled by the upstream reverse proxy.

Functions

Link to this function

index(conn, params)

View Source

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.

PlausibleWeb.PageView

Summary

Functions

__resource__()

The resource name, as an atom, for this view

index.html(assigns)

render(template, assigns \\ %{})

Renders the given template locally.

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

index.html(assigns)

View Source

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

PlausibleWeb.Plugins.API

Plausible Plugins API

Summary

Functions

base_uri()

Returns the API base URI, so that complete URLs can be generated from forwared Router helpers.

Functions

Link to this function

base_uri()

View Source

@spec base_uri() :: URI.t()

Returns the API base URI, so that complete URLs can be generated from forwared Router helpers.

PlausibleWeb.Plugins.API.Controllers.Goals

Controller for the Goal resource under Plugins API

Summary

Functions

create(conn, params)

delete(conn, params)

get(conn, params)

index(conn, params)

open_api_operation(action)

shared_security()

shared_tags()

Functions

Link to this function

create(conn, params)

View Source

@spec create(Plug.Conn.t(), map()) :: Plug.Conn.t()

Link to this function

delete(conn, params)

View Source

@spec delete(Plug.Conn.t(), map()) :: Plug.Conn.t()

Link to this function

get(conn, params)

View Source

@spec get(Plug.Conn.t(), map()) :: Plug.Conn.t()

Link to this function

index(conn, params)

View Source

@spec index(Plug.Conn.t(), %{}) :: Plug.Conn.t()

Link to this function

open_api_operation(action)

View Source

@spec open_api_operation(atom()) :: OpenApiSpex.Operation.t()

Link to this function

shared_security()

View Source

Link to this function

shared_tags()

View Source

PlausibleWeb.Plugins.API.Controllers.SharedLinks

Controller for the Shared Link resource under Plugins API

Summary

Functions

create(conn, params)

get(conn, params)

index(conn, params)

open_api_operation(action)

shared_security()

shared_tags()

Functions

Link to this function

create(conn, params)

View Source

@spec create(Plug.Conn.t(), map()) :: Plug.Conn.t()

Link to this function

get(conn, params)

View Source

@spec get(Plug.Conn.t(), map()) :: Plug.Conn.t()

Link to this function

index(conn, params)

View Source

@spec index(Plug.Conn.t(), %{}) :: Plug.Conn.t()

Link to this function

open_api_operation(action)

View Source

@spec open_api_operation(atom()) :: OpenApiSpex.Operation.t()

Link to this function

shared_security()

View Source

Link to this function

shared_tags()

View Source

PlausibleWeb.Plugins.API.Errors

Common responses for Plugins API

Summary

Functions

error(conn, status, message)

unauthorized(conn)

Functions

Link to this function

error(conn, status, message)

View Source

@spec error(
  Plug.Conn.t(),
  Plug.Conn.status(),
  String.t() | [String.t()] | Ecto.Changeset.t() | [Ecto.Changeset.t()]
) :: Plug.Conn.t()

Link to this function

unauthorized(conn)

View Source

@spec unauthorized(Plug.Conn.t()) :: Plug.Conn.t()

PlausibleWeb.Plugins.API.Router

Summary

Functions

api(conn, _)

auth(conn, _)

call(conn, opts)

Callback invoked by Plug on every request.

init(opts)

Callback required by Plug that initializes the router for serving web requests.

Functions

Link to this function

api(conn, _)

View Source

Link to this function

auth(conn, _)

View Source

Link to this function

call(conn, opts)

View Source

Callback invoked by Plug on every request.

Link to this function

init(opts)

View Source

Callback required by Plug that initializes the router for serving web requests.

PlausibleWeb.Plugins.API.Schemas.Error

OpenAPI schema for an error included in a response

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Error{detail: term()}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.Goal

OpenAPI schema for Goal

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Goal{}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.Goal.CreateRequest

OpenAPI schema for Goal creation request

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Goal.CreateRequest{}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.Goal.CreateRequest.CustomEvent

OpenAPI schema for Custom Event Goal creation request

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Goal.CreateRequest.CustomEvent{
  goal: term(),
  goal_type: term()
}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.Goal.CreateRequest.Pageview

OpenAPI schema for Pageview Goal creation request

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Goal.CreateRequest.Pageview{
  goal: term(),
  goal_type: term()
}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.Goal.CreateRequest.Revenue

OpenAPI schema for Custom Event Goal creation request

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Goal.CreateRequest.Revenue{
  goal: term(),
  goal_type: term()
}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.Goal.CustomEvent

OpenAPI schema for Custom Event Goal object

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Goal.CustomEvent{
  goal: term(),
  goal_type: term()
}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.Goal.ListResponse

OpenAPI schema for Goals list response

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Goal.ListResponse{
  goals: term(),
  meta: term()
}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.Goal.Pageview

OpenAPI schema for Pageview Goal object

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Goal.Pageview{
  goal: term(),
  goal_type: term()
}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.Goal.Revenue

OpenAPI schema for Revenue Goal object

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Goal.Revenue{
  goal: term(),
  goal_type: term()
}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.Goal.Type

OpenAPI schema for common Goal Type

Future-proof: funnels etc.

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Goal.Type{goal_type: term()}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.Link

OpenAPI Link schema

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Link{url: term()}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.NotFound

OpenAPI schema for a generic 404 response

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.NotFound{errors: term()}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.PaginationMetadata

Pagination metadata OpenAPI schema

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.PaginationMetadata{
  has_next_page: term(),
  has_prev_page: term(),
  links: term()
}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.PaymentRequired

OpenAPI schema for a generic 402 response

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.PaymentRequired{errors: term()}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.SharedLink

OpenAPI schema for SharedLink object

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.SharedLink{shared_link: term()}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.SharedLink.CreateRequest

OpenAPI schema for SharedLink creation request

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.SharedLink.CreateRequest{
  shared_link: term()
}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.SharedLink.ListResponse

OpenAPI schema for SharedLink list response

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.SharedLink.ListResponse{
  meta: term(),
  shared_links: term()
}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.Unauthorized

OpenAPI schema for a generic 401 response

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.Unauthorized{errors: term()}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Schemas.UnprocessableEntity

OpenAPI schema for a generic 422 response

Summary

Types

t()

Functions

schema()

Callback implementation for OpenApiSpex.Schema.schema/0.

Types

Link to this type

t()

View Source

@type t() :: %PlausibleWeb.Plugins.API.Schemas.UnprocessableEntity{errors: term()}

Functions

Link to this function

schema()

View Source

Callback implementation for OpenApiSpex.Schema.schema/0.

PlausibleWeb.Plugins.API.Spec

OpenAPI specification for the Plugins API

PlausibleWeb.Plugins.API.Views.Error

View for rendering Plugins REST API errors

Summary

Functions

__resource__()

The resource name, as an atom, for this view

render(template, assigns \\ %{})

Renders the given template locally.

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

render(template, assigns \\ %{})

View Source

@spec render(String.t(), map()) :: map() | binary()

Renders the given template locally.

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

PlausibleWeb.Plugins.API.Views.Goal

View for rendering Goals in the Plugins API

Summary

Functions

__resource__()

The resource name, as an atom, for this view

render(template, assigns \\ %{})

Renders the given template locally.

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

PlausibleWeb.Plugins.API.Views.Pagination

A view capable of rendering pagination metadata included in responses containing lists of objects.

Summary

Functions

__resource__()

The resource name, as an atom, for this view

render(template, assigns \\ %{})

Renders the given template locally.

render_metadata_links(meta, helper_fn, helper_fn_args, existing_params \\ %{})

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

render(template, assigns \\ %{})

View Source

@spec render(binary(), map()) :: binary()

Renders the given template locally.

Link to this function

render_metadata_links(meta, helper_fn, helper_fn_args, existing_params \\ %{})

View Source

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

PlausibleWeb.Plugins.API.Views.SharedLink

View for rendering Shared Links in the Plugins API

Summary

Functions

__resource__()

The resource name, as an atom, for this view

render(template, assigns \\ %{})

Renders the given template locally.

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

PlausibleWeb.PluginsAPICase

This module defines the test case to be used by tests that require setting up a Plugins API connection.

PlausibleWeb.Plugs.AuthorizePluginsAPI

Plug for Basic HTTP Authentication using Plugins API Tokens lookup.

Summary

Functions

call(conn, opts \\ [])

init(opts)

Functions

Link to this function

call(conn, opts \\ [])

View Source

Link to this function

init(opts)

View Source

PlausibleWeb.Plugs.MaybeDisableRegistration

Plug toggling registration according to selfhosted state.

Summary

Functions

call(conn, opts)

init(opts)

Functions

Link to this function

call(conn, opts)

View Source

Link to this function

init(opts)

View Source

PlausibleWeb.Plugs.NoRobots

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.

PlausibleWeb.RefInspector

Summary

Functions

parse(ref)

right_uri?(arg1)

Functions

Link to this function

parse(ref)

View Source

Link to this function

right_uri?(arg1)

View Source

PlausibleWeb.RemoteIp

Summary

Functions

get(conn)

Functions

Link to this function

get(conn)

View Source

PlausibleWeb.RequireAccountPlug

Summary

Functions

call(conn, opts)

init(options)

Functions

Link to this function

call(conn, opts)

View Source

Link to this function

init(options)

View Source

PlausibleWeb.RequireLoggedOutPlug

Summary

Functions

call(conn, opts)

init(options)

Functions

Link to this function

call(conn, opts)

View Source

Link to this function

init(options)

View Source

PlausibleWeb.Router

Summary

Functions

api(conn, _)

browser(conn, _)

call(conn, opts)

Callback invoked by Plug on every request.

csrf(conn, _)

flags(conn, _)

focus_layout(conn, _)

init(opts)

Callback required by Plug that initializes the router for serving web requests.

internal_stats_api(conn, _)

kaffy_browser(conn, _)

public_api(conn, _)

shared_link(conn, _)

Functions

Link to this function

api(conn, _)

View Source

Link to this function

browser(conn, _)

View Source

Link to this function

call(conn, opts)

View Source

Callback invoked by Plug on every request.

Link to this function

csrf(conn, _)

View Source

Link to this function

flags(conn, _)

View Source

Link to this function

focus_layout(conn, _)

View Source

Link to this function

init(opts)

View Source

Callback required by Plug that initializes the router for serving web requests.

Link to this function

internal_stats_api(conn, _)

View Source

Link to this function

kaffy_browser(conn, _)

View Source

Link to this function

public_api(conn, _)

View Source

Link to this function

shared_link(conn, _)

View Source

PlausibleWeb.SessionTimeoutPlug

Summary

Functions

call(conn, opts)

init(opts \\ [])

Functions

Link to this function

call(conn, opts)

View Source

Link to this function

init(opts \\ [])

View Source

PlausibleWeb.Site.MembershipController

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.

Summary

Functions

invite_member(conn, map)

invite_member_form(conn, params)

remove_member(conn, map)

transfer_ownership(conn, map)

transfer_ownership_form(conn, params)

update_role(conn, map)

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

Functions

Link to this function

invite_member(conn, map)

View Source

Link to this function

invite_member_form(conn, params)

View Source

Link to this function

remove_member(conn, map)

View Source

Link to this function

transfer_ownership(conn, map)

View Source

Link to this function

transfer_ownership_form(conn, params)

View Source

Link to this function

update_role(conn, map)

View Source

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.

PlausibleWeb.Site.MembershipView

Summary

Functions

__resource__()

The resource name, as an atom, for this view

invite_member_form.html(assigns)

render(template, assigns \\ %{})

Renders the given template locally.

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

transfer_ownership_form.html(assigns)

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

invite_member_form.html(assigns)

View Source

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Link to this function

transfer_ownership_form.html(assigns)

View Source

PlausibleWeb.SiteController

Summary

Functions

add_monthly_report_recipient(conn, map)

add_snippet(conn, params)

add_snippet_after_domain_change(conn, params)

add_spike_notification_recipient(conn, map)

add_weekly_report_recipient(conn, map)

change_domain(conn, params)

change_domain_submit(conn, map)

create_shared_link(conn, map)

create_site(conn, map)

delete_custom_domain(conn, map)

delete_google_auth(conn, params)

delete_shared_link(conn, map)

delete_site(conn, params)

disable_monthly_report(conn, params)

disable_spike_notification(conn, params)

disable_weekly_report(conn, params)

edit_shared_link(conn, map)

enable_monthly_report(conn, params)

enable_spike_notification(conn, params)

enable_weekly_report(conn, params)

forget_imported(conn, params)

import_from_google(conn, map)

import_from_google_confirm(conn, map)

import_from_google_user_metric_notice(conn, map)

import_from_google_view_id(conn, map)

import_from_google_view_id_form(conn, map)

index(conn, params)

make_private(conn, params)

make_public(conn, params)

new(conn, params)

new_shared_link(conn, params)

remove_monthly_report_recipient(conn, map)

remove_spike_notification_recipient(conn, map)

remove_weekly_report_recipient(conn, map)

reset_stats(conn, params)

settings(conn, map)

settings_custom_domain(conn, params)

settings_danger_zone(conn, params)

settings_email_reports(conn, params)

settings_funnels(conn, params)

settings_general(conn, params)

settings_goals(conn, params)

settings_integrations(conn, params)

settings_people(conn, params)

settings_props(conn, params)

settings_visibility(conn, params)

update_feature_visibility(conn, map)

update_google_auth(conn, map)

update_settings(conn, map)

update_shared_link(conn, map)

update_spike_notification(conn, map)

Functions

Link to this function

add_monthly_report_recipient(conn, map)

View Source

Link to this function

add_snippet(conn, params)

View Source

Link to this function

add_snippet_after_domain_change(conn, params)

View Source

Link to this function

add_spike_notification_recipient(conn, map)

View Source

Link to this function

add_weekly_report_recipient(conn, map)

View Source

Link to this function

change_domain(conn, params)

View Source

Link to this function

change_domain_submit(conn, map)

View Source

Link to this function

create_shared_link(conn, map)

View Source

Link to this function

create_site(conn, map)

View Source

Link to this function

delete_custom_domain(conn, map)

View Source

Link to this function

delete_google_auth(conn, params)

View Source

Link to this function

delete_shared_link(conn, map)

View Source

Link to this function

delete_site(conn, params)

View Source

Link to this function

disable_monthly_report(conn, params)

View Source

Link to this function

disable_spike_notification(conn, params)

View Source

Link to this function

disable_weekly_report(conn, params)

View Source

Link to this function

edit_shared_link(conn, map)

View Source

Link to this function

enable_monthly_report(conn, params)

View Source

Link to this function

enable_spike_notification(conn, params)

View Source

Link to this function

enable_weekly_report(conn, params)

View Source

Link to this function

forget_imported(conn, params)

View Source

Link to this function

import_from_google(conn, map)

View Source

Link to this function

import_from_google_confirm(conn, map)

View Source

Link to this function

import_from_google_user_metric_notice(conn, map)

View Source

Link to this function

import_from_google_view_id(conn, map)

View Source

Link to this function

import_from_google_view_id_form(conn, map)

View Source

Link to this function

index(conn, params)

View Source

Link to this function

make_private(conn, params)

View Source

Link to this function

make_public(conn, params)

View Source

Link to this function

new(conn, params)

View Source

Link to this function

new_shared_link(conn, params)

View Source

Link to this function

remove_monthly_report_recipient(conn, map)

View Source

Link to this function

remove_spike_notification_recipient(conn, map)

View Source

Link to this function

remove_weekly_report_recipient(conn, map)

View Source

Link to this function

reset_stats(conn, params)

View Source

Link to this function

settings(conn, map)

View Source

Link to this function

settings_custom_domain(conn, params)

View Source

Link to this function

settings_danger_zone(conn, params)

View Source

Link to this function

settings_email_reports(conn, params)

View Source

Link to this function

settings_funnels(conn, params)

View Source

Link to this function

settings_general(conn, params)

View Source

Link to this function

settings_goals(conn, params)

View Source

Link to this function

settings_integrations(conn, params)

View Source

Link to this function

settings_people(conn, params)

View Source

Link to this function

settings_props(conn, params)

View Source

Link to this function

settings_visibility(conn, params)

View Source

Link to this function

update_feature_visibility(conn, map)

View Source

Link to this function

update_google_auth(conn, map)

View Source

Link to this function

update_settings(conn, map)

View Source

Link to this function

update_shared_link(conn, map)

View Source

Link to this function

update_spike_notification(conn, map)

View Source

PlausibleWeb.SiteView

Summary

Functions

__resource__()

The resource name, as an atom, for this view

base_domain()

change_domain.html(assigns)

edit_shared_link.html(assigns)

goal_name(arg)

google_logo(assigns \\ %{})

import_from_google_confirm.html(assigns)

import_from_google_user_metric_form.html(assigns)

import_from_google_view_id_form.html(assigns)

index.html(assigns)

new.html(assigns)

new_shared_link.html(assigns)

plausible_url()

render(template, assigns \\ %{})

Renders the given template locally.

render_snippet(site)

settings_custom_domain.html(assigns)

settings_danger_zone.html(assigns)

settings_email_reports.html(assigns)

settings_funnels.html(assigns)

settings_general.html(assigns)

settings_goals.html(assigns)

settings_google_import.html(assigns)

settings_integrations.html(assigns)

settings_people.html(assigns)

settings_props.html(assigns)

settings_search_console.html(assigns)

settings_visibility.html(assigns)

shared_link_dest(site, link)

snippet.html(assigns)

snippet_after_domain_change.html(assigns)

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

with_indefinite_article(word)

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

base_domain()

View Source

Link to this function

change_domain.html(assigns)

View Source

Link to this function

edit_shared_link.html(assigns)

View Source

Link to this function

goal_name(arg)

View Source

Link to this function

google_logo(assigns \\ %{})

View Source

Link to this function

import_from_google_confirm.html(assigns)

View Source

Link to this function

import_from_google_user_metric_form.html(assigns)

View Source

Link to this function

import_from_google_view_id_form.html(assigns)

View Source

Link to this function

index.html(assigns)

View Source

Link to this function

new.html(assigns)

View Source

Link to this function

new_shared_link.html(assigns)

View Source

Link to this function

plausible_url()

View Source

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

render_snippet(site)

View Source

Link to this function

settings_custom_domain.html(assigns)

View Source

Link to this function

settings_danger_zone.html(assigns)

View Source

Link to this function

settings_email_reports.html(assigns)

View Source

Link to this function

settings_funnels.html(assigns)

View Source

Link to this function

settings_general.html(assigns)

View Source

Link to this function

settings_goals.html(assigns)

View Source

Link to this function

settings_google_import.html(assigns)

View Source

Link to this function

settings_integrations.html(assigns)

View Source

Link to this function

settings_people.html(assigns)

View Source

Link to this function

settings_props.html(assigns)

View Source

Link to this function

settings_search_console.html(assigns)

View Source

Link to this function

settings_visibility.html(assigns)

View Source

Link to this function

shared_link_dest(site, link)

View Source

Link to this function

snippet.html(assigns)

View Source

Link to this function

snippet_after_domain_change.html(assigns)

View Source

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Link to this function

with_indefinite_article(word)

View Source

PlausibleWeb.StatsController

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.

Summary

Functions

authenticate_shared_link(conn, map)

csv_export(conn, params)

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.

shared_link(conn, arg2)

Authorizes and renders a shared link

stats(conn, params)

Functions

Link to this function

authenticate_shared_link(conn, map)

View Source

Link to this function

csv_export(conn, params)

View Source

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.

Link to this function

shared_link(conn, arg2)

View Source

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

Link to this function

stats(conn, params)

View Source

PlausibleWeb.StatsView

Summary

Functions

__resource__()

The resource name, as an atom, for this view

base_domain()

large_number_format(n)

plausible_url()

pretty_stats_url(arg)

Returns a readable stats URL.

render(template, assigns \\ %{})

Renders the given template locally.

shared_link_password.html(assigns)

site_locked.html(assigns)

stats.html(assigns)

stats_container_class(conn)

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

waiting_first_pageview.html(assigns)

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

base_domain()

View Source

Link to this function

large_number_format(n)

View Source

Link to this function

plausible_url()

View Source

Link to this function

pretty_stats_url(arg)

View Source

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"

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

shared_link_password.html(assigns)

View Source

Link to this function

site_locked.html(assigns)

View Source

Link to this function

stats.html(assigns)

View Source

Link to this function

stats_container_class(conn)

View Source

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Link to this function

waiting_first_pageview.html(assigns)

View Source

PlausibleWeb.Tracker

Summary

Functions

call(conn, list)

child_spec(arg)

Returns a specification to start this module under a supervisor.

init(opts)

Functions

Link to this function

call(conn, list)

View Source

Link to this function

child_spec(arg)

View Source

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

init(opts)

View Source

PlausibleWeb.UnsubscribeController

Summary

Functions

monthly_report(conn, map)

weekly_report(conn, map)

Functions

Link to this function

monthly_report(conn, map)

View Source

Link to this function

weekly_report(conn, map)

View Source

PlausibleWeb.UnsubscribeView

Summary

Functions

__resource__()

The resource name, as an atom, for this view

render(template, assigns \\ %{})

Renders the given template locally.

success.html(assigns)

template_not_found(template, assigns)

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

Functions

Link to this function

__resource__()

View Source

The resource name, as an atom, for this view

Link to this function

render(template, assigns \\ %{})

View Source

Renders the given template locally.

Link to this function

success.html(assigns)

View Source

Link to this function

template_not_found(template, assigns)

View Source

@spec template_not_found(binary(), map()) :: no_return()

Callback invoked when no template is found. By default it raises but can be customized to render a particular template.

mix cancel_subscription

This task is meant to replicate the behavior of cancelling a subscription. On production, this action is initiated by a Paddle webhook. Currently, only the subscription status is changed with that action.

Summary

Functions

run(list)

Callback implementation for Mix.Task.run/1.

Functions

Link to this function

run(list)

View Source

Callback implementation for Mix.Task.run/1.

mix clean_clickhouse

Summary

Functions

run(_)

Callback implementation for Mix.Task.run/1.

Functions

Link to this function

run(_)

View Source

Callback implementation for Mix.Task.run/1.

mix create_free_subscription

Summary

Functions

execute(user_id)

run(arg1)

Callback implementation for Mix.Task.run/1.

Functions

Link to this function

execute(user_id)

View Source

Link to this function

run(arg1)

View Source

Callback implementation for Mix.Task.run/1.

mix download_country_database

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.

Summary

Functions

run(_)

Callback implementation for Mix.Task.run/1.

Functions

Link to this function

run(_)

View Source

Callback implementation for Mix.Task.run/1.

mix generate_referrer_favicons

Summary

Functions

run(_)

Callback implementation for Mix.Task.run/1.

Functions

Link to this function

run(_)

View Source

Callback implementation for Mix.Task.run/1.

mix pull_sandbox_subscription

Summary

Functions

run(list)

Callback implementation for Mix.Task.run/1.

Functions

Link to this function

run(list)

View Source

Callback implementation for Mix.Task.run/1.

mix send_pageview

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.

Summary

Functions

run(opts)

Callback implementation for Mix.Task.run/1.

Functions

Link to this function

run(opts)

View Source

Callback implementation for Mix.Task.run/1.