Examples

Real-world snippets for the most common Emit Vision integration patterns. Each example is self-contained and runnable as shown.

All examples assume you've already called init() once at app startup. See the Quick Start guide if you haven't done that yet.

Browser: track a button click

Use captureEvent inside any event handler. Pass a properties object for dimensions and a tags object for filterable labels.

import { captureEvent } from "@emit-vision/sdk-js";
 
function handleUpgradeClick() {
  captureEvent("upgrade_clicked", {
    properties: {
      plan: "pro",
      source: "pricing_page",
    },
    tags: {
      experiment: "pricing-v2",
    },
  });
}
 
document
  .getElementById("upgrade-btn")
  ?.addEventListener("click", handleUpgradeClick);

Events appear in the dashboard's Events tab within a few seconds.

Browser: capture a caught error

Wrap risky operations in try/catch and call captureError to send the error with context attached. See Errors for grouping and fingerprinting details.

import { captureError } from "@emit-vision/sdk-js";
 
async function loadUserProfile(userId: string) {
  try {
    const res = await fetch(`/api/users/${userId}`);
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return await res.json();
  } catch (err) {
    captureError(err as Error, {
      context: { userId, endpoint: "/api/users" },
      tags: { area: "profile" },
    });
    throw err; // re-throw so the caller can handle it
  }
}

React: error boundary

A class component that catches render-phase errors and reports them before showing a fallback UI.

import React from "react";
import { captureError } from "@emit-vision/sdk-js";
 
interface Props {
  children: React.ReactNode;
  fallback?: React.ReactNode;
}
 
interface State {
  hasError: boolean;
}
 
export class ErrorBoundary extends React.Component<Props, State> {
  state: State = { hasError: false };
 
  componentDidCatch(error: Error, info: React.ErrorInfo) {
    captureError(error, {
      context: { componentStack: info.componentStack ?? undefined },
      tags: { layer: "react_boundary" },
    });
  }
 
  static getDerivedStateFromError(): State {
    return { hasError: true };
  }
 
  render() {
    if (this.state.hasError) {
      return this.props.fallback ?? <p>Something went wrong.</p>;
    }
    return this.props.children;
  }
}

Wrap any subtree you want to protect:

<ErrorBoundary fallback={<p>Failed to load dashboard.</p>}>
  <Dashboard />
</ErrorBoundary>

Node.js: Express middleware + flush on shutdown

Initialize once at app startup, add the middleware, and flush on process exit so buffered events aren't lost. See sdk-node Reference for all options.

import express from "express";
import { init, middleware, flush } from "@emit-vision/sdk-node";
 
init({
  dsn: process.env.EMIT_VISION_DSN!,
  environment: process.env.NODE_ENV ?? "production",
  release: process.env.APP_VERSION,
});
 
const app = express();
app.use(middleware());
 
// your routes here
app.get("/", (_req, res) => res.send("ok"));
 
const server = app.listen(3000);
 
async function shutdown() {
  server.close();
  await flush({ timeout: 3000 });
  process.exit(0);
}
 
process.on("SIGTERM", shutdown);
process.on("SIGINT", shutdown);

User identification

Call setUser after a successful login so that subsequent events and errors carry the user's identity. See Sessions for how Emit Vision ties events into a session timeline.

import { setUser, captureEvent } from "@emit-vision/sdk-js";
 
async function handleLogin(credentials: { email: string; password: string }) {
  const user = await api.login(credentials);
 
  // Identify the user — all future events will include this
  setUser({ id: user.id, email: user.email });
 
  captureEvent("user_logged_in", {
    properties: { method: "email" },
  });
}