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 🙏

© 2025 – Pkg Stats / Ryan Hefner

getu-attribution-v2-sdk

v0.2.1

Published

GetuAI Attribution V2 SDK for client-side tracking

Readme

GetuAI Attribution SDK

A JavaScript SDK for tracking user attribution and conversion events in web applications.

Table of Contents


Features

| Feature | Description | | ------------------------- | ---------------------------------------------------------------- | | 🎯 UTM Tracking | Automatic capture and storage of UTM parameters from URLs | | 🔗 Cross-Domain UTM | Automatic UTM parameter passing to external links | | 📦 Event Batching | Efficient batch processing of events with configurable intervals | | 📴 Offline Support | Queue events locally when offline, sync when connection restores | | 🔄 SPA Support | Automatic page view tracking for Single Page Applications | | ⚡ Immediate Events | Critical events (purchase, login, signup) sent immediately | | 🕐 Session Management | Tracks user sessions with configurable timeout | | 🧹 Auto Clean UTM | Removes UTM parameters from URL after capture | | 📄 Page View Debounce | Prevents duplicate page view events within configurable interval | | 📝 TypeScript | Full TypeScript support with type definitions |


Installation

Via CDN (Recommended)

<script
  src="https://unpkg.com/getu-attribution-v2-sdk/dist/getuai-attribution.min.js"
  data-api-key="your_api_key_here"
></script>

Via NPM

npm install getu-attribution-v2-sdk

Quick Start

Automatic Initialization (CDN)

The SDK auto-initializes when loaded with a data-api-key attribute:

<script
  src="https://unpkg.com/getu-attribution-v2-sdk/dist/getuai-attribution.min.js"
  data-api-key="your_api_key_here"
  data-auto-track-page-view="true"
  data-debug="true"
></script>

Manual Initialization (NPM)

import { init, trackPageView, EventType } from "getu-attribution-v2-sdk";

// Initialize SDK
await init({
  apiKey: "your_api_key_here",
  autoTrackPageView: true,
  enableDebug: true,
});

// Track custom event
await trackPageView({ category: "homepage" });

Configuration

Script Tag Attributes

| Attribute | Type | Default | Description | | --------------------------- | ------- | --------------------------------------------- | --------------------------------------------- | | data-api-key | string | required | Your GetuAI API key | | data-api-endpoint | string | https://attribution.getu.ai/attribution/api | API endpoint URL | | data-debug | boolean | false | Enable debug logging | | data-auto-track | boolean | false | Enable auto-tracking (forms, links) | | data-auto-track-page-view | boolean | false | Enable auto page view tracking (includes SPA) | | data-batch-size | number | 100 | Number of events per batch | | data-batch-interval | number | 2000 | Batch interval in milliseconds | | data-auto-clean-utm | boolean | true | Remove UTM params from URL after capture |

Configuration Object

interface SDKConfig {
  // Required
  apiKey: string;

  // API Settings
  apiEndpoint?: string; // Default: "https://attribution.getu.ai/attribution/api"

  // Batch Settings
  batchSize?: number; // Default: 100
  batchInterval?: number; // Default: 2000 (ms)
  maxRetries?: number; // Default: 3
  retryDelay?: number; // Default: 1000 (ms)

  // Auto-Tracking
  autoTrack?: boolean; // Default: false - Enable form/link tracking
  autoTrackPageView?: boolean; // Default: false - Enable page view + SPA tracking

  // Session
  sessionTimeout?: number; // Default: 1800000 (30 minutes in ms)

  // Cross-Domain UTM
  enableCrossDomainUTM?: boolean; // Default: true
  crossDomainUTMParams?: string[]; // Default: ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"]
  excludeDomains?: string[]; // Default: [] - Domains to exclude from UTM passing

  // URL Management
  autoCleanUTM?: boolean; // Default: true - Remove UTM from URL after capture

  // Page View
  pageViewDebounceInterval?: number; // Default: 5000 (ms) - Debounce interval for same page

  // Debug
  enableDebug?: boolean; // Default: false
}

Full Configuration Example

await init({
  apiKey: "your_api_key_here",
  apiEndpoint: "https://your-api.com/attribution/api",
  batchSize: 50,
  batchInterval: 3000,
  maxRetries: 5,
  retryDelay: 2000,
  autoTrack: true,
  autoTrackPageView: true,
  sessionTimeout: 60 * 60 * 1000, // 1 hour
  enableCrossDomainUTM: true,
  crossDomainUTMParams: ["utm_source", "utm_medium", "utm_campaign"],
  excludeDomains: ["google.com", "facebook.com"],
  autoCleanUTM: true,
  pageViewDebounceInterval: 3000,
  enableDebug: true,
});

Event Tracking

Event Types

enum EventType {
  // Pre-conversion signals
  PAGE_VIEW = "page_view",
  PAGE_CLICK = "page_click",
  VIDEO_PLAY = "video_play",

  // Registration funnel
  FORM_SUBMIT = "form_submit",
  EMAIL_VERIFICATION = "email_verification",

  // Login flow
  LOGIN = "login",

  // Signup flow
  SIGNUP = "signup",

  // Purchase funnel
  PRODUCT_VIEW = "product_view",
  ADD_TO_CART = "add_to_cart",
  PURCHASE = "purchase",
}

Immediate Events

These events are sent immediately (not batched):

  • PURCHASE
  • LOGIN
  • SIGNUP
  • FORM_SUBMIT
  • EMAIL_VERIFICATION

Track Page View

// Basic
await trackPageView();

// With custom data
await trackPageView({
  category: "product",
  section: "electronics",
});

// With user ID
await trackPageView({ category: "dashboard" }, "user_123");

Track Page Click

// Basic
await trackPageClick();

// With click context
await trackPageClick("user_123", {
  element_id: "btn_signup",
  element_type: "button",
  element_text: "Sign Up",
  position: { x: 120, y: 360 },
});

Track Purchase

await trackPurchase(
  "user_123", // tracking_user_id
  99.99, // revenue
  Currency.USD, // currency (optional, default: USD)
  {
    // purchaseData (optional)
    product_id: "prod_123",
    product_name: "Premium Plan",
    quantity: 1,
  }
);

Track Login

await trackLogin("user_123", {
  method: "email",
  provider: "google",
});

Track Signup

await trackSignup("user_123", {
  method: "email",
  referral_code: "REF123",
});

Track Form Submit

await trackFormSubmit("user_123", {
  form_id: "contact_form",
  form_type: "contact",
});

Track Video Play

// Basic
await trackVideoPlay();

// With user ID
await trackVideoPlay("user_123");

// With custom data
await trackVideoPlay("user_123", {
  video_id: "video_123",
  video_title: "Introduction Video",
  duration: 120,
  position: 30,
});

Track Email Verification

await trackEmailVerification("user_123", {
  email: "[email protected]",
  verification_method: "email_link",
});

Track Product View

// Basic
await trackProductView();

// With user ID
await trackProductView("user_123");

// With product data
await trackProductView("user_123", {
  product_id: "prod_123",
  product_name: "Widget",
  category: "electronics",
  price: 29.99,
});

Track Add to Cart

// Basic
await trackAddToCart();

// With user ID
await trackAddToCart("user_123");

// With cart data
await trackAddToCart("user_123", {
  product_id: "prod_123",
  product_name: "Widget",
  quantity: 2,
  price: 29.99,
});

Track Custom Event

await trackEvent(
  EventType.ADD_TO_CART,
  {
    product_id: "prod_123",
    product_name: "Widget",
    price: 29.99,
    quantity: 2,
  },
  "user_123", // tracking_user_id (optional)
  29.99, // revenue (optional)
  Currency.USD // currency (optional)
);

Auto-Tracking

General Auto-Tracking (autoTrack)

When autoTrack: true, the SDK automatically tracks:

Form Submissions

  • Captures all form field values (with password masking)
  • Includes form metadata (id, action, method)
  • Handles checkboxes, radio buttons, multi-select, file inputs

External Link Clicks

  • Adds UTM parameters to external links
  • Respects excludeDomains configuration

Page View Auto-Tracking (autoTrackPageView)

When autoTrackPageView: true, the SDK:

  1. Initial Page View: Tracks page view on SDK initialization
  2. SPA Route Changes: Automatically tracks navigation via:
    • history.pushState()
    • history.replaceState()
    • Browser back/forward (popstate)
  3. Debouncing: Prevents duplicate tracking within pageViewDebounceInterval

SPA Support

Single Page Application support is automatically enabled when autoTrackPageView: true.

How It Works

User visits /home
  └── SDK tracks PAGE_VIEW for /home

User clicks link to /products
  └── React Router calls history.pushState()
  └── SDK detects route change
  └── SDK tracks PAGE_VIEW for /products (after 100ms delay for title update)

User clicks browser back button
  └── Browser fires popstate event
  └── SDK detects route change
  └── SDK tracks PAGE_VIEW for /home

Route Change Detection

The SDK intercepts:

  • history.pushState() - Standard navigation
  • history.replaceState() - URL replacement
  • popstate event - Browser back/forward

Path Comparison

Only tracks when pathname + search actually changes:

// These are considered different paths:
"/products"
"/products?category=electronics"
"/products/123"

// These are considered the same (no duplicate tracking):
"/products" -> "/products"

Cross-Domain UTM

Automatic UTM Passing

When users click external links, UTM parameters are automatically appended:

User visits your site with ?utm_source=google&utm_medium=cpc
  └── UTM params stored in localStorage

User clicks link to https://partner-site.com/page
  └── SDK modifies link to:
      https://partner-site.com/page?utm_source=google&utm_medium=cpc

Configuration

await init({
  apiKey: "your_api_key",
  enableCrossDomainUTM: true, // Default: true
  crossDomainUTMParams: [
    // Which params to pass
    "utm_source",
    "utm_medium",
    "utm_campaign",
  ],
  excludeDomains: [
    // Don't pass UTM to these domains
    "google.com",
    "facebook.com",
    "twitter.com",
  ],
});

Manual UTM Enhancement

// Add UTM to any URL
const enhancedURL = addUTMToURL("https://example.com/page");
// Result: "https://example.com/page?utm_source=google&utm_medium=cpc"

// Get current UTM parameters
const utmParams = getCurrentUTMParams();
// Result: { utm_source: "google", utm_medium: "cpc", utm_campaign: "summer" }

Attribution Data

Data Structure

interface AttributionData {
  firstTouch: UTMData; // First attribution touchpoint
  lastTouch: UTMData; // Most recent touchpoint
  touchpoints: UTMData[]; // All touchpoints history
  expiresAt: number; // Expiration timestamp
}

interface UTMData {
  utm_source?: string;
  utm_medium?: string;
  utm_campaign?: string;
  utm_term?: string;
  utm_content?: string;
  timestamp: number;
}

Accessing Attribution Data

const attribution = getAttributionData();

if (attribution) {
  console.log("First Touch:", attribution.firstTouch);
  console.log("Last Touch:", attribution.lastTouch);
  console.log("All Touchpoints:", attribution.touchpoints);
}

Touchpoint Recording

A new touchpoint is recorded when:

  • utm_source changes, OR
  • utm_campaign changes

Storage

LocalStorage

| Key | Content | Retention | | ---------------------- | -------------------- | ------------- | | attribution_utm_data | UTM attribution data | 30 days | | attribution_session | Session information | Session-based |

IndexedDB

| Store | Content | Retention | | -------- | ----------- | --------------------- | | events | Event queue | 7 days (auto cleanup) |

Automatic Cleanup

  • UTM Data: Expired data removed on next access
  • Events: Old events (>7 days) cleaned up periodically
  • Quota Exceeded: Oldest 20% of data removed automatically

Offline Support

How It Works

User goes offline
  └── Events queued in IndexedDB

User tracks events
  └── Events stored locally

User goes online
  └── SDK detects connection restore
  └── Queued events sent to server

Page unload
  └── SDK attempts to flush pending events

Retry Strategy

  • Failed requests retry with exponential backoff
  • Default: 3 retries with 1s base delay
  • Delay: baseDelay * 2^attemptNumber

API Reference

Core Functions

init(config: SDKConfig): Promise<AttributionSDK>

Initialize the SDK with configuration.

const sdk = await init({ apiKey: "your_key" });

getSDK(): AttributionSDK | null

Get the current SDK instance.

const sdk = getSDK();
if (sdk) {
  // SDK is initialized
}

waitForSDK(): Promise<AttributionSDK>

Wait for SDK initialization (useful with auto-init).

const sdk = await waitForSDK();

Event Functions

trackEvent(eventType, eventData?, tracking_user_id?, revenue?, currency?): Promise<void>

Track a custom event.

trackPageView(pageData?, tracking_user_id?): Promise<void>

Track a page view event.

trackPurchase(tracking_user_id, revenue, currency?, purchaseData?): Promise<void>

Track a purchase event (sent immediately).

trackLogin(tracking_user_id, loginData?): Promise<void>

Track a login event (sent immediately).

trackSignup(tracking_user_id, signupData?): Promise<void>

Track a signup event (sent immediately).

trackFormSubmit(tracking_user_id?, formData?): Promise<void>

Track a form submission event (sent immediately).

trackVideoPlay(tracking_user_id?, videoData?): Promise<void>

Track a video play event.

await trackVideoPlay("user_123", {
  video_id: "video_123",
  video_title: "Introduction Video",
  duration: 120,
});

trackEmailVerification(tracking_user_id, verificationData?): Promise<void>

Track an email verification event (sent immediately).

await trackEmailVerification("user_123", {
  email: "[email protected]",
  verification_method: "email_link",
});

trackProductView(tracking_user_id?, productData?): Promise<void>

Track a product view event.

await trackProductView("user_123", {
  product_id: "prod_123",
  product_name: "Widget",
  category: "electronics",
});

trackAddToCart(tracking_user_id?, cartData?): Promise<void>

Track an add to cart event.

await trackAddToCart("user_123", {
  product_id: "prod_123",
  product_name: "Widget",
  quantity: 2,
  price: 29.99,
});

Attribution Functions

getAttributionData(): AttributionData | null

Get current attribution data.

addUTMToURL(url: string): string

Add current UTM parameters to a URL.

getCurrentUTMParams(): Record<string, string>

Get current UTM parameters as object.

Utility Functions

flush(): Promise<void>

Flush all pending events to the server.

getStatus(): SDKStatus | null

Get SDK status including initialization state, session info, queue size, and SPA tracking status.

const status = getStatus();
// {
//   initialized: true,
//   session: { sessionId: "...", startTime: ..., lastActivity: ..., pageViews: 0 },
//   queueSize: 5,
//   online: true,
//   crossDomainUTM: {
//     enabled: true,
//     currentParams: { utm_source: "google" }
//   },
//   spaTracking: {
//     enabled: true,
//     currentPath: "/products"
//   }
// }

destroy(): void

Destroy SDK instance and clean up resources.


Usage Patterns

Global Window Object (CDN)

// Access via window.getuaiSDK namespace
await window.getuaiSDK.init({ apiKey: "your_key" });
await window.getuaiSDK.trackPageView();
await window.getuaiSDK.trackPurchase("user_123", 99.99);

// Access enums
const eventType = window.getuaiSDK.EventType.PURCHASE;
const currency = window.getuaiSDK.Currency.USD;

Static Methods (Advanced)

import { AttributionSDK, EventType } from "getu-attribution-v2-sdk";

// Use static methods
await AttributionSDK.init({ apiKey: "your_key" });
await AttributionSDK.trackEvent(EventType.PAGE_VIEW);
await AttributionSDK.trackPurchase("user_123", 99.99);

const attribution = AttributionSDK.getAttributionData();
const status = AttributionSDK.getStatus();

Custom Instance

import { AttributionSDK } from "getu-attribution-v2-sdk";

const sdk = new AttributionSDK({
  apiKey: "your_key",
  enableDebug: true,
});

await sdk.init();
await sdk.trackPageView();

Event Listeners

// Listen for SDK ready
window.addEventListener("getuaiSDKReady", (event) => {
  console.log("SDK initialized:", event.detail.sdk);
});

// Listen for SDK errors
window.addEventListener("getuaiSDKError", (event) => {
  console.error("SDK error:", event.detail.error);
});

TypeScript Support

import {
  init,
  trackEvent,
  EventType,
  Currency,
  type SDKConfig,
  type EventData,
  type AttributionData,
} from "getu-attribution-v2-sdk";

const config: SDKConfig = {
  apiKey: "your_api_key_here",
  enableDebug: true,
  autoTrackPageView: true,
};

await init(config);

// Type-safe event tracking
await trackEvent(
  EventType.PURCHASE,
  { product_id: "123" },
  "user_123",
  99.99,
  Currency.USD
);

// Type-safe attribution data
const attribution: AttributionData | null = getAttributionData();

Browser Support

| Browser | Minimum Version | | ------- | --------------- | | Chrome | 50+ | | Firefox | 50+ | | Safari | 10+ | | Edge | 79+ |

Required APIs

  • localStorage
  • IndexedDB
  • history.pushState/replaceState
  • fetch
  • Promise

Debug Mode

Enable debug logging to see detailed SDK activity:

<!-- Via script tag -->
<script src="..." data-api-key="your_key" data-debug="true"></script>
// Via config
await init({
  apiKey: "your_key",
  enableDebug: true,
});

Console Output Examples

[GetuAI Info] 🚀 GetuAI Attribution SDK initialized successfully
[GetuAI Info] 📄 Auto track page view enabled (including SPA route tracking)
[GetuAI Debug] 🔄 [SPA] Route change detected (pushState): /home -> /products
[GetuAI Debug] ✅ [SPA] Page view tracked for: /products
[GetuAI Info] UTM data extracted and stored successfully

Error Handling

try {
  await trackPurchase("user_123", 99.99, Currency.USD, {
    product_id: "prod_123",
  });
} catch (error) {
  console.error("Failed to track purchase:", error);
  // Event will be queued for retry automatically
}

Events that fail to send are:

  1. Stored in IndexedDB
  2. Retried with exponential backoff
  3. Sent when connection restores

License

MIT