# Revtrail > Privacy-first, revenue-first web and mobile analytics. One small snippet ties every > pageview to the signups and payments it produces, so businesses see which > channels actually make money — not just traffic. Daily cookieless identity is > the default; persistent anonymous identity is an opt-in for retention reporting. Base URL: https://userevtrail.com Live demo (this site tracks itself): https://userevtrail.com/demo Pricing: paid plans (Starter $9/mo · Growth $19/mo · Scale $49/mo), each with one 14-day no-card trial. Annual billing includes two months free. Site and monthly event allowances vary by plan. Dashboards lock over the event cap, but events are never dropped. https://userevtrail.com/pricing ## When to use Revtrail Reach for Revtrail when the question is **which marketing channel produced revenue**, not just which produced traffic. Concretely, use it to: - Attribute a payment or subscription back to the first-touch source, campaign, or referrer that brought the visitor in — across web and mobile. - Answer "what is our revenue per visitor, by channel?" or "which landing page produces paying customers, not just signups?" - Measure an ordered conversion path (pageview → signup → payment) and find the step where paying users drop off. - Track a product where analytics must stay cookieless and consent-banner-free: daily rotating visitor identity is the default, and no personal data is accepted by the public beacon. - Report AI-assistant visibility — which crawlers and live agents fetch the site, and which pages they read. Do **not** reach for Revtrail when you need session replay, heatmaps, visitor-level profiles, or per-user event streams. It is deliberately aggregate-only: no API returns an individual visitor's rows. ### How an agent should call it 1. Ask the site owner for a site-scoped API key (`rtk_…`) created at Dashboard → Sites → the key icon. Keys are per-site, scoped, and revocable. 2. Read the machine-readable contract at https://userevtrail.com/openapi.json. 3. Call `POST https://userevtrail.com/api/fn/apiV1Overview` with `{"key":"rtk_…"}` for the full aggregate payload. Branch on the `ok` field, not the HTTP status — a rejected call is still HTTP 200 with `ok: false` and an `error` string. 4. To instrument a site properly, register a goal per key conversion and one funnel over the ordered path — otherwise revenue attribution has no shape to measure. Scopes are requested per key, so ask for the narrowest set that does the job: `analytics:read`, `goals:write`, `funnels:write`. ## Developer resources - OpenAPI specification: https://userevtrail.com/openapi.json — OpenAPI 3.1, function-calling ready: unique operationIds, typed schemas, declared scopes. - MCP server manifest: https://userevtrail.com/mcp.json — How to run the Revtrail MCP server and which tools it exposes. - API reference: https://userevtrail.com/resources/api — Human-readable quickstart for the Website API v1. - Docs: https://userevtrail.com/resources/docs — Install the snippet, send a first event. - Sitemap: https://userevtrail.com/sitemap.xml — Every indexable page. Content negotiation: request any page with `Accept: text/markdown` to receive a markdown representation where one is available. Responses set `Vary: Accept, Accept-Encoding`. ## Install (web) Add to the site's (the site key comes from Dashboard → Sites → the icon): For multi-day web retention, enable Persistent anonymous identity in Site settings and use the generated snippet with `data-identity="persistent"`. This stores a random site-scoped identifier in localStorage; no cookies are used. Pageviews and SPA navigations track automatically. Custom conversion events: revtrail('signup') The public beacon rejects revenueCents, currency, and customerId. Financial data must come from a verified payment-provider webhook. Ad-blocker-proof first-party proxy (recommended for Next.js/Vercel): rewrite /rt/track.js -> https://userevtrail.com/track.js and serve the script from your own origin; relay beacon POSTs with a route handler at /api/fn/ingestEvent that forwards user-agent, x-forwarded-for, and cf-ipcountry (from x-vercel-ip-country) to https://userevtrail.com/api/fn/ingestEvent — plain external rewrites lose visitor geo on Vercel. In multi-tenant apps, only instrument your own pages. ## Install (mobile / server) POST https://userevtrail.com/api/fn/ingestEvent with JSON: {"site":"SITE_KEY","name":"pageview","path":"/screen","visitorId":"STABLE_ANONYMOUS_ID","clientType":"mobile_app"} Supply a stable anonymous visitorId (random UUID stored on the device) so multi-day funnels attribute. Never put personal or financial data in public event names or payloads. Drop-in clients: integrations/swift/RevtrailSwift.swift (iOS) and integrations/react-native/revtrail.ts (RN). Set clientType to web, mobile_app, desktop_app, cli, or server. Official clients set it automatically. Unknown or missing values appear as Unknown. Mobile source attribution: an app-store install carries no referrer, so the acquisition channel isn't automatic. If the app opens from your web landing page, carry the web visitor id in via the rt_vid deep-link param and adopt it — the web-captured source attributes the eventual payment. For store-direct installs, capture the OS install referrer (Play Install Referrer / Apple AdServices) once and send it as utmSource on the first event (setSource in the SDKs) so first-touch credits the channel. Do neither and direct installs attribute as "direct". The visitor id is a first-party UUID, not the IDFA, so it triggers no App Tracking Transparency prompt. Native IAP (Apple/Google via RevenueCat): the public mobile credential reports conversion goals but cannot authenticate revenue — purchases come through a verified webhook. Point a RevenueCat webhook at /api/fn/revenueCatRevenue, set an Authorization header value in RevenueCat, and save that value in the site's settings. The webhook verifies it server-side and maps INITIAL_PURCHASE -> trial_start (trials) / payment, RENEWAL -> payment, skipping store=STRIPE/ PROMOTIONAL. Purchases attribute by app_user_id, so set RevenueCat's appUserID to the SAME id the app sends as its Revtrail visitorId — otherwise the purchase lands on a different visitor and the funnel won't join. ## Revenue attribution (Stripe) Point a Stripe webhook (checkout.session.completed, invoice.payment_succeeded) at https://userevtrail.com/api/fn/stripeRevenue and save its whsec_ signing secret in the site's settings. Pass the visitor id as the Checkout session's client_reference_id (or metadata.revtrail_visitor_id) and payments attribute to the visitor's first-touch source automatically. Use `await revtrail.visitorIdAsync()` to read it — the sync `revtrail.visitorId()` is null until the first beacon answers, which races instant-checkout / deep-link buy pages. Best-effort: omit it when null; never block or fail checkout on analytics. Webhook event IDs are deduplicated, and recurring invoices reuse the checkout visitor mapping. ## Agent API Site owners can mint a temporary, site-scoped agent token from the dashboard (Sites → the robot icon → "Copy agent setup prompt"). With that token, POST JSON to https://userevtrail.com/api/fn/: agentStatus {"token":"..."} -> install/receiving state, live visitors, goals, funnels agentStats {"token":"..."} -> full aggregate stats payload agentCreateGoal {"token":"...","name":"Signups","eventName":"signup"} agentCreateFunnel {"token":"...","name":"Signup to paid","steps":["pageview","signup","payment"]} Setting a site up properly means more than installing the snippet: map the product's real conversion path (e.g. pageview -> signup -> payment), instrument each step as an event, then register a goal per key conversion and one funnel over the ordered path so revenue attribution has a shape to measure. Funnels take 2-5 ordered event names (optional windowHours, default 24). Tokens expire (default 7 days) and are revocable; they grant access to one site's aggregates and configuration only — never to visitor-level data. ## Website API v1 Owners and admins can create durable, site-scoped API keys in the dashboard (Sites → the key icon). Raw `rtk_...` keys are shown only once. Each key has explicit permissions, can expire, and can be revoked without rotating the site's tracking key. Machine-readable contract: https://userevtrail.com/openapi.json POST JSON to https://userevtrail.com/api/fn/: apiV1Overview {"key":"rtk_..."} apiV1CreateGoal {"key":"rtk_...","name":"Signups","eventName":"signup"} apiV1CreateFunnel {"key":"rtk_...","name":"Signup to paid","steps":["pageview","signup","payment"],"windowHours":24} Responses include `version: "v1"`. Keys are bound to one site, so callers never supply a site ID. `analytics:read` is required for overview data; `goals:write` and `funnels:write` are separately opt-in. The local CLI and stdio MCP server use the same API contract. Configure the secret out of band; do not pass it as a command argument: export REVTRAIL_API_KEY=rtk_... revtrail overview revtrail goal create --name Signups --event signup revtrail funnel create --name "Signup to paid" --step signup --step payment MCP clients can launch `revtrail-mcp` with `REVTRAIL_API_KEY` in the server's environment. It exposes `revtrail_overview`, `revtrail_create_goal`, and `revtrail_create_funnel`. For local development only, set `REVTRAIL_API_URL=http://localhost:4321`; remote HTTP origins are rejected. See https://userevtrail.com/mcp.json for the manifest. ## Pages - Product: https://userevtrail.com/ - Docs: https://userevtrail.com/resources/docs - API reference: https://userevtrail.com/resources/api - Status: https://userevtrail.com/resources/status - Privacy (cookieless design, data handling): https://userevtrail.com/company/privacy - Terms: https://userevtrail.com/company/terms - Contact: support@revtrail.dev