## 1. Project Overview & Quickstart (plausible/funnel-analysis)

# funnel-analysis

Open-source repository plausible/funnel-analysis

### Repository Details
- **Repository:** [plausible/funnel-analysis](https://github.com/plausible/funnel-analysis)
- **Primary Language:** Code

*Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.*

## 2. Official Technical Reference & Guides (plausible/docs)

## File: README.md

# Website

This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator.

### Installation

```bash
npm install
```

### Local Development

```bash
npm run start
```

This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server.

To run alongside [plausible/analytics](https://github.com/plausible/analytics/), also run caddy in a different terminal:

```bash
caddy run --config Caddyfile
```

Docs are served on localhost:8001/docs in that case.

### Build

```bash
$ npm run build
```

This command generates static content into the `build` directory and can be served using any static contents hosting service.

### Deployment

```bash
$ GIT_USER=<Your GitHub username> USE_SSH=true npm run deploy
```

If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.

---

## File: docs/custom-props/for-custom-events.md

---
title: Custom properties for events
---

When you track a custom event, you can include property key-value pairs alongside it. This lets you capture additional context about the event, for example which pricing plan a visitor selected when clicking a sign-up button, or which content variation they were shown.

### Using HTML class attributes

If you're using Plausible's class-based event tracking, add properties using the format `plausible-event-=<value>` on the same element:

```html
...
...
```

Both buttons trigger the same `Sign Up` event, but the `plan` property will differ between them.

:::tip
To represent a space in a property value, use a `+` sign. Space characters are not valid in class attributes.
:::

You can add up to 30 properties per event by separating each class with a space.

### Using the JavaScript method

If you're triggering events manually with JavaScript, pass properties as a second argument:

```js
plausible('Sign Up', {props: {plan: 'pro', variation: 'homepage-cta'}})
```

## Create property-filtered goals

When you [create a goal from a custom event](goal-conversions.md) in your site settings, you can optionally attach up to three property constraints to that goal definition.

A property-filtered goal only counts an event when both the event name and the property values match. For example, you can create a `Pro Sign Up` goal that only fires when a `Sign Up` event includes `plan=pro`. A separate `Starter Sign Up` goal would match `plan=starter`.

This is distinct from simply sending properties with your events:

- **Sending a property with an event** records raw data. You can filter and analyze it in the dashboard after the fact.
- **Attaching a property to a goal** makes the property part of the goal's definition. The goal only counts when that specific property value is present. It becomes a discrete conversion metric, not a filtered view of existing data.

## Use property-filtered goals in funnels

Funnels in Plausible are built from goals, not raw events. Each funnel step must map to a defined goal.

If you want a funnel step to represent a specific variation of an event rather than all instances of it, you need a goal with the property constraint built in.

For example, a funnel that tracks:

1. Visitor views the pricing page
2. Visitor clicks the Pro plan sign-up button
3. Visitor completes registration

Step 2 requires a goal that matches only `Sign Up` events where `plan=pro`. Without the property constraint on the goal, that step would count any sign-up button click on the site regardless of which plan was selected.

Once you've created property-filtered goals, you can [add them as funnel steps](funnel-analysis.md) the same way as any other goal.

---

## File: docs/custom-props/for-pageviews.md

---
title: Attach custom properties to pageviews
---

import useBaseUrl from '@docusaurus/useBaseUrl';

## Add your custom properties to your Plausible snippet

You can add custom properties by updating your Plausible snippet.

To add properties that attach to every tracked event, update the `plausible.init` call to pass `customProperties` option:

```javascript
plausible.init({
  // ... Other initialization options
  customProperties: {
    author: "John Doe",
    type: "blog-post"
  }
})
```

You're now tracking custom properties alongside pageviews.

## Advanced: Dynamically setting custom properties

To include dynamic data for custom properties, set `customProperties` to be a function. This function will be called for every event.

For example:

```js
plausible.init({
  // ... Other initialization options
  customProperties: function(eventName) {
    if (eventName == "pageview") {
      return {
        author: "John Doe",
        title: document.title
      }
    }

    return {}
  }
})
```

---

## File: docs/custom-props/introduction.md

---
title: Custom properties
---

import useBaseUrl from '@docusaurus/useBaseUrl';
import PlanFeatureNote from '@site/src/components/PlanFeatureNote';

Custom properties let you collect and analyze metrics that Plausible doesn't track automatically. You can attach them to pageviews or custom events to create your own segments and filters. If you're coming from Google Analytics, custom properties are equivalent to [custom dimensions](https://plausible.io/blog/custom-dimensions-analytics).



For example, say you want to track your blog posts by `author`. Every time a visitor lands on one of the posts, you can send a pageview with the property `author=...`. You can then filter your Plausible dashboard by a specific author to see all the relevant stats for the posts published by that particular writer.

Other examples:

* Filter content by the publication date, page type, ID, tag or category
* Filter visitors by login status or user role
* Filter visitors by language they're viewing your website in
* Filter visitors by how many prefer or use the dark mode
* Filter visitors by level completions or high score if you're a game developer
* Filter by the segment that saw a particular variation of your site which is useful for A/B testing

## Personally identifiable information

Note that you must ensure that no personally identifiable information (PII) is sent to Plausible with custom properties. PII is information that could be used on its own to identify, contact, or precisely locate an individual. This includes:

* full names or usernames
* email addresses
* mailing addresses
* phone numbers
* credit card information
* passport numbers
* precise locations
* IP addresses
* pseudonymous cookie IDs, advertising IDs or other pseudonymous end user identifiers

If you're confused whether the information you're sending to us qualifies as PII, look at the [explanations and examples](https://plausible.io/blog/pii-examples) in our guide.

## `(none)` values

Plausible will display `(none)` in your dashboard when you send a custom property key with no value, or `null`/`undefined` as a value. Also, when you send one event with a property (e.g. `author`) and another event with the same name, but without the `author` property, then you will also see the `(none)` value because the property has not been sent with every event.

When you filter your dashboard by a particular custom event and look at the **Properties** tab, you should only see `(none)` if some of those events were sent without the property. However, if you're viewing the **Properties** tab without any custom event filter, it returns all the events in your dashboard (including all regular pageviews) and many of these events may not have a property attached. This is why you see the `(none)` value.

## Accepted values

Custom properties only accept scalar values such as strings, numbers and booleans. Data structures such as objects, arrays etc. aren't accepted.

## Limits

* You can send up to 30 different custom properties per event
* The number of allowed characters for a property name is 300
* The limit for custom property values is 2000 characters 

## Set up custom property tracking

Please check out the following sections of instructions for setting up the tracking and analyzing the data in your dashboard:

* [Attach custom properties to pageviews](/custom-props/for-pageviews)
* [Attach custom properties to custom events](/custom-props/for-custom-events)
* [Analyze your traffic by custom properties](/custom-props/props-dashboard)

---

## File: docs/custom-props/props-dashboard.md

---
title: Segment your traffic by custom properties
---

import useBaseUrl from '@docusaurus/useBaseUrl';

## 1. Configure custom properties in your site settings

When you send custom properties to Plausible, they won't show up in your dashboard automatically. You'll have to configure the custom property for the numbers to show up.

To configure a property, go to the [site settings](website-settings.md) in your Plausible account and visit the **Custom Properties** section. You should see an empty list with a prompt to add a property. You also have the option to add all properties that you've already sent with one click.

## 2. Filter your stats by custom properties

As soon as you've recorded at least one custom event or one pageview with a custom property attached to it, you'll be able to see an option to filter by that property in your Plausible dashboard.

At the bottom of your dashboard, in the **Goals** section you can switch to the **Properties** tab. There you can select a specific custom property to see the related data. After you filter the dashboard by one particular custom property, you can segment your stats even further by adding additional custom properties to the filter. Keep clicking on custom properties to add more segments.

Clicking on any of your custom events in the **Goals** section will also take you to the **Properties** tab to display the properties attached to that specific custom event.





### You can also use the filter menu to segment further

You can also open [the filter dropdown menu](filters-segments.md) in the top right of your dashboard and select **Property**.

In that view you can interact with the dropdown fields, where Plausible will automatically provide filtering suggestions based on the custom properties that we have recorded. The suggestions take into account the selected time period and other filters that you've already applied to your stats. You can choose between "is", "is not", "does not contain" and "contains" as options when selecting the custom property to filter by. 

You can filter by multiple custom properties too. Click on the **Add another** link to add another custom property to the filter. Choose the custom properties that you want to segment your audience by and click on the **Apply Filter** button to filter your dashboard.

---

## File: docs/proxy/guides/akamai.md

---
displayed_sidebar: someSidebar
title: Proxying Plausible through Akamai
sidebar_label: Akamai
---

We've removed old proxying instructions due to them being out of date. [See our general proxying guide](/proxy/introduction).

---

## File: docs/proxy/guides/apache.md

---
title: Proxying Plausible through Apache HTTP Server
sidebar_label: Apache
---

If you're already running Apache HTTP Server as your main web server or reverse proxy, you can also configure it to proxy your analytics. Start by adjusting your configuration as shown in the next step.

:::tip Don't want to manage your own proxy? We can handle it for you
Our managed proxy lets you send analytics through your own domain name as a first-party connection. All you need to do is set up a CNAME record using the instructions we'll send you and update the snippet on your site. We'll take care of everything else. [Contact us for details](https://plausible.io/contact).
:::

## Step 1: Enable the required modules

```bash
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod ssl
```

## Step 2: Get your snippet

In the **Site Installation** area of the **General** section in your [site settings](website-settings.md) you can see
the snippet specific for your site. It will look similar to the following:

```html
<script async src="https://plausible.io/js/pa-XXXXX.js"></script>
<script>
  window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};
  plausible.init()
</script>
```

Your snippet will have a different script location than the example above. Look for the `https://plausible.io/js/pa-XXXXX.js` part in your snippet - that's the personalized location for your site's script. Mark it down for subsequent steps.

## Step 3: Update your config
``` title="apache-vhost.conf"
<VirtualHost *:80>
  ServerName website.com

  ProxyRequests off
  ProxyPreserveHost off
  SSLProxyEngine on

  <Location /js/script.js>
    ProxyPass https://plausible.io/js/pa-XXXXX.js
    ProxyPassReverse https://plausible.io/js/pa-XXXXX.js
  </Location>

  <Location /api/event>
    ProxyPass https://plausible.io/api/event
    ProxyPassReverse https://plausible.io/api/event
  </Location>

</VirtualHost>
```

Replace `https://plausible.io/js/pa-XXXXX.js` in this config with script location from step 2.

## Step 4: Adjust your deployed script

With the above config in place, you can change the script tag on your site as follows:

```html
<script async src="/js/script.js"></script>
<script>
  window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};
  plausible.init({
    endpoint: "/api/event"
  })
</script>
```

That's it! You're now using a proxy.

---

## File: docs/proxy/guides/caddy.md

---
title: Proxying Plausible through Caddy
sidebar_label: Caddy
---

If you're already running Caddy as your main web server or reverse proxy, you can also configure it to proxy your analytics. Start by adjusting your configuration as shown in the next step.

:::tip Don't want to manage your own proxy? We can handle it for you
Our managed proxy lets you send analytics through your own domain name as a first-party connection. All you need to do is set up a CNAME record using the instructions we'll send you and update the snippet on your site. We'll take care of everything else. [Contact us for details](https://plausible.io/contact).
:::


## Step 1: Get your snippet

In the **Site Installation** area of the **General** section in your [site settings](website-settings.md) you can see
the snippet specific for your site. It will look similar to the following:

```html
<script async src="https://plausible.io/js/pa-XXXXX.js"></script>
<script>
  window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};
  plausible.init()
</script>
```

Your snippet will have a different script location than the example above. Look for the `https://plausible.io/js/pa-XXXXX.js` part in your snippet - that's the personalized location for your site's script. Mark it down for subsequent steps.

## Step 2: Update your Caddyfile

Add the following to your Caddyfile:

``` title="Caddyfile"
@plausible path /js/script.js /api/event
handle @plausible {
	# Use path from step 1
	rewrite /js/script.js /js/pa-XXXXX.js
	reverse_proxy https://plausible.io {
		header_up Host {http.reverse_proxy.upstream.hostport}
	}
}
```

## Step 3: Adjust your deployed script

With the above config in place, you can change the script tag on your site as follows:

```html
<script async src="/js/script.js"></script>
<script>
  window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};
  plausible.init({
    endpoint: "/api/event"
  })
</script>
```

Courtesy: [Francis Lavoie](https://caddy.community/u/francislavoie/summary) (@francislavoie) on a [Caddy Community post](https://caddy.community/t/how-to-proxy-plausible-analytics/12679/5).

---

## File: docs/proxy/guides/cloudflare.md

---
title: Proxying Plausible through Cloudflare
sidebar_label: Cloudflare
---

import useBaseUrl from '@docusaurus/useBaseUrl';

You can use Cloudflare Workers to proxy your Plausible Analytics requests. Cloudflare Workers offers free service for up to 100,000 requests per day.
All you need to set it up is a free Cloudflare account. Here's the step-by-step process for creating a proxy.

:::tip Don't want to manage your own proxy? We can handle it for you
Our managed proxy lets you send analytics through your own domain name as a first-party connection. All you need to do is set up a CNAME record using the instructions we'll send you and update the snippet on your site. We'll take care of everything else. [Contact us for details](https://plausible.io/contact).
:::

Step 0: Sign up for a free Cloudflare account if you don't have an account already and add your site.

## Step 1: Create a worker

In your Cloudflare account, click on the "Compute (Workers" > 'Workers & Pages' section in the sidebar to get the 'Overview' page. Choose "Start with Hello World!" and then click on "Get Started" to start configuring your proxy.





## Step 2 (Optional): You can change your service name

This is optional but you can change the service name to give your worker a more meaningful name. It's also fine to keep the random name that Cloudflare generates by default. Then click on the 'Deploy' button.





## Step 3: Get your snippet

In the **Site Installation** area of the **General** section in your [site settings](website-settings.md) you can see
the snippet specific for your site. It will look similar to the following:

```html
<script async src="https://plausible.io/js/pa-XXXXX.js"></script>
<script>
  window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};
  plausible.init()
</script>
```

Your snippet will have a different script location than the example above. Look for the `https://plausible.io/js/pa-XXXXX.js` part in your snippet - that's the personalized location for your site's script. Mark it down for subsequent steps.

## Step 4: Paste the following code

Next click on the 'Edit Code' button, remove the default code that Cloudflare presents and paste the code that we present below instead.





:::tip
Change the folder name in the first two lines of the code below. This makes your proxy harder to discover and block, especially if you're not hosting your site on the Cloudflare CDN.
:::

In the **ProxyScript** line, change `https://plausible.io/js/pa-XXXXX.js` to your script location from step 3.

In the **ScriptName** line, change the `/js/` to whatever you wish. Say `/your-folder-name/`. Then the location in the code would be `/your-folder-name/script.js`.

In the **Endpoint** line, change the `/api/` to whatever you want. It can be the same as above but you can also choose something different. If you choose `/your-folder-name/`, then the full location would be `/your-folder-name/event`.

:::warning
Avoid words like 'plausible', 'analytics', 'tracking', 'stats' in path names as they may be blocked.
:::

```js title="cloudflare-worker.js"
const ProxyScript = 'https://plausible.io/js/pa-XXXXX.js'
const ScriptName = '/js/script.js';
const Endpoint = '/api/event';

const ScriptWithoutExtension = ScriptName.replace('.js', '')

addEventListener('fetch', event => {
    event.passThroughOnException();
    event.respondWith(handleRequest(event));
})

async function handleRequest(event) {
  const pathname = new URL(event.request.url).pathname
  const [baseUri, ...extensions] = pathname.split('.')

  if (baseUri.endsWith(ScriptWithoutExtension)) {
      return getScript(event, extensions)
  } else if (pathname.endsWith(Endpoint)) {
      return postData(event)
  }
  return new Response(null, { status: 404 })
}

async function getScript(event, extensions) {
    let response = await caches.default.match(event.request);
    if (!response) {
        response = await fetch(ProxyScript);
        event.waitUntil(caches.default.put(event.request, response.clone()));
    }
    return response;
}

async function postData(event) {
    const request = new Request(event.request);
    request.headers.delete('cookie');
    return await fetch("https://plausible.io/api/event", request);
}
```

Once you've added the above code to the worker, you can click on the blue 'Save and Deploy' button on the top right. On the confirmation message, do confirm that you want to save and deploy your worker by clicking on the 'Save and Deploy' button again.





## Step 4: Make sure the script is accessible

Now, the Plausible script should be accessible at the following URL:

```
https://your-worker-name.your-cloudflare-zone.workers.dev/your-folder-name/script.js
```

If you can load this URL and see some JavaScript code, you should be good to go to the following step.

## Step 5: Integrate a new snippet into your site header

Once you have the URL for your script, you can replace your Plausible Analytics script tag in the Header (`<head>`) section of your site with the proxied snippet. This is how the new snippet should look like (make sure to edit it to have the correct domain name of your site and the correct URL to the proxied file):

```html
<script async src="https://your-worker-name.your-cloudflare-zone.workers.dev/your-folder-name/script.js"></script>
<script>
  window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};
  plausible.init({
    endpoint: "https://your-worker-name.your-cloudflare-zone.workers.dev/your-folder-name/event"
  })
</script>
```

That's it! You're now counting your website stats using a proxy.

## Step 6 (Optional): Run proxy as a subdirectory

If you're hosting your site on the Cloudflare CDN, you can run the proxy as a subdirectory installation to avoid a third-party
request to the `workers.dev` domain. This is completely optional but it can make your URLs look much cleaner and avoid third-party
requests.

In your Cloudflare account, click on the 'Workers & Pages' section in the sidebar. Then, click on the worker that you have just created and then choose the 'Triggers' options in the 'Settings' section of your worker. Next click on the 'Add route' button on the right-hand side of the 'Route' heading.

Next, in the 'Route' field enter the URL prefix where you would like to host the proxy. In this example, we'll install the proxy on the `example.com` domain, and we'll use `qwerty` as the subdirectory name. You can choose any name for the subdirectory, but it's a good idea to avoid words like 'analytics' and 'tracking'.

* Route: `*example.com/qwerty/*`

Then select your domain name in the 'Zone' field. Then click on the 'Add route' button. After clicking 'Add route', the script should be accessible at the subdirectory URL of your site: `https://example.com/qwerty/your-folder-name/script.js`.

At this point you can change your Plausible script tag in your site header to reference the new URL. It's also important to specify the `endpoint` option in `plausible.init()` to make sure data is sent through the worker as well. The new snippet in your site header should look like this:

```html
<script async src="/qwerty/your-folder-name/script.js"></script>
<script>
  window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};
  plausible.init({
    endpoint: "/qwerty/your-folder-name/event"
  })
</script>
```

Notice that since the script tag is installed on the same domain as the website itself, there's no need to specify the hostname in script `src` and plausible.init `endpoint` attribute. A relative path will work just fine.

---

## File: docs/proxy/guides/cloudfront.md

---
displayed_sidebar: someSidebar
title: Proxying Plausible through CloudFront
sidebar_label: CloudFront
---

We've removed old proxying instructions due to them being out of date. [See our general proxying guide](/proxy/introduction).