Browse documentation by task
Developer reference

Analytics API and data definitions

Use scoped event queries, visitor journeys and verified revenue reports without confusing browser events with payment evidence.

Authentication and tenant boundaries

Dashboard read endpoints require the signed-in HttpOnly session cookie. Owners with verified email can issue project-bound read-only bearer tokens, shown once and stored as hashes, with expiry up to 90 days. read:reports permits summary/trend/search; read:journeys additionally permits raw event and journey reads. Tokens never authorize account access or mutations. Owners can mutate their own projects; verified, accepted Viewers can read shared projects but cannot change settings, billing or connections. Project IDs and public tracker IDs are routing identifiers, not authentication. Do not copy a browser session into public client code.

API writes require JSON and same-origin checks. Exact allowed website origins apply to public collection. Cookies are Secure in production. A missing session is 401; inaccessible projects are 404. Invalid query controls return 400.

Automatic navigation policy

startPageviews({mode, routes, initial}) explicitly opts into mapped pageview automation. mode is history (default) or hash; routes is a required object of 1–50 exact safe paths or terminal /* prefixes mapped to static safe page labels. initial defaults true. stopPageviews() stops only navigation automation; consent(false) stops all collection and clears the stored pseudonym.

History pushState/replaceState and popstate are observed only while consented. Hash mode additionally handles #/route changes. Query strings are ignored for page identity; ordinary history fragments do not become pages. Repeated equivalent configuration and duplicate navigation signals do not add events. Manual track(pageview) is independent, so do not combine it with automatic pageviews for the same visit.

GPC=true blocks consent grants, pageviews, named events and visitor ID access. A newly observed GPC signal withdraws active tracking and aborts pending requests where possible. Clearing GPC does not silently restore consent. This is an implementation behavior, not a claim of universal legal compliance.

Consented browser collection

The tracker never grants consent automatically. Connect consent and withdrawal to your consent manager. Page is an explicit nonpersonal path label; no full URL, search query or fragment is collected. Do not place names, account IDs or tokens in path labels. Referrer, if supplied, must be a hostname; device is an optional coarse declared category, not fingerprinting. Country is not inferred from browser input.

reylin.consent(true); // only after the visitor permits it
await reylin.track('pageview', {page:'/pricing', device:'desktop'});
await reylin.track('signup', {page:'/signup'});
// On withdrawal:
reylin.consent(false);

Summary and ordered funnel

GET /api/projects/:id/summary accepts days (1–366), currency (uppercase ISO code), source, steps (comma-separated names), and conversionHours (1, 24 or 168). Days end at the current UTC time. Use page:/pricing for exact declared pageviews or page:/docs/* for a safe declared-path prefix, mixed with named goals and final $payment. A funnel requires strictly ordered timestamps; any qualifying entry can start a path and each pseudonymous visitor is counted once. Source applies to entry. Missing consent or visitor linkage cannot create a payment conversion.

The reserved final $payment step reads successful ledger payments only. A browser event called purchase or payment is never financial proof. Refunds do not erase successful-payment conversions. Revenue totals use integer provider minor units; currencies are never combined or implicitly converted.

Dimension queries and pagination

GET /api/projects/:id/events accepts from/to ISO timestamps (maximum 366-day range), limit (1–1000), cursor, groupBy, and filters as URL-encoded JSON. Dimensions: source, type, page, referrer, country, device. Missing values are Unknown, not guessed. Operators: is, is_not, contains, not_contains. Up to ten filters combine with AND; contains comparison is case-insensitive.

Omit groupBy for chronological individual events; set it for event and distinct-visitor counts. Responses include the normalized from/to bounds and nextCursor. Reuse exactly those bounds and filters on subsequent requests, since a moving end time changes the query. Cursors are query-bound, not access credentials.

const query = new URLSearchParams({
  from:'2026-10-01T00:00:00Z', to:'2026-10-31T23:59:59Z',
  groupBy:'page', limit:'100',
  filters:JSON.stringify([{dimension:'source',operator:'contains',value:'Google'}])
});
const response = await fetch('/api/projects/PROJECT_ID/events?' + query);

Pseudonymous visitor journeys

GET /api/projects/:id/journey accepts visitorId, from/to, limit and cursor. It returns consented event facts, linked successful payments, and refund states for those payments in chronological order. It does not resolve a person, email, device graph or cross-site identity. A missing visitor returns an empty journey rather than fabricated history. Refund amounts remain currency-specific and statuses remain visible.

Provider connection and import semantics

Customer Stripe analytics and your Reylin subscription are separate trust boundaries. Connection onboarding verifies the provider account, creates a draft with a stable webhook endpoint, then activates the encrypted signing secret. Signatures validate raw delivery bytes; money is reconciled from the current provider object and deduplicated.

The bounded 7/30-day historical payment import does not reconstruct historic visitors, every refund or disputes. Coverage warnings remain visible. Disconnected revenue is unavailable; a zero stored-payment count is not proof of zero real sales. The live provider acceptance test remains a deployment prerequisite.

Search data is not revenue

Search Console integration is separately authorized read-only search reporting. Clicks, impressions, CTR and position are Google search metrics, not payments or unique website visitors. Google date boundaries are Pacific Time, unlike the UTC event-reporting window. API results may omit rows and return top rows; bounded pagination never proves an exhaustive export. OAuth provisioning and real account authorization require a separately configured integration.

Saved configuration and calendar reports

GET and POST /api/projects/:id/config/:kind support segment, funnel, goal, note and preferences. Updates use /:id and deletes use POST {action: delete}. Only owners mutate. Notes are owner-only; other saved definitions are readable by shared Viewers. Goal event keys cannot change; display labels never rewrite event history. Preferences are saved explicitly and applied to the current report on request.

GET /api/projects/:id/trend accepts from, to, timezone, bucket hour/day/week/month, currency, and compare=true. Its half-open window [from,to) prevents boundary double counting. Buckets follow actual local calendar boundaries including daylight-saving transitions; weeks start Monday. Previous-period comparison has equal elapsed duration, and a zero baseline returns null percentage change.

Customer subscriptions and recurring contracts

Customer analytics can reconcile customer.subscription.created, customer.subscription.updated and customer.subscription.deleted events. Only subscription IDs are retained from signed event triggers; current subscription state is retrieved through the matching verified account. Subscription snapshots never create cash-receipt ledger entries.

GET /api/projects/:id/subscriptions returns gross contracted monthly recurring amounts, separated by currency, before discounts and tax. Fixed licensed recurring items only: paused, metered, tiered, transformed, unknown and stale snapshots are excluded with coverage warnings. Trial equivalents are separate from active MRR. Exact rational aggregation is rounded half-up once per currency. Month/year/week/day normalization is explicitly reported.

Known subscriptions refresh in bounded background batches. Failed reads exclude that subscription immediately; snapshots older than 24 hours are not reported as current. Owners can start a resumable discovery scan under Recurring contracts. Completion means available current subscriptions were paginated, not that every historical lifecycle or changing provider record was reconstructed. Discovery requires read permission for subscription listing and retrieval.

Declarative goals and safe queues

After explicit consent, data-reylin-event on a clickable element dispatches one named goal per click. data-reylin-view-event dispatches once when at least half the element is visible per consent grant. Optional data-reylin-page supplies an explicit safe path label. Form values, link destinations and DOM text are never harvested. Withdrawal disconnects observers and aborts pending requests where supported.

Preload and denied-consent queue entries are discarded, not replayed later. Postload reylinQueue.push([track, eventName, dimensions]) dispatches only while consent is currently true. No automatic pageview or automatic consent is added.

Observed sessions and private visitor search

GET /api/projects/:id/session-metrics reports a session-entry cohort inside [from,to). Sessions group consented events by pseudonymous browser ID and a gap strictly greater than 30 minutes. Stored prior history prevents an artificial new session merely because a report window starts; retention and deletion can still remove continuity evidence.

A bounce is a session closed by inactivity with exactly one pageview and no non-pageview events. Open sessions are excluded from the bounce denominator. Mean observed span is the difference between first and last recorded event, not time-on-site or an attention estimate. First observed pageview and last observed page labels are not proof of true landing/exit behavior. Missing data is Unknown, not geolocation or an invented browser profile.

GET /api/projects/:id/visitors is private and requires a project session/Viewer or read:journeys token. It supports source, eventType, customerStatus all/paid/unpaid, identifier search, limit and query-bound cursor. Source and event type filters require the same observed event. Counts describe that visitor’s observed events in the chosen window. Paid means linked ledger payments in that same window; browser purchase events do not establish it. Payment counts are separate per currency.

Aggregate session metrics permit read:reports tokens and never include individual visitor IDs. Visitor rows are pseudonymous observations, not verified people, emails, identity matching or CRM profiles.

Acquisition dimensions and frozen revenue

Explicit event dimensions can include campaign, medium, content and term as lowercase nonpersonal slugs up to 64 characters, hostname as a DNS hostname, and coarse browser/OS categories. They are declared labels: Reylin does not infer them from a fingerprint or automatically capture raw search queries. Missing dimensions stay Unknown. Existing page, referrer and device fields remain supported.

New verified payment records freeze the consented first-touch dimension snapshot within the configured attribution window. A later event, deleted event history or changed provider metadata cannot rewrite it. Legacy payments without a dimension snapshot remain Unknown for that dimension; no historical attribution is fabricated.

GET /api/projects/:id/acquisition accepts dimension, metric, from, to and currency. It is an aggregate read for project sessions/Viewers and read:reports tokens. The report uses a payment cohort: payments inside the half-open window and their eligible succeeded refunds before its end, capped per payment. It is not a refund cash-movement report. Money is kept separately by currency. Conversion requires an observed consented visitor in the same dimension bucket/window; zero-denominator ratios are unavailable, not invented zeroes.

Reports return at most 100 sorted buckets plus explicit omitted-bucket counts/totals. Visitors can appear in multiple dimension buckets, so bucket visitor sums need not equal globally unique visitors. Saved event-query segments support the same declared acquisition/platform dimensions.

Categorical goal properties

Owners first declare enum-only schemas in Goal properties, for example signup → plan → starter or growth. Event and property schema keys are lowercase snake case up to 32 characters; at most 20 event schemas, 8 properties each and 20 values per property. Labels are short lowercase slugs, never personal identifiers or secrets. Membership in an enum does not prove anonymity: the project owner is responsible for nonpersonal labels. Unknown keys or values are rejected before persistence and quota consumption.

Send properties as the third tracker argument, for example reylin.track("signup", {page:"/pricing"}, {plan:"starter"}). Consent is required. No DOM text or form values are collected automatically. The server validates against that project’s current schema. Schema edits affect future events, not historical records.

GET /api/projects/:id/goal-properties accepts eventType, property, from and to (half-open UTC window). Configured categories and a distinct missing bucket contain event and unique-visitor counts, never visitor IDs. Removed historical categories count as excludedEvents/excludedVisitors without echoing removed labels. Owners, Viewers and read:reports tokens can read this aggregate; only owners can GET/POST /property-schemas. Raw properties remain part of journey-scoped event reads.

Owner visitor cleanup jobs

GET /api/projects/:id/visitor-erasure lists that owner’s sanitized job statuses; append the job ID for one status. POST to the collection starts a job with visitorId, a stable random requestId and retainFinancialRecords:true. The raw visitor pseudonym belongs in the JSON body, never a URL. Verified owner sessions only; Viewers and API bearer tokens cannot start or inspect these jobs.

The same request ID and target are idempotent; a conflicting target is rejected. Public status omits suppression digests and worker tokens. Completion preserves money and frozen attribution while unlinking the known pseudonym; it is not a legal/physical/provider-side erasure guarantee. Read the Data lifecycle guide and retained-data acknowledgement before use.

Collection and financial writes are paused for the affected project while transaction-local fences and resumable batches run. Jobs waiting on uncertain sends remain visibly pending. Manual retention and project/account deletion cannot race an active cleanup. Scope limits include legacy unindexed receipts, user-authored notes/labels, external copies and backups.

Owner data export inventory

GET /api/account/data-export returns the supported local sections, field projections, availability and exclusions. Add section, optional owner projectId, limit (1–100) and cursor to read a page. The server derives the owner from the authenticated session, never a supplied owner ID. Viewer roles and read-only API tokens do not authorize this account-level route.

The cursor is section/owner/project-bound. Rows are selected through static SQL and JSON field allowlists; there is no arbitrary database, table, path or column parameter. Missing or schema-incompatible storage returns explicit unavailable coverage. Credential hashes, ciphertexts, raw tokens and worker internals are omitted. The result is not an atomic snapshot or a universal completeness claim.

Owner reports and alerts

Project owners can opt into a weekly report with an explicit UTC weekday/hour and currency, or named event alerts. Messages go only to the verified account email; there is no arbitrary recipient field. New goal alerts start from the server receipt checkpoint, so enabling a rule never replays earlier events. A late-arriving event can alert if it arrives after the rule was enabled. Browser goals are not proof of revenue.

Delivery is independently disabled by default. Dry-run rules may queue reports but do not send email. An accepted message means the email provider accepted it, not that it reached the inbox. Pending queue and owner daily delivery limits suppress excess notifications; no overage charges are created. Disable all in Reports & alerts cancels queued messages. Previously accepted messages cannot be recalled.

Only owner sessions can access /api/projects/:id/notifications. Read-only bearer tokens and Viewers cannot configure reports or read the private queue. POST actions are weekly, goal, remove_goal and unsubscribe.

Public aggregate links and widgets

Owners explicitly create a share in project Sharing settings. Anyone holding its bearer URL can read only aggregate visitors, events, payments, gross/refunded/net receipts, currency and period. No sources, visitors, notes or underlying records are included. Links and widget embeds are not published automatically. Rotation or revocation invalidates the old URL immediately, but cannot erase copies someone already viewed.

The shared page and embed are noindex and use no-referrer/no-store headers. The widget is frameable by design only after an owner creates the capability. Private dashboard routes remain unframeable. A zero aggregate ledger count does not establish that a disconnected real business had no sales.

Read-only SDK and CLI

reylin-client.mjs is a dependency-free server-side SDK exposing summary/events/journey/trend/search. reylin-cli.mjs exposes the same read operations and prints JSON. Set REYLIN_API_TOKEN in the environment, never command-line arguments or browser bundles. Tokens cannot mutate billing, provider settings or user accounts. These source tools are local; no npm registry package or third-party MCP connection has been published.

node reylin-cli.mjs summary --origin https://YOUR_APPROVED_HOST --project PROJECT_ID --days 30 --currency USD

Errors and data handling

Never retry a chargeable action with a new idempotency key just because its response was lost. Do not put secrets in query strings, custom events or support screenshots. Exports and pseudonymous journeys are authenticated project data; restrict their access and honor retention/deletion policies. There is no public unauthenticated analytics read API.

References

This documentation describes the local implementation, not proof of a live provider integration. Review credentials, consent, security and deployment before collecting real customer data.
Explore the synthetic demo →