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.1.7

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"].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
  li2Analytics.trackSale({
    customerExternalId: 'user_123',
    amount: 4999, // $49.99 in cents
    eventName: 'purchase',
    invoiceId: 'inv_abc123',
  })
</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) |

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.

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

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)

const result = await li2.trackSale({
  clickId: 'abc123', // Required for server-side tracking
  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)
}

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
  const result = await li2.trackSale({
    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 | | isTrackingAvailable()| Check if click ID is available | | getClickId() | Get the current click ID |

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) |

TrackLead Parameters

| Parameter | Type | Required | Description | | -------------------- | -------- | -------- | ------------------------------------- | | clickId | string | Server only | Click ID for attribution | | eventName | string | Yes | Name of the lead event | | customerExternalId | string | Yes | 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 | | 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) |

License

MIT