Plausible Setup & Implementation | OpsBlu Docs

Plausible Setup & Implementation

How to implement Plausible analytics for privacy-first, cookieless website tracking.

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:

  1. Sign up at plausible.io
  2. Add your website domain
  3. Invite team members with email

Self-Hosted:

  1. Deploy Plausible via Docker on your server
  2. Access the admin panel at your deployment URL
  3. 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:

  1. Go to your site in Plausible
  2. Navigate to Site Settings > Goals
  3. Click Add Goal
  4. Select Custom Event
  5. Enter the exact event name (case-sensitive)
  6. 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):

  1. In Plausible Site Settings > Goals, click Add Goal
  2. Select Pageview
  3. 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)

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

  1. Open Plausible dashboard for your site
  2. In another tab, visit your website
  3. Within 5-10 seconds, your visit should appear in the "Current visitors" count
  4. Navigate several pages and verify:
    • Page URLs appear in the "Top Pages" section
    • Referrer shows correctly
    • Country/device data is populated

Custom Event Verification

  1. Create a test goal in Plausible
  2. Trigger the event on your website (click a tracked button, submit a form)
  3. 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

  1. Open Chrome DevTools > Network tab
  2. Filter for plausible or your proxy domain
  3. Navigate your site
  4. Verify:
    • Script loads successfully (200 response)
    • Event requests fire to /api/event (POST requests)
    • Event payload includes correct domain, url, and name fields

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

  1. Enable uBlock Origin or Brave shields
  2. Visit your site
  3. Check network tab -- requests to plausible.io should be blocked
  4. 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

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