Chrome Extension Analytics Setup
Instrument a Chrome extension with PostHog analytics to track installs, popup opens, and lead capture events
Instructions
Chrome Extension Analytics Setup
Instrument a Chrome extension with event tracking so you can measure installs, engagement, and lead capture. Chrome extensions cannot use standard web analytics (no page views), so you must send events explicitly via API.
PostHog Setup for Extensions
Chrome extensions run in a sandboxed environment. You cannot include PostHog's standard JS snippet. Instead, use the PostHog API directly.
Option 1: PostHog API (Recommended for Teaser Extensions)
Send events directly from the extension's popup or background script:
// analytics.js — include in your extension
const POSTHOG_API_KEY = 'phc_YOUR_PROJECT_KEY';
const POSTHOG_HOST = 'https://us.i.posthog.com'; // or eu.i.posthog.com
async function trackEvent(eventName, properties = {}) {
const distinctId = await getOrCreateDistinctId();
await fetch(`${POSTHOG_HOST}/capture/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
api_key: POSTHOG_API_KEY,
event: eventName,
distinct_id: distinctId,
properties: {
...properties,
$lib: 'chrome-extension',
extension_version: chrome.runtime.getManifest().version,
source: 'chrome-web-store-teaser'
}
})
});
}
async function getOrCreateDistinctId() {
const result = await chrome.storage.local.get('distinct_id');
if (result.distinct_id) return result.distinct_id;
const id = crypto.randomUUID();
await chrome.storage.local.set({ distinct_id: id });
return id;
}
Required Events to Track
| Event Name | When Fired | Properties |
|-----------|------------|------------|
| extension_installed | chrome.runtime.onInstalled in background.js | install_reason (install, update, chrome_update) |
| popup_opened | When popup.html loads | page (popup) |
| waitlist_form_submitted | Form submission in popup | email_domain, referrer |
| feature_preview_clicked | User clicks a feature preview | feature_name |
| extension_uninstalled | Set via chrome.runtime.setUninstallURL() | Tracked via uninstall survey landing page |
Background Script Event Tracking
// background.js
import { trackEvent } from './analytics.js';
chrome.runtime.onInstalled.addListener((details) => {
trackEvent('extension_installed', {
install_reason: details.reason,
previous_version: details.previousVersion || null
});
// Set uninstall URL for exit survey
chrome.runtime.setUninstallURL(
'https://yoursite.com/extension-uninstall?source=chrome-web-store-teaser'
);
});
Popup Event Tracking
// popup.js
import { trackEvent } from './analytics.js';
// Track popup opens
trackEvent('popup_opened');
// Track form submissions
document.getElementById('waitlist').addEventListener('submit', async (e) => {
e.preventDefault();
const email = document.getElementById('email').value;
trackEvent('waitlist_form_submitted', {
email_domain: email.split('@')[1]
});
// Send to your backend / Loops API
});
Permissions Required
Add to manifest.json:
{
"permissions": ["storage"],
"host_permissions": [
"https://us.i.posthog.com/*",
"https://yoursite.com/*"
]
}
Verifying Events
- Install the extension locally (
chrome://extensions> Load unpacked) - Open the popup, submit a test form
- Check PostHog > Activity > Live Events for incoming events
- Verify
distinct_idpersists across popup opens (checkchrome.storage.local)
Error Handling
- If
fetchfails (network error), queue events inchrome.storage.localand retry on next popup open - PostHog API returns 200 for valid events. A 400 response means malformed payload — check
api_keyandeventfields - Chrome extensions have a 5MB storage limit for
chrome.storage.local. Flush queued events before approaching this limit