# Install optional browser tracking

Capture embedded app activity without exposing a private workspace key.

## What you need

An embedded app, the app-specific `crstpx_` browser token and permission to add the snippet. Verified contact capture also requires the matching Shopify client secret.

## Steps

1. Open the app’s Developers setup or [get_setup_guide](/docs/mcp/get-setup-guide) and copy its actual pixel snippet into the embedded app layout so it loads on intended pages.
2. Use the public app token only. Never put `crst_`, `hcak_`, an install key or Shopify client secret into browser code.
3. If approved, configure the matching client secret for server-side verification of App Bridge session tokens. Verified contact capture is separate from analytics events.
4. Optionally call `window.crust.track("event_name", {step: "example"})` for a real browser action after the snippet loads.
5. Open the app as an authorized test merchant and inspect browser request receipt and app observation. Use backend events for milestones on which a consequential Flow should act.

## Expected result

Browser session/page/custom activity observed for that app. Usage authenticated only by the public app token is analytics-grade; a verified Shopify session token is needed for authoritative contact enrichment.

## HTTP ingest contract

POST `/api/track` accepts JSON text (the snippet uses `text/plain`) with `appToken`, optional `customerId`/`idToken` and 1–20 `events`. Page/session events carry `type` (`page_view` or `session_start`) and `sessionId`; custom events carry `type: "custom"`, `name`, `sessionId` and optional properties. Optional timestamps are milliseconds and are clamped to the last hour through now.

The endpoint returns `{ "ok": true }` after processing; contact capture can fail separately from event storage. This public browser write endpoint is not an affiliate attribution or private analytics read API.

## Troubleshooting

Check token/app mapping, snippet load, shop hint and App Bridge token availability. A client-secret mismatch can show a stale-secret warning. An ad blocker or missing browser receipt is not proof of merchant inactivity.
