Plausible is a lightweight, privacy-first analytics platform that tracks website usage without cookies, personal data collection, or consent banners. The entire tracking script is under 1KB (compared to Google Analytics at ~45KB), and it provides a clean dashboard focused on essential metrics: visitors, page views, bounce rate, visit duration, and traffic sources. The tradeoff for simplicity is limited customization -- Plausible does not support user-level tracking, session replay, or complex event properties. A proper implementation focuses on script deployment, custom goal definitions, and ad blocker mitigation.
Why Proper Implementation Matters
Simplicity Requires Deliberate Configuration
Plausible tracks basic metrics automatically, but anything beyond pageviews requires explicit setup:
- Custom events (button clicks, form submissions, signups) are not tracked unless you define goals and add JavaScript calls
- Revenue tracking requires manual event instrumentation with monetary values
- Outbound link tracking requires a script extension (
plausible.outbound-links.js) - File download tracking requires a separate script extension
- 404 page tracking requires adding a dedicated script
Without configuring these extensions and goals, you get pageview data and nothing else.
Ad Blocker Impact is Significant
Plausible's tracking script is blocked by:
- uBlock Origin (default filter lists)
- Brave browser shields
- Firefox Enhanced Tracking Protection (strict mode)
- Pi-hole and DNS-level blockers
- Privacy-focused browser extensions
For tech audiences, ad blocker usage can be 40-60%, meaning you potentially miss half your visitors. The recommended mitigation is proxying the Plausible script through your own domain.
Self-Hosted vs. Cloud Tradeoffs
| Factor | Plausible Cloud | Self-Hosted |
|---|---|---|
| Setup time | 5 minutes | 1-2 hours |
| Maintenance | Zero | You handle updates, backups, SSL |
| Cost | $9-19+/month | Server costs ($5-20/month VPS) |
| Data ownership | Plausible servers (EU) | Your servers |
| Custom domain | Limited proxy support | Full control |
| GDPR compliance | Plausible acts as processor | You are sole controller |
| Features | All included | All included |
| Uptime | Plausible SLA | Your responsibility |
Pre-Implementation Planning
Access and Permissions
Plausible Cloud:
- Sign up at
plausible.io - Add your website domain
- Invite team members with email
Self-Hosted:
- Deploy Plausible via Docker on your server
- Access the admin panel at your deployment URL
- Create an admin account during first setup
Key Configuration:
| Setting | Value | Notes |
|---|---|---|
| Site Domain | yoursite.com |
Exact match, no protocol prefix |
| Script URL (Cloud) | https://plausible.io/js/script.js |
Or proxy URL |
| Script URL (Self-Hosted) | https://analytics.yoursite.com/js/script.js |
Your deployment URL |
| API Token | Generated in account settings | For Stats API access |
Goal Planning
Plan your custom event goals before implementation:
| Goal Name | Type | Revenue? | Trigger |
|---|---|---|---|
| Signup | Custom Event | No | Account creation success |
| Purchase | Custom Event | Yes | Order confirmation |
| Contact Form | Custom Event | No | Form submission |
| Newsletter | Custom Event | No | Email signup |
| Outbound Link | Automatic | No | Script extension handles this |
| File Download | Automatic | No | Script extension handles this |
| 404 Error | Pageview | No | URL matches /404 pattern |
Script Extension Selection
Plausible uses modular script extensions. Choose which to enable:
| Extension | Script Filename | Purpose |
|---|---|---|
| Default | script.js |
Basic pageview tracking |
| Outbound links | script.outbound-links.js |
Track clicks to external sites |
| File downloads | script.file-downloads.js |
Track PDF, ZIP, etc. downloads |
| Tagged events | script.tagged-events.js |
CSS class-based event tracking (no JS needed) |
| Revenue | script.revenue.js |
Monetary value with custom events |
| Pageview props | script.pageview-props.js |
Custom properties on pageviews |
| Hash routing | script.hash.js |
Track hash-based SPA navigation |
| Outbound + Downloads + Revenue | script.outbound-links.file-downloads.revenue.js |
Combined extensions |
Important: Extensions are combined into a single script URL by concatenating the extension names. For example, to use outbound links, file downloads, and revenue tracking:
https://plausible.io/js/script.outbound-links.file-downloads.revenue.js
Implementation Walkthrough
Step 1: Add Plausible Script
Basic Installation (pageviews only):
<!-- Plausible Analytics -->
<script defer data-domain="yoursite.com"
src="https://plausible.io/js/script.js"></script>
With Common Extensions:
<!-- Plausible Analytics with outbound links, file downloads, and revenue tracking -->
<script defer data-domain="yoursite.com"
src="https://plausible.io/js/script.outbound-links.file-downloads.revenue.js"></script>
Self-Hosted:
<script defer data-domain="yoursite.com"
src="https://analytics.yoursite.com/js/script.outbound-links.file-downloads.revenue.js"></script>
Script Placement: Add the script in the <head> section of every page. The defer attribute ensures it does not block page rendering.
Step 2: Configure Custom Event Goals
First, create goals in the Plausible dashboard:
- Go to your site in Plausible
- Navigate to Site Settings > Goals
- Click Add Goal
- Select Custom Event
- Enter the exact event name (case-sensitive)
- Save
Then fire events from your JavaScript:
Form Submission:
// After successful form submission
document.getElementById('contact-form').addEventListener('submit', function(e) {
// Let the form submit normally, track the event
plausible('Contact Form', {
props: {
form_type: 'contact',
page: window.location.pathname
}
});
});
Signup:
// After account creation
function onSignupSuccess(user) {
plausible('Signup', {
props: {
method: user.authMethod, // 'google', 'email'
plan: user.selectedPlan // 'free', 'pro'
}
});
}
Purchase with Revenue:
// On order confirmation page (requires revenue extension)
plausible('Purchase', {
revenue: {
currency: 'USD',
amount: 129.98
},
props: {
order_id: 'ORD-2024-12345',
item_count: 2
}
});
Button Click:
document.querySelector('.cta-button').addEventListener('click', function() {
plausible('CTA Clicked', {
props: {
button_text: this.textContent,
button_location: 'hero_section'
}
});
});
Step 3: CSS Class-Based Event Tracking (No JavaScript)
With the tagged-events extension, you can track clicks using CSS classes instead of JavaScript:
<!-- Include the tagged-events extension -->
<script defer data-domain="yoursite.com"
src="https://plausible.io/js/script.tagged-events.js"></script>
<!-- Add CSS classes to trigger events -->
<a href="/pricing"
class="plausible-event-name=Pricing+Clicked plausible-event-location=nav">
View Pricing
</a>
<button
class="plausible-event-name=CTA+Clicked plausible-event-location=hero">
Start Free Trial
</button>
<a href="/whitepaper.pdf"
class="plausible-event-name=Whitepaper+Downloaded">
Download Whitepaper
</a>
Class format: plausible-event-name=EventName where spaces are replaced with +.
Step 4: Set Up Proxy for Ad Blocker Bypass
Why proxy: Ad blockers block requests to plausible.io. Proxying through your own domain makes the tracking script appear as first-party content.
Nginx Proxy Configuration:
# Add to your Nginx server block
# Proxy the Plausible script
location = /js/analytics.js {
proxy_pass https://plausible.io/js/script.outbound-links.file-downloads.revenue.js;
proxy_set_header Host plausible.io;
proxy_ssl_server_name on;
# Cache the script for 1 day
proxy_cache_valid 200 1d;
proxy_buffering on;
}
# Proxy the event API
location = /api/event {
proxy_pass https://plausible.io/api/event;
proxy_set_header Host plausible.io;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_ssl_server_name on;
}
Update your script tag to use the proxy:
<script defer data-domain="yoursite.com"
data-api="https://yoursite.com/api/event"
src="https://yoursite.com/js/analytics.js"></script>
Cloudflare Workers Proxy (alternative):
// Cloudflare Worker script
export default {
async fetch(request) {
const url = new URL(request.url);
if (url.pathname === '/js/analytics.js') {
return fetch('https://plausible.io/js/script.outbound-links.file-downloads.revenue.js');
}
if (url.pathname === '/api/event') {
const newRequest = new Request('https://plausible.io/api/event', {
method: request.method,
headers: request.headers,
body: request.body,
});
return fetch(newRequest);
}
return new Response('Not Found', { status: 404 });
}
};
Step 5: Configure Pageview Goals (URL-Based)
For tracking visits to specific pages (no JavaScript needed):
- In Plausible Site Settings > Goals, click Add Goal
- Select Pageview
- Enter the URL path:
- Exact:
/pricing(matches only /pricing) - Wildcard:
/blog/*(matches all blog posts) - Starts with:
/docs/**(matches all docs pages and sub-paths)
- Exact:
Common pageview goals:
| Goal | Path | Purpose |
|---|---|---|
| Pricing Page | /pricing |
Track pricing page visits |
| Blog Post View | /blog/* |
Track blog engagement |
| Documentation | /docs/** |
Track docs usage |
| Thank You Page | /thank-you |
Form submission confirmation |
Step 6: Self-Hosted Deployment (Optional)
Docker Compose Deployment:
version: "3.3"
services:
plausible_db:
image: postgres:15-alpine
restart: always
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=postgres
plausible_events_db:
image: clickhouse/clickhouse-server:23.3-alpine
restart: always
volumes:
- event-data:/var/lib/clickhouse
ulimits:
nofile:
soft: 262144
hard: 262144
plausible:
image: ghcr.io/plausible/community-edition:v2
restart: always
command: sh -c "sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
depends_on:
- plausible_db
- plausible_events_db
ports:
- 8000:8000
environment:
- BASE_URL=https://analytics.yoursite.com
- SECRET_KEY_BASE=YOUR_SECRET_KEY_64_CHARS
- DATABASE_URL=postgres://postgres:postgres@plausible_db:5432/plausible_db
- CLICKHOUSE_DATABASE_URL=http://plausible_events_db:8123/plausible_events_db
- MAILER_EMAIL=analytics@yoursite.com
- SMTP_HOST_ADDR=smtp.mailgun.org
- SMTP_HOST_PORT=587
- SMTP_USER_NAME=your_smtp_user
- SMTP_USER_PWD=your_smtp_password
volumes:
db-data:
event-data:
Reverse Proxy (Nginx in front of Plausible):
server {
listen 443 ssl http2;
server_name analytics.yoursite.com;
ssl_certificate /etc/letsencrypt/live/analytics.yoursite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/analytics.yoursite.com/privkey.pem;
location / {
proxy_pass http://localhost:8000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
}
}
Verification and QA
Real-Time Dashboard
- Open Plausible dashboard for your site
- In another tab, visit your website
- Within 5-10 seconds, your visit should appear in the "Current visitors" count
- Navigate several pages and verify:
- Page URLs appear in the "Top Pages" section
- Referrer shows correctly
- Country/device data is populated
Custom Event Verification
- Create a test goal in Plausible
- Trigger the event on your website (click a tracked button, submit a form)
- In Plausible dashboard > Goals section, verify:
- The goal shows a conversion count
- Custom properties (if using
props) display correctly - Revenue values (if using revenue extension) show amounts
Network Tab Debugging
- Open Chrome DevTools > Network tab
- Filter for
plausibleor your proxy domain - Navigate your site
- Verify:
- Script loads successfully (200 response)
- Event requests fire to
/api/event(POST requests) - Event payload includes correct
domain,url, andnamefields
Expected event payload:
{
"n": "pageview",
"u": "https://yoursite.com/pricing",
"d": "yoursite.com",
"r": "https://google.com",
"w": 1440
}
For custom events:
{
"n": "Purchase",
"u": "https://yoursite.com/order-confirmation",
"d": "yoursite.com",
"r": null,
"w": 1440,
"p": {"order_id": "ORD-12345", "item_count": "2"},
"$": {"amount": 129.98, "currency": "USD"}
}
Ad Blocker Testing
- Enable uBlock Origin or Brave shields
- Visit your site
- Check network tab -- requests to
plausible.ioshould be blocked - If using proxy:
- Enable ad blockers
- Verify proxy URL (
yoursite.com/js/analytics.js) is NOT blocked - Verify events still fire through proxy endpoint
Common Issues
| Issue | Cause | Fix |
|---|---|---|
| No data in dashboard | Script not loading | Check script tag placement, verify data-domain matches exactly |
| Events not tracking | Goal not created in Plausible | Create the goal first, then fire events |
| Proxy not working | Nginx proxy misconfigured | Check proxy_pass URL and proxy_set_header Host |
| Revenue not appearing | Missing revenue script extension | Use script.revenue.js combined extension |
| SPA navigation not tracked | Hash-based routing | Add script.hash.js extension |
| Wrong domain in data | data-domain mismatch |
Must match exactly what's configured in Plausible |
| Self-hosted slow | ClickHouse not optimized | Increase memory limits, check disk I/O |
Deployment Artifacts
- Script tag: Complete script tag with extensions and proxy URL
- Goal definitions: Event names, pageview paths, and revenue tracking
- Proxy configuration: Nginx/Cloudflare Worker/CDN proxy setup
- Custom event implementations: JavaScript code for each tracked action
- CSS class tags (if using tagged-events): Classes applied to tracked elements
- Self-hosted configuration (if applicable): Docker Compose, environment variables, SSL, backups
- API token: For programmatic access to stats (stored securely)
Linked Runbooks
- Install or Embed the Tag or SDK -- Script installation and proxy setup
- Event Tracking -- Custom event and goal configuration
- Data Layer Setup -- Integration with site data for event properties
- Cross-Domain Tracking -- Multi-domain configuration
- Server-Side vs Client-Side -- Client script vs. Stats API for data access
Change Log and Owners
- Document who manages the Plausible account and goal definitions
- Track script extension changes (added/removed extensions)
- Maintain proxy configuration updates
- Record self-hosted version updates and backup schedule
- Review quarterly: ad blocker impact, goal conversion rates, proxy health