Prebit Developer Docs
Storefront Framework (Boron)

analytics

Session/page-view tracking, heartbeat, Web Vitals, and a business-event bus — the same data Prebit's own dashboard reads.

Boron ships two different tracking mechanisms because the two things they track have two different trust requirements — one runs in your app's proxy.ts, the other runs in the browser.

proxy.ts — page views and sessions

/api/store/{storeId}/track (Prebit's real, existing traffic endpoint — the same one every Prebit storefront's dashboard reads geo/device/ referrer/UTM/session data from) is designed to be called by whatever server owns the visitor-facing cookie, not by an arbitrary browser — it isn't CORS-open for a third-party origin. Since a Boron app can be hosted anywhere, that server is your own app, in your own proxy.ts (Next.js 16's renamed middleware.ts convention):

// proxy.ts
import { trackPageView } from "@prebit/boron/server";

export const proxy = trackPageView;

export const config = {
  matcher: ["/((?!_next/static|_next/image|favicon.ico|api/).*)"],
};

trackPageView() sets a sliding-window session cookie (sid, 30 minutes, httpOnly — plus a sid_public non-httpOnly mirror the client-side pieces below read), then fire-and-forgets the page-view to Prebit along with geo-relevant headers (IP, user agent) and, on a new session only, referrer/UTM/landing-page attribution. Never throws, never blocks the real response.

<AnalyticsProvider> — heartbeat, Web Vitals, and page_view for adapters

Mount once, near <CartProvider>:

// app/layout.tsx
import { CartProvider, AnalyticsProvider } from "@prebit/boron/client";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <AnalyticsProvider>
          <CartProvider>{children}</CartProvider>
        </AnalyticsProvider>
      </body>
    </html>
  );
}

This starts three things, all direct browser calls (unlike page-view tracking above, /heartbeat and /vitals are already CORS-enabled for any origin, so no proxy route is needed):

  • Heartbeat — a POST /heartbeat every 60s while the tab is visible (paused via the Page Visibility API), keeping the dashboard's live- visitor count accurate for someone who opens a page and just stays on it.
  • Web Vitals — LCP/INP/CLS reported via the real web-vitals package, fetch(..., { keepalive: true }) (deliberately not sendBeacon — it always attaches ambient cookies with no way to opt out, which turns this endpoint's uncredentialed, wildcard-CORS response into a silently blocked request).
  • page_view on the event bus (see below) on every route change — for third-party pixel/analytics adapters that need a client-side signal, distinct from the proxy's own page-view write.

track() / subscribe() — the business-event bus

import { track, subscribe } from "@prebit/boron/client";

Auto-fired for you: product_view (from <Product>, on mount), add_to_cart (from useCart().add), checkout_started (from useCheckout().initiate), page_view (from <AnalyticsProvider>, on every route change). Fire anything else yourself:

track("purchase", { event_id: order.id, value: order.total, currency: "INR", items: order.items });
track("newsletter_signup", { source: "footer" });

purchase is never auto-fired

Only your own order-confirmation page knows the order actually happened — call track('purchase', { event_id, ... }) there once payment is confirmed. Passing event_id also gets you automatic exactly-once dedup (via sessionStorage) so a refreshed confirmation page can't double-count it.

subscribe(name, callback) wires up an adapter — same shape new-frontend's embedded prebit.analytics object uses for its Meta Pixel subscriber:

subscribe("purchase", (name, props) => {
  myAnalyticsTool.log(name, props);
});

Meta Pixel — built in, opt-in

Set NEXT_PUBLIC_PREBIT_META_PIXEL_ID and <AnalyticsProvider> loads the pixel and forwards page_view → PageView and purchase → Purchase automatically. Leave it unset and nothing pixel-related loads at all.

On this page