npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zalify/analytics

v0.2.6

Published

## Install

Readme

Next.js integration for @zalify/analytics

Install

pnpm add @zalify/analytics

Peer 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 useEffect above fires once on mount (initial load) and again on every client-side navigation via pathname.

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

  • track is async; use void track(...).catch(...) or await to avoid unhandled rejections.
  • eventId (except for Scroll): optional; when omitted the SDK uses uuid(). Pass it as the second argument when you need to align with Shopify event.id or 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: PageViewedData is 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 pathname changes (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 cartLine is 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 call trackPageView, etc.; behavior matches track.