DevTools Extension

The emit-vision DevTools extension adds a dedicated panel to Chrome DevTools. It shows every SDK event as it fires, validates events against your governance schema, and links directly to the dashboard — without leaving the browser.

Installation

Install from the Chrome Web Store or load unpacked for local development.

Chrome Web Store (recommended)

Search for "emit-vision DevTools" or use the direct listing link on the extensions page.

Load unpacked (development)

  1. Clone the monorepo and run pnpm build in apps/extension/.
  2. Open chrome://extensions, enable Developer mode.
  3. Click Load unpacked and select the apps/extension/dist/ folder.
  4. The emit-vision icon appears in the Chrome toolbar.

Install from .zip

If you received the extension as a .zip file (e.g., emit-vision-extension.zip):

  1. Unzip the file to a folder on your machine.
  2. Open chrome://extensions, enable Developer mode.
  3. Click Load unpacked and select the unzipped folder.

SDK setup

The extension listens to the SDK's debug channel. No extra config is required for basic capture — as long as the SDK is initialized on the page, the extension picks it up automatically.

Add projectId for dashboard deep links

Pass your project ID to the SDK to enable "Open in dashboard" links and the session replay link in the status bar:

import { init } from "@emit-vision/sdk-js";
 
init({
  apiKey: "evk_your_key",
  projectId: "proj_your_project_id",
  environment: "production",
});

The projectId is forwarded through the debug channel and used to build app.emitvision.com/sessions/<id>?projectId=... and event detail URLs.

Self-hosted dashboard URL

If you run a self-hosted emit-vision instance, set your dashboard base URL in the extension settings (gear icon in the status bar). Links will use your custom domain instead of app.emitvision.com.

Using the event stream

Open DevTools (F12 / ⌘⌥I) and select the emit-vision tab.

The event stream on the left lists every SDK message in arrival order — init, event, identify, flush, and error. Each row shows:

  • Event type icon and name
  • Property preview (first key-value pair)
  • Timestamp relative to page load
  • A colored dot indicating validation status (green = valid, yellow = warning, red = error, gray = unvalidated)

Click a row to open the event detail drawer on the right. The drawer shows the full payload as a collapsible JSON tree, the validation result, and an Open in dashboard ↗ button (when eventId is present).

Filtering

Type in the filter bar at the top to filter events by name. The filter is case-insensitive and matches partial names.

Clearing

Click Clear to wipe the event stream. Events that fired before you cleared are gone; new ones accumulate as before.

Validating events against governance rules

The extension fetches your project's governance schema from the dashboard and validates each event as it arrives.

How schema loading works

  1. When the SDK sends an init message, the extension reads the projectId from the payload (or auto-detects it from your dashboard session via the /api/projects endpoint).
  2. It fetches GET /api/projects/:projectId/governance and caches the result for 5 minutes.
  3. Every incoming event message is checked against eventRules — required properties, property types.

Local schema override

You can define local event rules that supplement or override the remote schema. This is useful for rules that haven't landed in production yet:

  1. Open the event detail drawer for any event.
  2. Use the Refresh schema button (status bar) after editing local rules via the extension's DevTools API (advanced use).

Rules defined locally take precedence over remote rules for the same event name.

Validation status indicators

Dot colorMeaning
GreenAll required properties present, types match
YellowWarning — event name not in the governance schema, or a property has an unexpected type
RedError — one or more required properties are missing
GrayNo governance schema loaded, or the schema has no event rules

Recording a journey

Use the Journey Recorder to capture a sequence of events into a replayable export — useful for writing tests or documenting user flows.

  1. Click Record in the toolbar. A pulsing red dot confirms recording is active.
  2. Give the journey a name in the text field (e.g., checkout_flow).
  3. Navigate through the user flow you want to capture.
  4. Click Stop when done. An Export modal appears.

The modal shows each step as a numbered list with event name, relative timestamp (ms from start), and properties. You can:

  • Copy JSON — copies the journey as a structured JSON object to the clipboard.
  • Download .json — saves the export as <name>-<date>.json.
  • Open in analytics — opens the journey in the dashboard's Analytics page, pre-loaded as a session replay. The journey is base64-encoded and passed as ?importJourney= in the URL.

Journey history

Every completed journey is automatically saved to a persistent history (up to 20 entries). Access it via the History button in the toolbar. Each entry shows the journey name and the date it was recorded. From the history list you can re-export any past journey or delete individual entries.

The most recent journey is also accessible via Show last without opening the full history list.

Sandbox mode

Sandbox mode lets you test your analytics implementation without sending real events to your ingest endpoint.

Enabling sandbox mode

Click the Sandbox toggle in the DevTools panel toolbar. The toolbar indicates when sandbox is active.

What sandbox does

When sandbox is on, the extension intercepts all fetch calls to the SDK's /v1/batch endpoint before they leave the browser. Instead of reaching your server, each request is:

  1. Parsed — events are extracted from the request body.
  2. Captured — events are forwarded to the DevTools panel, tagged as sandboxed.
  3. Swallowed — a synthetic 200 {"ok":true} response is returned so the SDK thinks the flush succeeded.

Events captured in sandbox mode appear in the event stream with a sandboxed indicator. They run through schema validation exactly like real events.

Auto-disable on navigation

Sandbox mode turns off automatically whenever you navigate to a new page. This prevents accidentally leaving sandbox on between sessions and sending stale "no-op" responses to a fresh page load.

Every event with an eventId has an Open in dashboard ↗ button in the detail drawer. Clicking it opens the event detail page in a new tab:

https://app.emitvision.com/events/<eventId>?projectId=<projectId>

The status bar shows the session ID as a clickable link to the session replay:

https://app.emitvision.com/sessions/<sessionId>?projectId=<projectId>

Both links omit ?projectId when projectId was not provided to the SDK.

Troubleshooting

SDK not detected (badge stays gray, no events in panel)

  • Confirm the SDK is initialized on the page. Open the browser console and check for [emit-vision] log lines — init() logs "emit-vision ready" by default when debug: true.
  • Check that the content script is running: open chrome://extensions, find emit-vision DevTools, and verify it's enabled and has access to the current site.
  • Hard-refresh the page (⌘⇧R / Ctrl+Shift+R) after enabling the extension.

Badge is yellow (localhost warning)

Your endpoint option points to localhost or 127.0.0.1. Events still flow, but the yellow badge indicates the SDK is pointing at a local server, not production. This is expected during local development.

Schema not loading

  • You must be signed into the emit-vision dashboard in the same browser profile for the extension to read your session cookie.
  • If you're self-hosted, set your dashboard base URL in the extension settings (gear icon) — the schema fetch uses that base URL.
  • Click Refresh schema (circular arrow in the status bar) to force a fresh fetch.

Self-hosted dashboard URL

Click the ⚙ gear icon in the status bar to open the Settings overlay. Enter your dashboard base URL (e.g., https://your-domain.com) and click Save. All deep links and schema fetches will use this URL until you change it.

Session replay link not appearing

The session replay link requires a sessionId in the SDK init payload. This is included automatically unless you explicitly pass sessionId: undefined to init(). Check the init event in the panel — the sessionId field should be a UUID.