Docs / Chrome Extension
Chrome extension setup
Chrome extensions cannot load Aizen's hosted tracker script directly. Instead, create a chrome_extension target, mint an events:write key, and send events from your bundled background service worker.
1. Create the target
- Create a new target in Aizen and choose `Chrome extension`.
- Add your extension name, timezone, and optional extension ID.
- Create an `events:write` key from the target settings page.
2. Bundle local extension code
Add your Aizen host to host_permissions and ship the background worker inside the extension package.
{
"manifest_version": 3,
"name": "My Extension",
"version": "1.0.0",
"permissions": ["storage"],
"host_permissions": ["https://your-aizen-app.com/*"],
"background": {
"service_worker": "background.js",
"type": "module"
}
}3. Send events from the background worker
Use a stable anonymous install ID as client_id. In v1, Aizen uses that ID to keep visitor counts stable for extension traffic.
const API_URL = 'https://your-aizen-app.com/api/event'
const SITE_ID = 'your_site_id'
const WRITE_KEY = 'your_events_write_key'
async function getInstallId() {
const { aizenInstallId } = await chrome.storage.local.get('aizenInstallId')
if (aizenInstallId) return aizenInstallId
const newId = crypto.randomUUID()
await chrome.storage.local.set({ aizenInstallId: newId })
return newId
}
export async function track(payload) {
const clientId = await getInstallId()
await fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${WRITE_KEY}`
},
body: JSON.stringify({
site_id: SITE_ID,
type: payload.type ?? 'event',
name: payload.name,
path: payload.path,
platform: 'web',
timestamp: Date.now(),
client_id: clientId,
context: payload.context ?? 'background',
extension_id: chrome.runtime.id,
props: payload.props
})
})
}4. Track popup or option screens
Treat extension surfaces like screen paths such as /popup,/options, or /sidepanel.
chrome.runtime.sendMessage({
type: 'track',
payload: {
type: 'pageview',
path: '/popup',
context: 'popup'
}
})Security notes
- Write keys embedded in an extension are revocable identifiers, not true secrets.
- Set the extension ID in Aizen once you know it to reject mismatched writes.
- Use the regular public API docs for `stats:read` keys.