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

@li2/analytics

v0.5.1

Published

Li2 Analytics SDK for conversion tracking

Readme

@li2/analytics

Conversion tracking SDK for Li2.ai. Track leads and sales from your marketing campaigns with automatic click ID attribution.

Installation

npm install @li2/analytics
# or
pnpm add @li2/analytics
# or
yarn add @li2/analytics

Client-Side SDK

The client-side SDK automatically captures click IDs from URLs (?uid=...) and cookies, making it easy to track conversions in the browser. You don't need to pass clickId manually - it's auto-detected.

Note: If you need to track conversions on the server (e.g., after a webhook or server-side payment confirmation), use getClickId() to capture the click ID on the client and pass it to your server. See Server-Side SDK for details.

Installation Snippet

Add this snippet to your <head> tag. It loads the SDK asynchronously and queues any tracking calls made before the script loads.

<script>
  !(function (c, n) {
    c[n] = c[n] || function () { (c[n].q = c[n].q || []).push(arguments); };
    ["trackLead", "trackSale", "trackEvent", "identify"].forEach((t) => (c[n][t] = (...a) => c[n](t, ...a)));
    var s = document.createElement("script");
    s.defer = 1;
    s.src = "https://unpkg.com/@li2/analytics/dist/index.global.js";
    s.setAttribute("data-publishable-key", "li2_pk_...");
    document.head.appendChild(s);
  })(window, "li2Analytics");
</script>

Script Tag Usage

<script
  src="https://unpkg.com/@li2/analytics/dist/index.global.js"
  data-publishable-key="li2_pk_..."
></script>

<script>
  // Track a lead
  li2Analytics.trackLead({
    eventName: 'signup',
    customerExternalId: 'user_123',
    customerName: 'John Doe',
    customerEmail: '[email protected]',
  })

  // Track a sale (click ID auto-detected from cookie/URL)
  li2Analytics.trackSale({
    customerExternalId: 'user_123',
    amount: 4999, // $49.99 in cents
    eventName: 'purchase',
    invoiceId: 'inv_abc123',
  })

  // Track a direct sale (no tracked link — pass clickId: "" explicitly)
  li2Analytics.trackSale({
    customerExternalId: 'user_123',
    amount: 2500,
    clickId: '', // Direct Sale — no link attribution
  })

  // Track a named event
  li2Analytics.trackEvent('button_clicked', { category: 'cta' })
</script>

Script Tag Attributes

| Attribute | Description | | --------- | ----------- | | data-publishable-key | Your publishable API key (li2_pk_...) | | data-api-url | Custom API endpoint (default: https://api.li2.ai) | | data-debug | Enable debug logging (presence enables, no value needed) | | data-cookie-options | JSON object for cookie customization (see below) | | data-outbound | JSON array of domains for outbound link tracking (e.g., ["partner.com"]) | | data-pageview | "true" to enable automatic pageview tracking | | data-clicks | "true" to enable automatic click tracking (heatmap data) |

Cookie Options

By default, the SDK stores the click ID in a cookie scoped to the current domain with a 30-day expiration. Use data-cookie-options for cross-domain tracking or custom expiration.

<script
  src="https://unpkg.com/@li2/analytics/dist/index.global.js"
  data-publishable-key="li2_pk_..."
  data-cookie-options='{"domain":".example.com","expiresInDays":60}'
></script>

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | domain | string | (current domain) | Cookie domain for cross-subdomain tracking (e.g., .example.com) | | expiresInDays | number | 30 | Days until the cookie expires | | path | string | "/" | Cookie path |

Cross-domain tracking example: If users land on www.example.com but convert on app.example.com, set domain to .example.com to share the click ID across subdomains.

Outbound Link Tracking

Automatically append click IDs to outbound links and iframes pointing to specified domains. This is useful for tracking conversions across multiple domains or passing attribution data to partner sites.

Key Benefits:

  • Reduced bundle size - Only loads when configured (separate module)
  • Automatic tracking - No manual link modification needed
  • Dynamic content support - Tracks links added after page load
  • SPA compatible - Works with client-side routing

Script Tag Usage

Add the data-outbound attribute with a JSON array of domains to track:

<script
  src="https://unpkg.com/@li2/analytics/dist/index.global.js"
  data-publishable-key="li2_pk_..."
  data-outbound='["partner.com", "checkout.example.com"]'
></script>

The SDK will automatically:

  1. Find all <a> and <iframe> elements pointing to the specified domains
  2. Append the click ID as a uid query parameter
  3. Monitor for dynamically added links (SPAs, AJAX content)

Module Import Usage

import { init } from '@li2/analytics'

init({
  publishableKey: 'li2_pk_...',
  outbound: ['partner.com', 'checkout.example.com'],
})

Example

Before tracking:

<a href="https://partner.com/signup">Sign up</a>

After tracking (automatic):

<a href="https://partner.com/signup?uid=abc123xyz">Sign up</a>

The partner site can then read the uid parameter and use it for server-side conversion tracking.

How It Works

  1. Domain matching: Links are tracked if their hostname ends with any configured domain
  2. Normalization: www. prefixes are automatically stripped for matching
  3. Deduplication: Each link is only modified once to avoid duplicate parameters
  4. Periodic scanning: New links are detected every 2 seconds
  5. History API support: Links are re-scanned on navigation in SPAs

Note: The outbound module is loaded dynamically only when the outbound option is configured, keeping your bundle size minimal when not needed.

Pageview Tracking

Automatically track every page visit on your website, including SPA (React, Vue, Angular) navigation. Pageview data powers funnel analytics and drop-off analysis.

Key Benefits:

  • MPA + SPA support - Works with traditional sites and single-page apps
  • Automatic session management - Visitor and session IDs with 30-min timeout
  • Batched delivery - Events buffered and sent every 5s to minimize requests
  • Lazy-loaded - Only loads when enabled, keeping your bundle minimal

Script Tag Usage

Add data-pageview="true" to enable automatic pageview tracking:

<script
  src="https://unpkg.com/@li2/analytics/dist/index.global.js"
  data-publishable-key="li2_pk_..."
  data-pageview="true"
></script>

Configuration Attributes

| Attribute | Default | Description | | --------- | ------- | ----------- | | data-pageview | "false" | Enable pageview tracking | | data-pageview-spa | "auto" | SPA mode: "auto", "manual", or "disabled" | | data-pageview-hash | "false" | Track hash changes as separate pageviews | | data-pageview-exclude | "" | Comma-separated URL patterns to exclude (e.g., "/admin/*,/api/**") | | data-pageview-timeout | "30" | Session timeout in minutes | | data-pageview-batch | "5000" | Batch send interval in milliseconds | | data-pageview-search-params | "q,query,search,s,keyword" | URL params to detect as search queries | | data-pageview-cookie-less | "false" | Use only localStorage (no cookies) |

Programmatic Usage

// Enable pageview tracking programmatically
li2Analytics.enablePageviewTracking({
  spaMode: 'auto',
  excludePatterns: ['/admin/*'],
  sessionTimeout: 30,
});

// Manually track a pageview
li2Analytics.trackPageview({
  pageUrl: 'https://example.com/products',
  pageTitle: 'Products',
});

// Control tracking
li2Analytics.pageview.disable();
li2Analytics.pageview.enable();
li2Analytics.pageview.newSession();

How It Works

  1. Page detection: Intercepts History API (pushState, replaceState) and popstate events for SPA navigation
  2. Session management: Assigns persistent visitor_id (localStorage + cookie) and session_id (sessionStorage) with configurable timeout
  3. Batching: Buffers pageview events and flushes every 5 seconds via fetch, or immediately via sendBeacon on page unload
  4. Click ID linking: Automatically links pageviews to Li2 click IDs for attribution

Click Tracking

Automatically capture every click on your page to power heatmaps and rage click detection in the Li2 dashboard. Uses a single delegated listener and batched delivery — zero impact on page performance.

Key Benefits:

  • Zero-config - One attribute enables it all
  • Automatic deduplication - Rapid repeated clicks are deduplicated (50ms window)
  • Element metadata - Captures tag, text, class, ID, and CSS selector path
  • Rage click detection - Backend automatically detects frustration patterns
  • Lazy-loaded - Module only loads when enabled

Script Tag Usage

Add data-clicks="true" to enable automatic click tracking:

<script
  src="https://unpkg.com/@li2/analytics/dist/index.global.js"
  data-publishable-key="li2_pk_..."
  data-pageview="true"
  data-clicks="true"
></script>

Configuration Attributes

| Attribute | Default | Description | | --------- | ------- | ----------- | | data-clicks | "false" | Enable click tracking | | data-clicks-exclude | "" | CSS selector for elements to exclude (e.g., ".no-track, #sensitive") | | data-clicks-batch | "5000" | Batch send interval in milliseconds |

Note: Click tracking shares session config with pageview tracking. Set data-pageview-timeout, data-pageview-cookieless, etc. once and both modules use the same session.

Programmatic Usage

import { init } from '@li2/analytics'

const sdk = init({ publishableKey: 'li2_pk_...' })

await sdk.enableClickTracking({
  excludeSelector: '.no-track',
  batchInterval: 3000,
})

Event Tracking

Track named custom events (button clicks, form submissions, feature usage) that appear in your Li2 funnel analytics and event rules. Events flow through the same pipeline as pageviews — no extra setup needed.

Key Benefits:

  • Funnel compatible - Events appear as steps in your funnel builder
  • Event rules - Power automated tagging and retroactive classification
  • Auto-init - Starts pageview pipeline automatically if not already running
  • Category support - Group events for easier filtering

Script Tag Usage

<script>
  // Track a button click
  li2Analytics.trackEvent('cta_clicked')

  // Track with a category
  li2Analytics.trackEvent('video_played', { category: 'engagement' })

  // Track form submission
  document.querySelector('#signup-form').addEventListener('submit', () => {
    li2Analytics.trackEvent('form_submitted', { category: 'conversion' })
  })
</script>

Module Import Usage

import { trackEvent } from '@li2/analytics'

// Track a named event
await trackEvent('plan_selected', { category: 'onboarding' })

How It Works

Events are sent through the pageview pipeline with an event_name field set. This means:

  1. They are scoped to the current page URL and session
  2. They appear in funnel builder as matchable steps (type: "event")
  3. They trigger any matching event rules in the Li2 dashboard
  4. They are stored alongside pageview data for unified analysis

Module Import Usage

import { init, trackLead, trackSale } from '@li2/analytics'

// Initialize with your publishable key
init({
  publishableKey: 'li2_pk_...',
  debug: true, // optional: enable console logging
})

// Track a lead conversion
const leadResult = await trackLead({
  eventName: 'signup',
  customerExternalId: 'user_123',
  customerName: 'John Doe',
  customerEmail: '[email protected]',
})

if (leadResult.success) {
  console.log('Lead tracked:', leadResult.customerId)
}

// Track a sale conversion
const saleResult = await trackSale({
  customerExternalId: 'user_123',
  amount: 4999, // Amount in cents ($49.99)
  eventName: 'purchase',
  paymentProcessor: 'stripe',
  invoiceId: 'inv_abc123',
  currency: 'usd',
})

if (saleResult.success) {
  console.log('Sale tracked:', saleResult.saleEventId)
}

Utility Functions

import { isTrackingAvailable, getClickId } from '@li2/analytics'

// Check if a click ID is available for attribution
if (isTrackingAvailable()) {
  console.log('Click ID:', getClickId())
}

// Use getClickId() to pass the click ID to your server for server-side tracking
const clickId = getClickId() // Returns null if no click ID is available

Dashboard Overlays

The SDK includes two dashboard-powered overlays that your team can activate directly from the Li2 dashboard — no additional developer configuration required.

Heatmap Overlay

Visualize where users are clicking on any page. Activated from the Heatmap section of your dashboard via the "View on site" button. When activated, a floating toolbar appears on your page showing:

  • A Gaussian KDE heatmap rendered over your live page
  • Click counts and opacity controls
  • Device type filtering (desktop / tablet / mobile)

The SDK detects the ?li2_heatmap URL parameter and automatically loads the heatmap module. No code changes needed.

Visual Event Tagger

Tag DOM elements as named events directly on your live site — without writing code. Activated from the Event Rules section of your dashboard via the "Tag Events on Site" button.

When active, hovering over any element highlights it. Clicking it opens a panel where you can name the event and save it as an event rule. Tagged events appear immediately in your funnel builder and analytics.

The SDK detects the ?li2_tagger URL parameter and loads the tagger module automatically.

Security note: Both overlays require a time-limited session token generated by the dashboard. Direct URL access without a valid token shows an error.

Server-Side SDK

The server-side SDK is for use in Node.js, Next.js API routes, server actions, and other backend environments. It requires an API key for authentication.

Passing Click ID from Client to Server

Unlike the client-side SDK, the server cannot auto-detect the click ID. You need to capture it on the client and include it in your server requests:

// Client-side: capture the click ID
import { getClickId } from '@li2/analytics'

const clickId = getClickId()

// Include clickId when calling your server
fetch('/api/checkout', {
  method: 'POST',
  body: JSON.stringify({ clickId, ...otherData }),
})

Setup

import { initServer } from '@li2/analytics'

const li2 = initServer({
  apiKey: 'li2_sk_...', // Your secret API key
  debug: true, // optional: enable console logging
})

Track Lead (Server-Side)

// clickId must be captured from the client and passed to your server
const result = await li2.trackLead({
  clickId: 'abc123', // Required for server-side tracking
  eventName: 'signup',
  customerExternalId: 'user_123',
  customerName: 'John Doe',
  customerEmail: '[email protected]',
  metadata: {
    plan: 'pro',
    source: 'landing_page',
  },
})

if (result.success) {
  console.log('Lead tracked:', result.customerId)
}

Track Sale (Server-Side)

// Attributed sale — linked to a tracked visit
const result = await li2.trackSale({
  clickId: 'abc123', // Click ID from the client
  customerExternalId: 'user_123',
  amount: 9900, // Amount in cents ($99.00)
  eventName: 'subscription',
  paymentProcessor: 'stripe',
  invoiceId: 'inv_xyz789',
  currency: 'usd',
  metadata: {
    plan: 'annual',
    coupon: 'SAVE20',
  },
})

if (result.success) {
  console.log('Sale tracked:', result.saleEventId)
}

Direct Sale (No Link Attribution)

For sales that happen without a tracked link (e.g., in-store, phone, manual entry), pass an explicit empty string for clickId:

const result = await li2.trackSale({
  clickId: '', // Empty string = Direct Sale (no link attribution)
  customerExternalId: 'user_123',
  amount: 5000,
  customerEmail: '[email protected]',
  customerName: 'John Doe',
})

Important: clickId must be explicitly provided. Omitting it entirely returns an error. Pass "" for Direct Sale or a valid click ID for attributed sale.

Next.js Example

// app/api/checkout/route.ts
import { initServer } from '@li2/analytics'

const li2 = initServer({ apiKey: process.env.LI2_API_KEY! })

export async function POST(request: Request) {
  const { clickId, userId, amount, invoiceId } = await request.json()

  // Track the sale after successful payment
  // clickId from client, or "" for direct sale
  const result = await li2.trackSale({
    clickId: clickId ?? '',
    customerExternalId: userId,
    amount,
    invoiceId,
    paymentProcessor: 'stripe',
  })

  return Response.json({ success: result.success })
}

API Reference

Client-Side

| Function | Description | | -------- | ----------- | | init(config) | Initialize the SDK with configuration | | trackLead(params) | Track a lead conversion event | | trackSale(params) | Track a sale conversion event | | trackEvent(eventName, options?) | Track a named custom event | | trackPageview(options?) | Manually track a pageview | | identify(params) | Link an anonymous visitor to a known customer | | isTrackingAvailable() | Check if click ID is available | | getClickId() | Get the current click ID | | enablePageviewTracking(config?) | Enable pageview tracking programmatically | | enableClickTracking(options?) | Enable click tracking programmatically | | pageview.disable() | Pause pageview tracking | | pageview.enable() | Resume pageview tracking | | pageview.newSession() | Force a new session |

Server-Side

| Function | Description | | -------- | ----------- | | initServer(config) | Create a server-side SDK instance | | trackLead(params) | Track a lead (clickId required) | | trackSale(params) | Track a sale (clickId required — pass "" for Direct Sale) | | identify(params) | Link anonymous visitor to customer (clickId required) |

TrackLead Parameters

| Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | | clickId | string | Server only | Click ID for attribution | | eventName | string | Yes | Name of the lead event | | customerExternalId | string | No | Your unique customer identifier | | customerName | string | No | Customer's name | | customerEmail | string | No | Customer's email | | customerAvatar | string | No | URL to customer's avatar | | metadata | object | No | Additional data (max 10,000 chars) |

TrackSale Parameters

| Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | | clickId | string | Server only | Click ID for attribution. Pass "" for Direct Sale (no link). | | customerExternalId | string | Yes | Your unique customer identifier | | amount | number | Yes | Amount in smallest currency unit | | eventName | string | No | Name of sale event (default: "Purchase") | | paymentProcessor | string | No | Payment processor (e.g., "stripe") | | invoiceId | string | No | Your invoice/transaction ID | | currency | string | No | Currency code (default: "usd") | | customerName | string | No | Customer's name | | customerEmail | string | No | Customer's email | | metadata | object | No | Additional data (max 10,000 chars) |

TrackEvent Parameters

| Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | | eventName | string | Yes | Name of the event (e.g., "cta_clicked") | | options.category | string | No | Event category for grouping |

EnableClickTracking Options

| Option | Type | Default | Description | | ------ | ---- | ------- | ----------- | | excludeSelector | string | null | CSS selector for elements to exclude | | batchInterval | number | 5000 | Batch flush interval in ms | | sessionTimeout | number | 30 | Session timeout in minutes | | cookieLessMode | boolean | false | Use localStorage only (no cookies) | | cookieDomain | string | — | Cookie domain for cross-subdomain tracking |

License

MIT