Plausible Event Tracking: Custom Goals, Revenue Tracking, | OpsBlu Docs

Plausible Event Tracking: Custom Goals, Revenue Tracking,

How to track custom events in Plausible with the lightweight script extension. Covers goal setup, custom properties, revenue tracking, and 404...

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:

  1. Event Name: What happened (e.g., "Signup", "Download", "Purchase")
  2. 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)

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

JavaScript:

// 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)
  • SignUp vs Signup (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');

React:

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>;
}

Vue.js:

<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:

  1. Create Custom HTML tag
  2. Add Plausible script
  3. Create trigger (e.g., DOM Ready)

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:

  1. Log into Plausible dashboard
  2. Select your site
  3. Click "Current Visitors" (top right)
  4. Perform action on your site
  5. See event appear in real-time

Goal Conversions:

  1. Go to Settings > Goals
  2. Add custom event goal
  3. View conversions in main dashboard
  4. 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:

  1. Settings > Goals > Add Goal
  2. Goal Type: Custom Event
  3. Event Name: (exact match of your event name)
  4. 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 Signup or always Sign 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:

  1. Go to Settings > Goals
  2. Add custom event goals
  3. Use exact event name matching
  4. Monitor conversion rates
  5. 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

  1. Development: Test on localhost
  2. Staging: Use separate domain/property
  3. Production: Monitor goals and conversions
  4. Validation: Check network requests and dashboard
  5. Documentation: Maintain event catalog

Additional Resources: