Revfaro Docs

Tracking

JavaScript SDK

Use Revfaro's typed browser tracker in JavaScript or TypeScript applications, with cookie or cookieless tracking and lifecycle cleanup.

In short

The revfaro browser SDK is an optional alternative to the script tag. It provides typed initialization, automatic pageviews, goals, identify and teardown without runtime dependencies, with a dedicated cookieless entry. Initialize only in the browser and copy the website ID and endpoint from Setup.

On this page

Package availability

The official revfaro package is available on npm. Install it in your app, or use the script installation without a build tool. Both methods use the same tracking engine.

The SDK uses the MIT license and has no runtime dependencies. It is a browser tracker installed with npm, not a Node.js server event client. For server-side revenue, use the Payments API.

Start tracking

Choose npm package under Settings → Setup. The snippet includes your website ID and collection endpoint. Install the package in your app:

Terminal
npm install revfaro

Initialize once from your browser entry point:

TypeScript
import { init } from 'revfaro';

const tracker = init({
  siteId: 'YOUR_SITE_ID',
  endpoint: 'https://revfaro.com/api/event',
});

// Keep this instance for goals, identity and unmount cleanup.

Use the npm tracker or the hosted script once per page. The npm API does not create window.revfaro; keep the returned instance to record actions and clean up. Different tracking configurations can record separate events, so remove the script tag when switching to npm.

Pageviews and History API navigation are automatic. Hash-only navigation does not add a pageview. HTML goal attributes, outbound clicks and visible engagement work as with the hosted script.

For a router that records views itself, use autoTrack: false, then call tracker.pageview() after each route change. Each manual call records a view of the current URL, including repeated calls.

Cookieless tracking

TypeScript
import { init } from 'revfaro/cookieless';

const tracker = init({
  siteId: 'YOUR_SITE_ID',
  endpoint: 'https://revfaro.com/api/event',
});

The dedicated entry excludes cookie identity code. It follows the same cookieless rules as the hosted script. tracker.attribution() returns {}. The explicit rf_ignore opt-out flag remains available; it is the only local-storage use. The main entry also accepts mode: 'cookieless'.

Server rendering and cleanup

Importing the SDK during server rendering is safe. Calling init() without a browser returns an inactive instance and sends nothing. Initialize a new instance in your framework's browser mount hook.

For React or Next.js, mount one client component in the root layout. Route changes are automatic; do not add the current pathname to the effect dependencies or manually send every pageview.

TSX
'use client';

import { useEffect } from 'react';
import { init } from 'revfaro';

export function Analytics() {
  useEffect(() => {
    const tracker = init({
      siteId: 'YOUR_SITE_ID',
      endpoint: 'https://revfaro.com/api/event',
    });
    return () => tracker.destroy();
  }, []);
  return null;
}

If other components send goals or identify visitors, share the initialized instance through a module or your framework's context. The Setup snippet includes a shared getTracker() helper. Do not create a tracker during a component render, and do not reuse an inactive server instance after hydration.

Matching init() calls share one tracking engine, while each caller receives its own handle. Call destroy() on the handle you own when your integration unmounts. The last active handle removes the engine's listeners, observers and timers and stops future retries, preserving other scripts' later history wrappers. Cleanup does not erase cookies, retract requests already sent or send a final event.

The initial automatic pageview waits until the next task. This allows React Strict Mode to discard its temporary mount without counting two visits. Goals, identity calls and navigation flush a pending initial pageview first. Different site or tracking configurations are not deduplicated.

Goals, identity and attribution

Call tracker.goal('signup', { source: 'pricing' }) after a successful action. tracker.track() is an alias for goal(). Use tracker.identify({ user_id: 'customer-123' }) after sign-in to connect visits to a known customer. Avoid sending passwords, API keys or other secrets as properties.

With SDK 0.1.1 or later, call tracker.reset() after logout or before identifying a different account. In cookie mode this rotates both the visitor and session IDs, including the in-memory fallback when cookies are blocked. It discards pending engagement and retries and refreshes existing checkout-link metadata. Shared handles on the same cookie domain observe the new identity; other tabs detect changed visitor cookies before their next send. Clear queued user-specific actions and synchronize authentication across tabs in your application as well.

Reset keeps tracking active and does not send a pageview. When driving pageviews manually, record the next view yourself. Already sent requests and previously collected data are not erased. destroy() only releases a handle and does not rotate identity. In cookieless mode, reset() clears local timers and engagement but cannot change the server-derived daily identity. Avoid identifying users in cookieless mode when accounts on a shared browser must remain separate.

In cookie mode, tracker.attribution() returns rf_visitor_id and rf_session_id. Your checkout integration can forward these as metadata using your payment provider's guide. The SDK never needs your payment-provider secret. Cookieless mode returns an empty attribution object.

Privacy and delivery

SDK 0.1.1 or later supports a strict query allowlist:

TypeScript
const tracker = init({
  siteId: 'YOUR_SITE_ID',
  endpoint: 'https://revfaro.com/api/event',
  allowedQueryParams: ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'],
});

Only these case-insensitive query names survive in every event's page URL and in its initial referrer. Empty values are removed. Use [] to remove all query parameters; omit the option to retain the default sensitive-name filter. Sensitive names such as token and email are always removed, even if listed. Fragments and URL credentials are removed in either mode. Outbound destinations omit all query values. Automatic pageviews ignore navigation that only changes removed parameters. Manual pageview() calls still record one view each.

This does not sanitize URL path segments, custom goal properties or identity traits. Keep secrets out of those values. An allowlist that removes payment return IDs prevents return-page revenue matching; forward tracker.attribution() as provider metadata to preserve attribution.

For the hosted script, the equivalent is data-allowed-query-params="utm_source,utm_campaign". An empty attribute removes all query parameters. Use window.revfaro('reset') after logout.

Initialize only after your application's required consent decision. autoTrack: false disables automatic pageviews but leaves other tracking enabled; it is not a consent switch. To stop tracking, destroy every active instance. Existing cookies and already collected data are not removed.

Automated browsers, localhost and the explicit rf_ignore opt-out are ignored by default. The allowLocalhost option enables browser sending for development; the collector still checks the site's registered domain. Use a registered staging subdomain for end-to-end verification.

Events are delivered in the background. Fetch omits credentials; beacons follow the browser's cookie policy and cannot override credentials. Network errors and server errors retry at most twice with the same event ID; 4xx responses are not retried. Closing a tab, blockers or connectivity can still lose events. A 202 response does not mean the event is already visible on the dashboard.

First-party proxy

Use endpoint: '/rf/event' when your server forwards this path to Revfaro. Follow the proxy guide and keep the site's proxy secret on the server. Never put a site API key or proxy secret in browser code.

Last updated · View as Markdown