Skip to main content

Install the SDK

Install the Composite Analytics SDK using your preferred package manager:
npm install @composite-inc/composite-js

Manifest Configuration

Your Chrome Extension’s manifest.json needs specific permissions to enable analytics and session recording.

Required Permissions

{
  "manifest_version": 3,
  "name": "Your Extension",
  "version": "1.0.0",
  "permissions": [
    "storage",
    "tabs"
  ],
  "host_permissions": [
    "https://prod.alb.us.api.composite.com/*"
  ],
  "background": {
    "service_worker": "background.js",
    "type": "module"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ]
}

Permission Breakdown

PermissionPurpose
storagePersist user identity and session data
tabsAccess tab information for session context
host_permissionsAllow API requests to Composite servers
Adding a new host permission will trigger a permission request for all existing users. If your extension doesn’t already have <all_urls> in your host_permissions or content script matches, adding prod.alb.us.api.composite.com will prompt users to re-approve permissions on update.To avoid this, you can route analytics through a domain you already have permission for. See Custom Proxy for configuration options.

Alternative: Programmatic Injection

If you don’t want to declare content scripts in your manifest (to avoid permission changes for existing users), you can use the chrome.scripting API to inject scripts programmatically:
{
  "manifest_version": 3,
  "name": "Your Extension",
  "version": "1.0.0",
  "permissions": [
    "storage",
    "scripting",
    "activeTab"
  ],
  "host_permissions": [
    "https://prod.alb.us.api.composite.com/*"
  ],
  "background": {
    "service_worker": "background.js",
    "type": "module"
  }
}
Then inject the content script from your background script:
// background.js - Inject content script programmatically
import { HttpTransport, createBackgroundHandler } from '@composite-inc/composite-js';

const transport = new HttpTransport({
  apiKey: 'pk_your_api_key',
  apiHost: 'https://prod.alb.us.api.composite.com',
});

createBackgroundHandler(transport);

// Inject when user clicks extension icon
chrome.action.onClicked.addListener(async (tab) => {
  if (tab.id) {
    await chrome.scripting.executeScript({
      target: { tabId: tab.id },
      files: ['content.js']
    });
  }
});

// Or inject on specific URLs
chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
  if (changeInfo.status === 'complete' && tab.url?.includes('your-app.com')) {
    await chrome.scripting.executeScript({
      target: { tabId },
      files: ['content.js']
    });
  }
});
Using chrome.scripting with activeTab only grants access when the user interacts with your extension. This avoids broad permission warnings but means recording only starts after user interaction.

Content Security Policy

For some extensions, you may need to adjust the Content Security Policy:
{
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'"
  }
}

What’s Next?