Overview
Plausible is a lightweight, privacy-first analytics platform designed as a simple alternative to Google Analytics. With a script that's under 1KB, Plausible focuses on essential metrics while respecting user privacy - no cookies, no personal data collection, and full GDPR/CCPA compliance by default.
Unlike complex analytics platforms, Plausible's event tracking is intentionally simple: custom events with optional properties. This minimalist approach makes implementation straightforward while still providing insights into user behavior. Plausible is ideal for teams that want actionable data without the complexity or privacy concerns of traditional analytics.
Event Model
How Plausible Events Work
Plausible events consist of:
- Event Name: What happened (e.g., "Signup", "Download", "Purchase")
- Custom Properties (optional): Additional context via
props(key-value pairs)
Basic Event Structure:
plausible('Signup')
Event with Properties:
plausible('Download', {
props: {
file: 'whitepaper.pdf',
location: 'blog'
}
})
Key Characteristics
- Lightweight and fast (< 1KB script)
- No cookies required
- No personal data collected
- Events are tied to pageviews in session
- Custom properties for additional context
- Revenue tracking built-in
Limits
- Event name: 120 characters (recommended < 30 for readability)
- Property name: 300 characters
- Property value: 2000 characters
- Properties per event: 30 custom properties max
- Events: Unlimited (billed by monthly pageviews + events)
Standard Events
Plausible automatically tracks pageviews and provides special built-in events.
Automatic Pageview Tracking
<!-- Just include the script - pageviews tracked automatically -->
<script defer data-domain="yourdomain.com" src="https://plausible.io/js/script.js"></script>
Automatic pageviews include:
- Page URL
- Referrer source
- Device type (desktop, mobile, tablet)
- Browser
- Operating system
- Country (no city/precise location)
Outbound Link Clicks
Enable automatic outbound link tracking:
<!-- Include outbound link tracking extension -->
<script defer data-domain="yourdomain.com" src="https://plausible.io/js/script.outbound-links.js"></script>
Tracks all external links automatically:
- Event name:
Outbound Link: Click - Property:
url(destination URL)
File Downloads
Enable automatic file download tracking:
<!-- Include file downloads extension -->
<script defer data-domain="yourdomain.com" src="https://plausible.io/js/script.file-downloads.js"></script>
Tracks common file types automatically (.pdf, .xlsx, .docx, .zip, etc.):
- Event name:
File Download - Property:
url(file URL)
404 Error Pages
Track 404 errors:
<!-- Include 404 tracking -->
<script defer data-domain="yourdomain.com" src="https://plausible.io/js/script.404.js"></script>
Add to 404 page:
<script>plausible('404', { props: { path: document.location.pathname } });</script>
Hash-based Routing (SPA)
For single-page applications:
<!-- Track hash changes as pageviews -->
<script defer data-domain="yourdomain.com" src="https://plausible.io/js/script.hash.js"></script>
Custom Events
Custom events track specific user interactions important to your business.
Basic Custom Events
// Simple event
plausible('Signup');
// Button click
plausible('CTA Click');
// Feature usage
plausible('Feature Used');
Events with Custom Properties
Add context with properties:
// Event with single property
plausible('Download', {
props: {
file: 'pricing-guide.pdf'
}
});
// Event with multiple properties
plausible('Signup', {
props: {
method: 'email',
plan: 'trial',
source: 'homepage'
}
});
// Rich property context
plausible('Video Played', {
props: {
title: 'Product Demo',
duration: '180',
quality: '1080p',
location: 'homepage'
}
});
Event Naming Best Practices
Good Names:
Signup(clear, concise)Purchase(specific action)Contact Form Submit(descriptive)Feature: Export Data(namespaced)
Avoid:
event1(not descriptive)user_clicked_the_signup_button_on_homepage(too long)SignUpvsSignup(be consistent with casing)
Implementation Examples
Button Clicks:
<button Click', {props: {button: 'signup', location: 'hero'}})">
Sign Up Free
</button>
Form Submissions:
document.getElementById('contact-form').addEventListener('submit', function(e) {
plausible('Contact Form Submit', {
props: {
formType: 'contact',
source: 'footer'
}
});
});
Feature Usage:
function enableDarkMode() {
// Enable dark mode logic...
plausible('Feature Toggle', {
props: {
feature: 'dark_mode',
state: 'enabled'
}
});
}
Ecommerce Events
Plausible supports ecommerce tracking through custom events with revenue properties.
Revenue Tracking
Use the special revenue property:
// Basic purchase with revenue
plausible('Purchase', {
props: {
revenue: '149.99' // Must be string
}
});
Note: Revenue must be passed as a string, not a number.
Product Browsing
// Product viewed
plausible('Product View', {
props: {
product_id: 'SKU_12345',
product_name: 'Wireless Mouse',
category: 'Electronics',
price: '29.99'
}
});
// Category browsed
plausible('Category View', {
props: {
category: 'Electronics',
product_count: '24'
}
});
Cart Events
// Add to cart
plausible('Add to Cart', {
props: {
product_id: 'SKU_12345',
product_name: 'Wireless Mouse',
price: '29.99',
quantity: '1'
}
});
// Remove from cart
plausible('Remove from Cart', {
props: {
product_id: 'SKU_12345',
reason: 'changed_mind'
}
});
// Cart viewed
plausible('Cart View', {
props: {
cart_total: '89.97',
item_count: '3'
}
});
Checkout Process
// Checkout started
plausible('Checkout Started', {
props: {
cart_total: '89.97',
item_count: '3',
checkout_type: 'guest'
}
});
// Payment method selected
plausible('Payment Method Selected', {
props: {
method: 'credit_card'
}
});
// Purchase completed
plausible('Purchase', {
props: {
revenue: '107.17', // Required for revenue tracking
order_id: 'ORDER_12345',
item_count: '3',
payment_method: 'credit_card',
shipping_method: 'standard',
currency: 'USD'
}
});
Subscription Events
// Trial started
plausible('Trial Started', {
props: {
plan: 'Pro',
duration: '14_days'
}
});
// Subscription purchased
plausible('Subscription', {
props: {
revenue: '29.99',
plan: 'Pro',
billing: 'monthly'
}
});
// Subscription cancelled
plausible('Subscription Cancelled', {
props: {
plan: 'Pro',
reason: 'too_expensive',
months_active: '6'
}
});
Refunds
plausible('Refund', {
props: {
revenue: '-107.17', // Negative value for refund
order_id: 'ORDER_12345',
reason: 'not_as_expected'
}
});
User Properties
Plausible doesn't support persistent user properties like other platforms. Instead, you can send context with each event using custom properties.
Per-Event User Context
// Include user attributes with each event
plausible('Feature Used', {
props: {
feature: 'advanced_reports',
user_plan: 'premium', // User context
user_role: 'admin', // User context
account_age_days: '45' // User context
}
});
Session-Level Context
For consistent properties across events, set them programmatically:
// Store user context
const userContext = {
plan: 'premium',
role: 'admin',
company_size: '50-100'
};
// Include in every event
function trackEvent(eventName, additionalProps = {}) {
plausible(eventName, {
props: {
...userContext,
...additionalProps
}
});
}
// Usage
trackEvent('Feature Used', {
feature: 'export_data'
});
Authenticated Users
Since Plausible doesn't store user IDs, include user context when relevant:
// After login
plausible('Login', {
props: {
method: 'email',
user_type: 'returning',
account_tier: 'premium'
}
});
// Feature usage with user context
plausible('Report Generated', {
props: {
report_type: 'sales',
user_tier: 'enterprise',
user_industry: 'technology'
}
});
Event Properties
Custom properties (props) provide context for events.
Property Best Practices
Good Properties:
plausible('Video Played', {
props: {
video_title: 'Getting Started',
video_duration: '180',
video_quality: '1080p',
player_location: 'homepage',
autoplay: 'false'
}
});
Avoid:
// Don't use inconsistent naming
props: {
videoTitle: 'Tutorial', // camelCase
video_duration: '180', // snake_case - pick one!
'Video Quality': '1080p' // spaces
}
// Don't send sensitive data
props: {
email: 'user@example.com', // PII
ip_address: '192.168.1.1' // PII
}
Property Data Types
All property values should be strings:
// Correct - all strings
plausible('Purchase', {
props: {
revenue: '149.99', // String, not number
quantity: '3', // String, not number
item_count: '5', // String, not number
is_first_purchase: 'true' // String, not boolean
}
});
// Incorrect - will cause errors
plausible('Purchase', {
props: {
revenue: 149.99, // Number - wrong!
quantity: 3, // Number - wrong!
is_first_purchase: true // Boolean - wrong!
}
});
Common Property Patterns
Content Engagement:
plausible('Article Read', {
props: {
article_title: 'Analytics Guide',
category: 'Tutorial',
read_time: '8',
word_count: '2500',
author: 'Jane Doe'
}
});
Form Interactions:
plausible('Form Submit', {
props: {
form_name: 'contact',
form_location: 'footer',
fields_filled: '5',
time_spent: '45'
}
});
Feature Usage:
plausible('Export', {
props: {
export_type: 'csv',
record_count: '1000',
file_size: '2.5mb',
export_source: 'reports_page'
}
});
Implementation Methods
1. JavaScript Snippet (Standard)
Basic Installation:
<script defer data-domain="yourdomain.com" src="https://plausible.io/js/script.js"></script>
Self-Hosted:
<script defer data-domain="yourdomain.com" src="https://your-plausible-server.com/js/script.js"></script>
With Extensions:
<!-- Multiple extensions combined -->
<script defer
data-domain="yourdomain.com"
src="https://plausible.io/js/script.outbound-links.file-downloads.hash.js">
</script>
2. Custom Events in Code
Vanilla JavaScript:
// Check if Plausible is loaded
if (window.plausible) {
plausible('Event Name', { props: { key: 'value' } });
}
// Or use the queue
window.plausible = window.plausible || function() {
(window.plausible.q = window.plausible.q || []).push(arguments);
};
plausible('Event Name');
import { useEffect } from 'react';
function SignupButton() {
const handleSignup = () => {
// Track event
window.plausible?.('Signup', {
props: {
source: 'homepage',
plan: 'trial'
}
});
// Proceed with signup logic...
};
return <button Up</button>;
}
<template>
<button @click="trackAndSubmit">Submit Form</button>
</template>
<script>
export default {
methods: {
trackAndSubmit() {
window.plausible?.('Form Submit', {
props: {
formType: 'contact',
source: this.$route.path
}
});
// Form submission logic...
}
}
}
</script>
3. Server-Side Events API
Plausible provides an Events API for server-side tracking:
Node.js:
const fetch = require('node-fetch');
async function trackPlausibleEvent(domain, eventName, url, props = {}) {
await fetch('https://plausible.io/api/event', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': 'YourApp/1.0'
},
body: JSON.stringify({
domain: domain,
name: eventName,
url: url,
props: props
})
});
}
// Usage
trackPlausibleEvent('yourdomain.com', 'Subscription', 'https://yourdomain.com/subscribe', {
revenue: '29.99',
plan: 'pro',
billing: 'monthly'
});
Python:
import requests
def track_plausible_event(domain, event_name, url, props=None):
payload = {
'domain': domain,
'name': event_name,
'url': url
}
if props:
payload['props'] = props
response = requests.post(
'https://plausible.io/api/event',
json=payload,
headers={'User-Agent': 'YourApp/1.0'}
)
return response.status_code
# Usage
track_plausible_event(
'yourdomain.com',
'Payment Processed',
'https://yourdomain.com/checkout/success',
{'revenue': '149.99', 'payment_method': 'stripe'}
)
cURL:
curl -X POST https://plausible.io/api/event \
-H 'Content-Type: application/json' \
-H 'User-Agent: YourApp/1.0' \
-d '{
"domain": "yourdomain.com",
"name": "Purchase",
"url": "https://yourdomain.com/checkout/success",
"props": {
"revenue": "149.99",
"order_id": "ORDER_12345"
}
}'
4. Google Tag Manager
Setup:
Event Tracking Tag:
<script>
plausible('{{Event Name}}', {
props: {
{{Property 1}}: '{{Value 1}}',
{{Property 2}}: '{{Value 2}}'
}
});
</script>
Debugging & Validation
1. Browser Console
// Check if Plausible is loaded
console.log(typeof plausible);
// Test event (doesn't actually send)
console.log('Tracking event: Signup');
plausible('Signup', { props: { plan: 'trial' } });
2. Network Tab Inspection
DevTools Network Tab:
Filter: /api/event
Look for: POST requests to plausible.io/api/event
Status: 202 Accepted (successful)
Request Payload:
{
"n": "Signup",
"u": "https://yourdomain.com/signup",
"d": "yourdomain.com",
"p": "{\"plan\":\"trial\",\"source\":\"homepage\"}"
}
3. Plausible Dashboard
Real-Time Events:
- Log into Plausible dashboard
- Select your site
- Click "Current Visitors" (top right)
- Perform action on your site
- See event appear in real-time
Goal Conversions:
- Go to Settings > Goals
- Add custom event goal
- View conversions in main dashboard
- Click goal to see property breakdown
4. Test Mode
Use localhost or test domain:
<!-- Test on localhost -->
<script defer data-domain="localhost" src="https://plausible.io/js/script.js"></script>
Events will be tracked but separated from production data.
5. Goal Setup Validation
Create a goal for your event:
- Settings > Goals > Add Goal
- Goal Type: Custom Event
- Event Name: (exact match of your event name)
- Save
Trigger the event and verify it appears in the Goals section.
Best Practices
Event Naming
Do:
- Use clear, descriptive names:
Signup,Purchase,Download - Be consistent with casing: always
Signupor alwaysSign Up - Use namespacing for related events:
Video: Play,Video: Pause - Keep names under 30 characters for readability
Don't:
- Use vague names:
Event,Action,Click - Include variable data:
Signup_User_12345 - Use special characters excessively
- Create hundreds of unique event names
Property Usage
Do:
- Use snake_case or camelCase consistently
- Convert all values to strings
- Include meaningful context
- Document property definitions
- Limit to essential properties (< 10 per event)
Don't:
- Mix data types (use strings for everything)
- Send PII (email, phone, address)
- Exceed 30 properties per event
- Use inconsistent property names
Revenue Tracking
Do:
// Always use string for revenue
plausible('Purchase', {
props: {
revenue: '149.99', // String!
currency: 'USD',
order_id: 'ORDER_12345'
}
});
Don't:
// Don't use numbers
plausible('Purchase', {
props: {
revenue: 149.99 // Will cause errors!
}
});
Privacy & Compliance
Already compliant by default:
- No cookies used
- No personal data collected
- No cross-site tracking
- IP addresses anonymized
- GDPR/CCPA compliant out-of-the-box
Additional privacy:
<!-- Exclude specific pages from tracking -->
<script defer
data-domain="yourdomain.com"
data-exclude="/admin/*,/account/*"
src="https://plausible.io/js/script.js">
</script>
Performance
Lightweight by design:
- Script size: < 1KB
- Loads asynchronously
- Doesn't block page rendering
- Minimal performance impact
Optimization:
<!-- Use defer attribute (recommended) -->
<script defer data-domain="yourdomain.com" src="https://plausible.io/js/script.js"></script>
<!-- Self-host for even faster loads -->
<script defer data-domain="yourdomain.com" src="/js/script.js"></script>
Goal Configuration
Create goals for key events:
- Go to Settings > Goals
- Add custom event goals
- Use exact event name matching
- Monitor conversion rates
- Set up funnel analysis (premium feature)
Data Organization
Group related events:
// Video events
plausible('Video: Play', { props: { title: 'Demo' } });
plausible('Video: Pause', { props: { title: 'Demo' } });
plausible('Video: Complete', { props: { title: 'Demo' } });
// Form events
plausible('Form: Start', { props: { form: 'contact' } });
plausible('Form: Submit', { props: { form: 'contact' } });
Testing Strategy
- Development: Test on localhost
- Staging: Use separate domain/property
- Production: Monitor goals and conversions
- Validation: Check network requests and dashboard
- Documentation: Maintain event catalog
Additional Resources: