@zalify/analytics
v0.2.6
Published
## Install
Readme
Next.js integration for @zalify/analytics
Install
pnpm add @zalify/analyticsPeer dependencies: react and react-dom (^18 or ^19).
App Router (recommended)
Root app/layout.tsx is usually a Server Component. Add a client wrapper ZalifyAnalytics: the layout passes no props; ZalifyAnalytics hardcodes the workspace_id (a public string) and optional creator_id for creator-shop flows, then renders <Analytics />.
components/zalify-analytics.tsx
"use client";
import { Analytics, track, StandardEvents } from "@zalify/analytics/react";
import { useEffect } from "react";
import { usePathname } from "next/navigation";
export function ZalifyAnalytics() {
const pathname = usePathname();
useEffect(() => {
void track(StandardEvents.PageView, {}).catch(console.error);
}, [pathname]);
return (
<Analytics
workspace_id="your-workspace-id"
/>
);
}The workspace_id is a public string — you can hardcode it directly without needing an environment variable. For creator_id in creator-shop flows, you can fetch it from your BFF/API, global store, or session and pass it in.
What's automatic vs explicit:
- Scroll tracking (at 5/10/20/40% depth) is wired up automatically by
<Analytics />— no extra code needed.- Page views must be called explicitly. The
useEffectabove fires once on mount (initial load) and again on every client-side navigation viapathname.
app/layout.tsx
import type { ReactNode } from "react";
import { ZalifyAnalytics } from "@/components/zalify-analytics";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<ZalifyAnalytics />
{children}
</body>
</html>
);
}Analytics from @zalify/analytics/react is a Client Component ("use client"). ZalifyAnalytics is also a Client Component and can be imported from a Server layout with no props.
<Analytics /> props
These are passed from ZalifyAnalytics into <Analytics /> (or directly if you use <Analytics /> in another client module).
| Prop | Required | Description |
|------|----------|-------------|
| workspace_id | Yes | Workspace ID |
| creator_id | Depends | Creator storefront flows need the creator ID |
| shopify_shop_id | No | Required when enabling Shopify DOM tracking |
| pageViewEnabled | No | Default true |
| enabledShopifyTracking | No | Default false; when true, pass shopify_shop_id or ShopifyTracking.init will not run |
| enabledAdsTracking | No | Default false |
| enabledNewZalifyTracking | No | Default true |
Defaults inside the component include appEnv: "headless" and autoSessionStart: true. Props you pass override the matching fields.
Event tracking (Headless)
<Analytics /> only initializes the SDK. For page views, product views, add to cart, leads, etc., call track + StandardEvents from the main package (same behavior as ZalifyHeadlessTracking.track*, aligned with Shopify Custom Pixel / Web Pixels).
import { track, StandardEvents } from "@zalify/analytics";
// Most events: second argument is data; omit eventId and the SDK generates a uuid
await track(StandardEvents.PageView, pageViewedData);
await track(StandardEvents.PageView, eventId, pageViewedData); // explicit eventId (e.g. match Pixel event.id)
// Scroll: two arguments only, no eventId
await track(StandardEvents.Scroll, scrollParams);
// Add to cart payload must include cartId (type ProductAddedToCartTrackData)
await track(StandardEvents.ProductAddToCart, { ...productAddedToCart, cartId: "…" });StandardEvents values not supported by track (e.g. SessionStart, Identify) throw at runtime.
Conventions
trackis async; usevoid track(...).catch(...)orawaitto avoid unhandled rejections.eventId(except forScroll): optional; when omitted the SDK usesuuid(). Pass it as the second argument when you need to align with Shopifyevent.idor similar.data: use exported SDK types (see below). Jump to definition in your IDE for nested fields; you usually do not need to install@shopify/web-pixels-extension. Semantics match Shopify Web Pixels.
TypeScript imports from @zalify/analytics
import { track, StandardEvents } from "@zalify/analytics";
import type {
PageViewedData,
CollectionViewedPayload,
ProductViewedData,
ProductAddedToCartTrackData,
LeadData,
SearchSubmittedData,
CheckoutStartedData,
PaymentInfoSubmittedData,
CheckoutCompletedData,
} from "@zalify/analytics";For add to cart, use ProductAddedToCartTrackData (ProductAddedToCartData & { cartId: string }) with track(StandardEvents.ProductAddToCart, data).
Page view
const data: PageViewedData = {};
await track(StandardEvents.PageView, data);
// await track(StandardEvents.PageView, eventId, data);- Type:
PageViewedDatais effectively an empty object{}at the type level; in Headless mode page context is collected from the browser by the SDK. - Usage: On SPA navigations, call again when
pathnamechanges (e.g.usePathname+useEffect).
Collection viewed
const data: CollectionViewedPayload = {
collection: {
id: "...",
title: "...",
productVariants: [
/* Fill using IDE hints for CollectionViewedPayload */
],
},
};
await track(StandardEvents.CollectionViewed, data);
// await track(StandardEvents.CollectionViewed, eventId, data);Product view
const data: ProductViewedData = {
productVariant: {
/* Fill using ProductViewedData hints */
},
};
await track(StandardEvents.ProductView, data);
// await track(StandardEvents.ProductView, eventId, data);Product add to cart
const data: ProductAddedToCartTrackData = {
cartLine: {
/* Fill cartLine per type hints */
},
cartId: "your-cart-id",
};
await track(StandardEvents.ProductAddToCart, data);
// await track(StandardEvents.ProductAddToCart, eventId, data);- Note: If
cartLineis missing, the SDK returns early and does not send the event.
Lead
const data: LeadData = { email: "[email protected]" };
await track(StandardEvents.Lead, data);
// await track(StandardEvents.Lead, eventId, data);Other events (track and data types)
| Call | data type (@zalify/analytics) |
|------|-----------------------------------|
| track(StandardEvents.SearchSubmitted, data) | SearchSubmittedData |
| track(StandardEvents.CheckoutStarted, data) | CheckoutStartedData |
| track(StandardEvents.PaymentInfoSubmitted, data) | PaymentInfoSubmittedData |
| track(StandardEvents.CheckoutCompleted, data) | CheckoutCompletedData |
| track(StandardEvents.Scroll, scrollParams) | ScrollChangeHandlerParams from @analytics/scroll-utils (two arguments only, no eventId) |
You may pass eventId as the second argument for all of the above except Scroll. Ensure <Analytics /> has already run init; otherwise calls may throw or wait for initialization.
Advanced: You can still
import { ZalifyHeadlessTracking } from "@zalify/analytics"and calltrackPageView, etc.; behavior matchestrack.
