Skip to main content

Custom event goals

note

If you use the Custom Events feature, then these count towards your billable monthly pageviews.

Here are the steps you need to take to track custom events such as purchases, signups, button clicks or form submissions.

1. Change the Plausible snippet on your site

Please change the file name in the src attribute of your Plausible snippet from script.js to script.tagged-events.js. It should look like this:

<script defer data-domain="<yourdomain.com>" src="https://plausible.io/js/script.tagged-events.js"></script>

Or if you're using a proxy:

<script defer data-domain="<yourdomain.com>" src="https://yourproxy.com/script.tagged-events.js"></script>
note

If you're using outbound link clicks, file downloads or any of our other script extensions, you can combine them by changing the src attribute in the snippet. If you want to track custom events and outbound link clicks simultaneously, change the script name to script.tagged-events.outbound-links.js.

2. Add a CSS class name to the element you want to track on your site

Tag the site element you want to track with a CSS class name. How to do this varies depending on the site builder, CMS or framework you've used to build your site.

For instance, if you're using WordPress, you can click on any block element you want to track such as a button or a form. This will open up the block menu on the right-hand side of your screen.

Click on any WordPress block element you want to track such as a button or a form

You can then click on "Advanced" and add a CSS class name in the "Additional CSS class(es)" field. Add the CSS class name in this format: plausible-event-name=MyEventName. For instance, if you want to track form submissions on your contact form, you could use: plausible-event-name=Form+Submit.

Add a CSS class name in the 'Additional CSS class(es)' field

When tracking form submits, it is important to tag the <form> element itself with the plausible-event-name=... class (not the input or button element inside the form). Normally, Plausible can track button clicks, but if a button is inside a form, it will navigate to the next page often leaving not enough time for the event to finish.

note

To represent a space character in the event names, you can use a + sign. For example: plausible-event-name=Form+Submit will display as Form Submit in your dashboard

You can also add class names directly in HTML

If you can edit the raw HTML code of the element you want to track, you can also add the classes directly in HTML. For example:

<!-- before -->
<button>Click Me</button>

<!-- after -->
<button class="plausible-event-name=Button+Click">Click Me</button>

Or if your element already has a class attribute, just separate the new ones with a space:

<!-- before -->
<button class="some-existing-class">Click Me</button>

<!-- after -->
<button class="some-existing-class plausible-event-name=Button+Click">Click Me</button>

If your CMS overrides the format of your class names, Plausible will most likely not be able to track it. If that's the case, please keep reading the below instructions.

Does the element you want to track have an id attribute, or can you add one?

If the element already has an id you can use that. If it doesn't, go ahead and add a unique id attribute.

You can use this id to add the class names to your element dynamically with JavaScript. Here's the code you will have to insert in the <head> section of the page with the element you want to track:

<script>
var toTag = [
{
elementId: 'my-custom-event-element',
classes: 'plausible-event-name=<event_name> plausible-event-<property>=<value>'
}
]

document.addEventListener('DOMContentLoaded', function (_e) {
toTag.forEach(function (tagObject) {
var element = document.getElementById(tagObject.elementId)
tagObject.classes.split(' ').forEach(function (className) {
if (element) { element.classList.add(className) }
})
})
})
</script>

In this code, you will have to change the elementId and classes keys in the toTag variable. If you want to track multiple elements on one page, you can do it like this:

var toTag = [
{
elementId: 'my-custom-event-element',
classes: 'plausible-event-name=<event_name> plausible-event-<property>=<value>'
},
{
elementId: 'another-custom-event-element',
classes: 'plausible-event-name=<event_name> plausible-event-<property>=<value>'
},
// ...
]

Once you have this script running on your site, it will add your class names as soon as the HTML content is loaded on the page, and Plausible will be able to track your element.

3. Create a custom event goal in your Plausible account

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

To configure a goal, go to your website's settings in your Plausible account and visit the "Goals" section. You should see an empty list with a prompt to add a goal.

Add your first goal

Click on the "+ Add goal" button to go to the goal creation form.

Select Custom event as the goal trigger and enter the name of the custom event you are triggering. The name must match the one you added as a CSS class name on your site for conversions to appear in your analytics dashboard. So in our example where you added a CSS class name plausible-event-name=Form+Submit, the goal to add to your Plausible account is Form Submit (plus is replaced by a space).

Add your custom event goal

Next, click on the "Add goal" button and you'll be taken back to the Goals page. When you navigate back to your Plausible dashboard, you should see the number of visitors who triggered the custom event. Custom events are listed at the bottom of your dashboard and will appear as soon as the first conversion has been tracked.

4. Verify that the CSS class has been added correctly

After adding the class, please go back to your site, and verify that the class attribute got added with the exact required format. You can check it by right-clicking the element and inspecting it. This will show you the HTML code of the element.

In some cases, the tracking classes might be added to a wrapper <div> element (parent to the element you want to track), but don't worry, Plausible will still be able to track clicks on the child element if its parent has the necessary classes.

If your CMS doesn't support CSS class names or if it overrides the format of your class names, you would need to use custom JavaScript code to either trigger custom events manually or to attach the class names to your element dynamically.

Are you using Webflow? Here's our guide for how to set up custom events for form submissions and button clicks on Webflow.

And here's how to trigger custom events manually using JavaScript.

Using custom props

Custom properties can be attached to events to capture dynamic elements and to further break down goal conversions. You can use custom properties to create your custom metrics to collect and analyze data that Plausible doesn't automatically track.

You can then filter and sort your goals by custom event properties in your Plausible dashboard. For those coming from Google Analytics, custom properties are roughly the same concept as custom dimensions in Google Analytics.

Let's say you have a contact form both in the header and footer of your site. In addition to tracking submissions, you might want to know which section of your site the form was submitted on. Instead of creating separate goals for each form, you can send a custom property instead:

plausible-event-<property>=<value> allows you to define custom properties that are sent with your custom event. For example plausible-event-position=footer. The full CSS class name would look like this:

plausible-event-name=Form+Submit plausible-event-position=footer

note

To represent a space character in property values, you can use a + sign. For example: plausible-event-author=John+Doe. Spaces in custom property names (author in this example) are not allowed.

You can add as many of these classes as you want. And the names can be anything that you want.

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

Custom properties will show up automatically on your dashboard as long as you've added the goal itself. You don't need to manually add them in your settings.

Plausible will display (none) in your dashboard when you send a custom property key with no value, or null/undefined as a value.

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

Want to trigger custom events manually with custom JavaScript?

First, make sure your tracking setup includes the second line as shown below:

<script defer data-domain="<yourdomain.com>" src="https://plausible.io/js/script.js"></script>
<script>window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>

This snippet creates a global function called plausible which can be used to trigger custom events from anywhere in your code.

Here's what triggering a custom event looks like:

plausible('Signup')

The event name can be anything. As a second parameter, you can also send an object with options. The supported options at the moment are:

  • callback – a function that is called once the event is logged successfully.
  • props – an object with custom properties for the event

And here's what triggering a custom event with custom properties looks like:

plausible('Download', {props: {method: 'HTTP', Region: 'Europe'}})

This is the whole extent of the API. It's intentionally very slim so as to keep the SDK small and quick to load.

If you want to trigger form submissions, button clicks etc. you need to implement the code for that yourself. This is an example of code we use to track custom events (trial signups) on our own website.

registerForm.addEventListener('submit', function(e) {
e.preventDefault();
setTimeout(submitForm, 1000);
var formSubmitted = false;

function submitForm() {
if (!formSubmitted) {
formSubmitted = true;
registerForm.submit();
}
}

plausible('Signup', {callback: submitForm});
})

When you want to track a simple link click:

<a href="/register" data-analytics='"Register"'>Register</a>

Or if you want to track a link click with custom properties:

<a href="/register" data-analytics='"Register", {"props":{"plan":"Navigation","location":"footer"}}'>Register</a>
note

Do watch the quotes! The data-analytics tag value should have both single and double quotes as shown above.

note

If you are using a website builder (e.g. Webflow, Shopify, Wix, etc.) you might not be able to add double quotes to the data-analytics tag value. Click here to read how to use custom events in this scenario.

To be able to use the data-analytics tags and track the link clicks, you need to add the code below. You should insert this just before the closing </body> tag:

<script>
let links = document.querySelectorAll("a[data-analytics]");
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click', handleLinkEvent);
links[i].addEventListener('auxclick', handleLinkEvent);
}

function handleLinkEvent(event) {
var link = event.target;
var middle = event.type == "auxclick" && event.which == 2;
var click = event.type == "click";
while (link && (typeof link.tagName == 'undefined' || link.tagName.toLowerCase() != 'a' || !link.href)) {
link = link.parentNode;
}
if (middle || click) {
let attributes = link.getAttribute('data-analytics').split(/,(.+)/);
let events = [JSON.parse(attributes[0]), JSON.parse(attributes[1] || '{}')];
plausible(...events);
}
if (!link.target) {
if (!(event.ctrlKey || event.metaKey || event.shiftKey) && click) {
setTimeout(function () {
location.href = link.href;
}, 150);
event.preventDefault();
}
}
}
</script>

Code example for tracking form button submit events

1. Add a data-analytics attribute tag on a submit button inside a form

When you want to track a simple form submit event:

<form>
...
<button type="submit" data-analytics='"Contact"'>Send Message...</button>
</form>

Or if you want to track a form submit event with custom properties:

<form>
...
<button type="submit" data-analytics='"Contact", {"props":{"page":"home"}}'>Send Message...</button>
</form>
note

Do watch the quotes! The data-analytics tag value should have both single and double quotes as shown above.

2. Add the JavaScript that will be sending the form submit events to Plausible

To be able to use the data-analytics tag and track the form submit events, you need to add the code below. You should insert this just before the closing </body> tag:

<script>
let buttons = document.querySelectorAll("button[data-analytics]");
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', handleFormEvent);
buttons[i].addEventListener('auxclick', handleFormEvent);
}

function handleFormEvent(event) {
event.preventDefault();
let attributes = event.target.getAttribute('data-analytics').split(/,(.+)/);
let events = [JSON.parse(attributes[0]), JSON.parse(attributes[1] || '{}')];
plausible(...events);
setTimeout(function () {
event.target.form.submit();
}, 150);
}
</script>

Tracking audio and video elements

  1. Give your audio or video element an id attribute to use it with JavaScript. If it already has an id, feel free to use that instead of trackedMedia in this example.
<audio id="trackedMedia" controls src="your_audio.mp3">
Your browser doesn't support this audio element
</audio>
  1. Add the below script to your HTML page with the media element. In order to be able to use the media element with JavaScript, the script should be inserted after the media element itself. It is safe to insert it at the end of the <body> section, just before the closing </body> tag.
<script>
var mediaElement = document.getElementById('trackedMedia')

// Set a flag to ignore the case where playing has already started and is resumed from paused state
var mediaAlreadyStarted = false

// Listen to the 'play' event on the media element. Ignore if already started playing and not finished yet
mediaElement.addEventListener('play', function (e) {
if (!mediaAlreadyStarted) {
mediaAlreadyStarted = true
plausible('Media Played')
}
})

// Listen to the 'ended' event on the media element to reset the flag and start listening again
mediaElement.addEventListener('ended', function (e) {
mediaAlreadyStarted = false
})
</script>

The same code also applies for <video> elements. Feel free to replace Media Played with a more suitable name for your custom event.

Code examples for website builders such as Shopify and Wix

Some website builders do not allow you to add double quotes to attribute values. The above-presented examples will not work in those cases. Use the following workaround to track custom events in case double quotes are not allowed attribute values in your website builder. This works only when you do not intend to send custom properties.

When you want to track a simple link click:

<a href="/register" data-analytics="Register">Register</a>
note

In your website builder this translates into providing the Register value without quotes.

To be able to use the data-analytics tags and track the link clicks, you need to add the code below. You should insert this just before the closing </body> tag:

<script>
let links = document.querySelectorAll("a[data-analytics]");
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click', handleLinkEvent);
links[i].addEventListener('auxclick', handleLinkEvent);
}

function handleLinkEvent(event) {
var link = event.target;
var middle = event.type == "auxclick" && event.which == 2;
var click = event.type == "click";
while (link && (typeof link.tagName == 'undefined' || link.tagName.toLowerCase() != 'a' || !link.href)) {
link = link.parentNode;
}
if (middle || click) {
let attributeValue = link.getAttribute('data-analytics');
plausible(attributeValue);
}
if (!link.target) {
if (!(event.ctrlKey || event.metaKey || event.shiftKey) && click) {
setTimeout(function () {
location.href = link.href;
}, 150);
event.preventDefault();
}
}
}
</script>