Embed Chipp Insights Beacon
Add Chipp Insights to your website to track user presence, identify logged-in users, and monitor client-side errors.

Add Chipp Insights to any website to track anonymous and authenticated user presence, identify logged-in users after authentication, and automatically capture client-side errors. The beacon is lightweight (~1.5KB gzipped) and designed to be invisible: it never blocks your page or logs to the console.
For Alchemist projects (end-user tracking). This is analytics for YOUR deployed app’s end-users. If you’re tracking your own builder’s activation at build.chipp.ai, see Builder Analytics & Activation Tracking instead.
What is Chipp Insights?
Chipp Insights helps you understand how your end-users interact with your Chipp-powered app. It automatically:
- Tracks page views: See which pages your end-users visit and how they navigate
- Identifies users: Link anonymous sessions to real users after login
- Captures errors: Monitor client-side JavaScript errors in production
- Respects privacy: Uses anonymous session IDs until you explicitly call
identify()
Where You’ll See This Data
There isn’t a full Chipp Insights dashboard yet. Today, the data this beacon collects surfaces in these places:
- Project Usage tab - your project’s Usage tab shows a globe of where your end-users are, by country, over the last 7 days.
- Alchemist chat - ask the assistant for your project’s analytics. It can report event volume, unique and identified visitors, top pages, top countries, and top client-side errors.
It also surfaces inside Chipp Mail (your team’s shared inbox at email.chipp.ai), in two places:
- Contact panel: open any email thread with someone, and if that person’s email shows up in your project’s telemetry, you’ll see a “Chipp Insights” section on their contact profile: which of your projects they’ve been active on, and when they were last seen.
- Notifications feed: new activity from a known contact (an
identify()call on one of your projects) shows up as a notification alongside your unread mail and Slack mentions.
This is a soft signal, not a verified fact (see “How It Works” below for why). Per-person activity only shows up in Chipp Mail. Aggregate numbers show up in the Usage tab and in Alchemist chat.
Quick Start
Add a single <script> tag before the closing </body> tag on your website, with your project key:
<script
src="https://build.chipp.ai/i/beacon.js"
data-project-key="tk_pub_YOUR_PROJECT_KEY"
></script>The beacon automatically:
- Creates a random, persistent session ID on first load
- Sends a pageview ping on every page load and navigation
- Captures uncaught JavaScript errors and promise rejections
To identify a user after login, call:
chippInsights.identify("user@example.com");That’s it. The beacon will include the user’s email on all subsequent pageviews and errors.
Getting Your Project Key
If your site was generated by Chipp (an Alchemist project), you don’t need to do anything. Every new Alchemist project ships with its own key already wired into the site’s shared layout: the beacon is active out of the box, with no manual step. The plaintext key lives in your project’s own repo at chipp-insights.json (root of the repo) if you ever need to reference it directly.
If you want to add the beacon to a different website (one Chipp didn’t generate for you, or a second site you want the same project tracked under), copy the key from the dashboard:
In the Alchemist, open the project and click Usage.
Below the activity globe, the Beacon key card shows your tk_pub_ key and a ready-to-paste snippet.
Click Copy key or Copy snippet, then paste the snippet before the closing </body> tag of the other site.
The card reads the key from chipp-insights.json in your project’s repo and shows it only after checking that it is a live key of this project. Only the project owner can see it. If the card says the repo has no key, or that the key is revoked or belongs to another project, contact support for a new key. Chipp stores only a fingerprint of the key, so it cannot show a key that is not in your repo.
This is a public key. It’s safe to embed in your website: it only allows sending pageview and error data, not reading back data or accessing other projects.
JavaScript API
The beacon exposes a window.chippInsights object with methods to manually trigger events and control the beacon.
Identifying Users
Call identify() after a user logs in to link their session to their email address:
// After login
chippInsights.identify("jane@example.com");What happens:
- The email is stored in-memory and persisted to
sessionStoragefor a 30-minute sliding window - All subsequent pageviews and errors on this page load include the email
- If the user does a full-page reload (not a client-side navigation), the email is reattached automatically during that window
- After 30 minutes, the sessionStorage marker expires and the session becomes anonymous again
Best practice:
Call identify() immediately after your authentication succeeds, before the user navigates:
async function handleLogin(email, password) {
const result = await authenticateUser(email, password);
if (result.success) {
chippInsights.identify(email);
// Then navigate
window.location.href = "/dashboard";
}
}Manual Pageview Ping
The beacon automatically sends pageview pings on load and on client-side route changes (via pushState / replaceState hooks). If your app uses a navigation method not covered by these hooks, manually trigger a pageview:
// In a custom router or navigation handler
chippInsights.pageview();When to use:
- You have a custom client-side router that doesn’t use
history.pushStateorreplaceState - You want to track navigation that’s not a traditional page view (e.g., modal opens, tab switches)
Full API Reference
| Method | Signature | Description |
|---|---|---|
init(projectKey) | (projectKey: string) => void | Initialize the beacon with your project key. Called automatically from data-project-key attribute: use this only if you need to initialize programmatically. |
identify(email) | (email: string) => void | Link the current session to a user’s email address. Called after successful login. |
pageview() | () => void | Manually send a pageview ping. Use only if your app has custom navigation not covered by standard route hooks. |
Script Tag Attributes
Customize the beacon’s behavior by adding attributes to the <script> tag:
<script
src="https://build.chipp.ai/i/beacon.js"
data-project-key="tk_pub_YOUR_PROJECT_KEY"
></script>| Attribute | Required | Description |
|---|---|---|
data-project-key | Yes | Your project’s public key. Starts with tk_pub_. Already filled in for you on an Alchemist-generated project (see “Getting Your Project Key” above). |
How It Works
Session Tracking
The beacon creates a unique distinctId (a random UUID) on first load and persists it in localStorage under the key chipp_insights_distinct_id. This ID is:
- Reused across page loads: the same device always has the same anonymous session ID
- Anonymous by default: no personally identifiable information until you call
identify() - Linked to a user on
identify(): subsequent events include both thedistinctIdand the user’s email
A word on trust: identify(email) is exactly what it sounds like: whatever email your own code passes in, with nothing tying the browser making the call to the person that email actually belongs to. It’s the same trust level as any client-side analytics identify() call (PostHog’s works the same way). That’s a fine, normal level of confidence for “this looks like usage,” but it’s why Chipp Mail’s Contact panel phrases it as “activity recorded for X,” never “X used this”: treat the data the same way in your own reporting.
Automatic Pageview Pings
The beacon sends a pageview ping:
- On page load: when the script first runs
- On SPA navigation: when the user uses the browser back/forward buttons or clicks a link that uses
history.pushStateorreplaceState - Manually: when you call
chippInsights.pageview()
Each ping includes:
distinctId: the anonymous session IDemail(if identified): only set afteridentify()is calledpath- the current page’s pathname plus query string
Error Tracking
The beacon automatically captures:
- Uncaught exceptions -
window.addEventListener("error", ...)(the beacon never overwrites your ownwindow.onerror) - Unhandled promise rejections:
window.addEventListener("unhandledrejection", ...)
Each error includes:
message: the error messagestack- the error stack trace (the server truncates it at 8000 chars)- Rate limiting: max 5 errors per minute per page load; identical errors are deduplicated
Fail-Silent Design
The beacon is designed to be invisible if something goes wrong:
- All errors are caught and never re-thrown
- Network failures don’t block your page
- No logs to the browser console in normal operation
- Bundle size is tiny (~1.5KB gzipped), so page load impact is minimal
Data Payloads
The beacon sends three types of events to POST /api/public/telemetry/beacon (your Chipp instance):
Pageview Event
{
"projectKey": "tk_pub_...",
"distinctId": "550e8400-e29b-41d4-a716-446655440000",
"email": "jane@example.com",
"eventType": "pageview",
"path": "/dashboard"
}Identify Event
{
"projectKey": "tk_pub_...",
"distinctId": "550e8400-e29b-41d4-a716-446655440000",
"email": "jane@example.com",
"eventType": "identify"
}Error Event
{
"projectKey": "tk_pub_...",
"distinctId": "550e8400-e29b-41d4-a716-446655440000",
"email": "jane@example.com",
"eventType": "error",
"errorMessage": "Cannot read property 'foo' of undefined",
"errorStack": "TypeError: Cannot read property 'foo' of undefined\n at getUserData (main.js:123:45)\n ..."
}Examples
Basic Setup
Simplest integration: just add the script with your project key:
<!DOCTYPE html>
<html>
<body>
<!-- Your page content -->
<script
src="https://build.chipp.ai/i/beacon.js"
data-project-key="tk_pub_abcdef1234567890"
></script>
</body>
</html>Login Tracking
Identify users after they log in:
<form id="login-form">
<input type="email" id="email" placeholder="Email" />
<input type="password" id="password" placeholder="Password" />
<button type="submit">Log In</button>
</form>
<script
src="https://build.chipp.ai/i/beacon.js"
data-project-key="tk_pub_abcdef1234567890"
></script>
<script>
document.getElementById("login-form").addEventListener("submit", async (e) => {
e.preventDefault();
const email = document.getElementById("email").value;
const password = document.getElementById("password").value;
try {
const response = await fetch("/api/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
if (response.ok) {
// Identify the user in Chipp Insights
chippInsights.identify(email);
// Redirect to dashboard
window.location.href = "/dashboard";
} else {
alert("Login failed");
}
} catch (error) {
console.error("Login error:", error);
}
});
</script>React Integration
Load the beacon in a React app:
import { useEffect } from "react";
function App({ user }) {
useEffect(() => {
// Load the beacon script
const script = document.createElement("script");
script.src = "https://build.chipp.ai/i/beacon.js";
script.dataset.projectKey = "tk_pub_abcdef1234567890";
script.async = true;
document.body.appendChild(script);
return () => {
script.remove();
};
}, []);
// Identify user when logged in
useEffect(() => {
if (user?.email && window.chippInsights) {
window.chippInsights.identify(user.email);
}
}, [user?.email]);
return <div>Your app</div>;
}Next.js Integration
Use Next’s built-in Script component:
"use client";
import Script from "next/script";
export default function RootLayout({ children, user }) {
return (
<>
<Script
src="https://build.chipp.ai/i/beacon.js"
data-project-key="tk_pub_abcdef1234567890"
strategy="afterInteractive"
/>
<script
dangerouslySetInnerHTML={{
__html: `
if (window.chippInsights && ${JSON.stringify(user?.email)}) {
chippInsights.identify('${user.email}');
}
`,
}}
/>
{children}
</>
);
}Custom Router Integration
If your app uses a custom router that doesn’t use history.pushState, manually trigger pageviews:
class CustomRouter {
navigate(path) {
this.currentPath = path;
this.render();
// Tell Chipp Insights about the navigation
if (window.chippInsights) {
chippInsights.pageview();
}
}
}Conditional Loading
Only load the beacon for specific users or pages:
if (isProductionEnvironment() && user.hasAnalyticsEnabled) {
const script = document.createElement("script");
script.src = "https://build.chipp.ai/i/beacon.js";
script.dataset.projectKey = "tk_pub_abcdef1234567890";
document.body.appendChild(script);
}Privacy & Compliance
Before you start
Chipp Insights is designed to be privacy-friendly:
- Anonymous by default: no email or identifying info is sent until you explicitly call
identify() - First-party: data is sent to your own Chipp instance, not a third-party service
- No cookies by default: uses localStorage and sessionStorage for session tracking, not cookies
However, if your website or app has its own privacy policy or cookie consent banner:
- Check your privacy policy: Update it to mention that you use Chipp Insights for pageview and error tracking
- Cookie consent: If your site uses a cookie banner and classifies analytics as “marketing” or “analytics” cookies that require consent, you may want to wait for user consent before initializing the beacon
- Optional: Consent-aware initialization: You can defer the beacon’s initialization until consent is given:
// Wait for consent before initializing
if (userHasGivenAnalyticsConsent()) {
const script = document.createElement("script");
script.src = "https://build.chipp.ai/i/beacon.js";
script.dataset.projectKey = "tk_pub_abcdef1234567890";
document.body.appendChild(script);
}What Chipp Insights sends
| Field | Purpose | When |
|---|---|---|
projectKey | Authentication | Every event |
distinctId | Anonymous session ID | Every event |
email | User identification | Only if you call identify() |
path | Page tracking | Pageview events |
errorMessage / errorStack | Error monitoring | Error events only |
Chipp Insights does not send:
- Browser fingerprints
- IP addresses (sent by your HTTP layer, not the beacon; Chipp never stores the raw IP, but it does record an approximate country, region, city, and timezone for each event from its edge network)
- User-Agent or device info
- Cookies (unless your site sets them separately)
- Any personal data beyond the email you explicitly provide
Troubleshooting
The beacon script isn’t loading
- Check the URL: Make sure the script
srcis correct and matches your Chipp instance domain - Check your project key: Verify
data-project-keyis set and starts withtk_pub_ - Check CORS: The beacon uses
navigator.sendBeacon()which doesn’t require CORS headers, but check your browser’s Network tab for any errors - Check Content Security Policy: If your site has a strict CSP, allow the beacon:
plaintext
script-src https://build.chipp.ai; connect-src https://build.chipp.ai;
identify() isn’t working
- Check timing: Make sure the beacon script has loaded before calling
identify(). If you’re loading the script asynchronously, wait a moment:javascriptsetTimeout(() => { if (window.chippInsights) { chippInsights.identify("user@example.com"); } }, 100); - Check email validity: The email must be a non-empty string. Pass the actual email, not
nullorundefined. - Check browser console: The beacon never logs errors to the console (fail-silent design), but your app’s own code might be throwing. Check for any errors in the browser DevTools.
Not seeing activity in Chipp Mail
- Check the project key: Make sure you’re using the right project key for your Chipp app. Each project has its own key.
- Check network activity - Open your browser’s Network tab and look for requests to
/api/public/telemetry/beacon. If you don’t see any, the beacon script isn’t loading ordata-project-keyis missing. A wrong key still sends requests, but they get a401response. - Check beacon initialization: The beacon runs automatically on page load. If the script is on the page, it should be sending data.
- Check the endpoint - The beacon sends to
POST /api/public/telemetry/beacon. The route returns 200 even on bad input, to avoid retry storms. The one exception is a401, which means the project key is wrong or revoked. Any other non-2xx response points at a real problem; contact support with the failing response. - Remember how Chipp Mail matches - per-person data only surfaces in Chipp Mail when it matches an email you already have a thread with (see “Where You’ll See This Data” above). No matching contact means nothing will visibly show up, even if events are landing correctly.
High error rates in Chipp Insights
If you’re seeing a lot of errors reported:
- Check for tight error loops: If your app has a bug that throws repeatedly, the beacon caps errors at 5 per minute per page load and silently drops the rest. Fix the underlying bug.
- Check third-party scripts: Scripts you don’t control (ads, tracking, etc.) can throw errors. These are captured by the beacon. Check your browser console to see what’s throwing.
- Check for typos: Undefined variables, null reference errors, etc. are the most common. Use a linter or TypeScript to catch these before production.
The beacon is slowing down my page
The beacon is designed to be non-blocking:
- Bundle size is ~1.5KB gzipped: negligible impact on page load
- All network requests use
navigator.sendBeacon()which is fire-and-forget: doesn’t block the page - Errors are caught and never re-thrown: won’t break your app
If you’re noticing performance issues:
- Check network conditions: Slow networks can make any request take longer. The beacon won’t block your page, but it may take time to send.
- Check your own code: If your page is slow, it’s likely your own JavaScript, not the beacon.
- Disable the beacon: If you want to test, don’t include the script tag. The beacon is completely optional.
Content Security Policy (CSP)
If your website uses a Content Security Policy, allow the beacon’s script and network requests:
script-src https://build.chipp.ai;
connect-src https://build.chipp.ai;If you’re using a nonce-based CSP, add the nonce to the script tag:
<script
nonce="YOUR_NONCE"
src="https://build.chipp.ai/i/beacon.js"
data-project-key="tk_pub_YOUR_PROJECT_KEY"
></script>FAQ
Q: Is the beacon GDPR compliant?
The beacon itself is privacy-friendly (anonymous by default, minimal data collection), but your use of it must comply with your privacy policy and applicable laws. If your site is subject to GDPR, CCPA, or similar regulations:
- Update your privacy policy to mention Chipp Insights
- If required by your jurisdiction, get consent before sending data
- Provide a way for users to opt out (e.g., respect Do Not Track)
Q: Can I disable the beacon for certain users?
Yes. Only add the script tag for users who consent, or use the conditional-loading pattern shown in the examples above.
Q: Can the beacon read cookies or localStorage?
No. The beacon only writes to localStorage (for the distinctId) and sessionStorage (for the email marker). It doesn’t read your app’s data.
Q: What happens if Chipp Insights is down?
The beacon uses navigator.sendBeacon() which is fire-and-forget. If the endpoint is unreachable, the request fails silently and doesn’t block your page. Once Chipp is back online, new requests will go through.
Q: Can I use the beacon on multiple websites?
Yes. Use the same project key on all your websites: events from all of them land in the same project’s data, there’s no per-domain separation today.
Q: How long is data retained?
There’s currently no automatic expiration: events aren’t deleted on a timer. This may change as the feature matures; if you need a specific record removed sooner (e.g. someone asked to be forgotten), contact support.