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

@reestify/affiliate

v0.1.3

Published

JavaScript SDK for affiliate tracking and attribution

Readme

@affiliate/sdk

JavaScript SDK for affiliate tracking and attribution. This SDK enables seamless integration of affiliate tracking into any website or web application.

Features

  • 🔗 Automatic referral link detection from URL parameters
  • 🍪 Cookie-based tracking with localStorage fallback
  • 📊 Custom event tracking
  • 🔄 Automatic retry with exponential backoff
  • 🌐 Framework-agnostic (works with React, Vue, Next.js, vanilla JS)
  • 📦 Tiny bundle size (~3KB gzipped)
  • 🔒 TypeScript support with full type definitions

Installation

# Using npm
npm install @affiliate/sdk

# Using yarn
yarn add @affiliate/sdk

# Using bun
bun add @affiliate/sdk

# Using pnpm
pnpm add @affiliate/sdk

Quick Start

import { AffiliateTracker } from '@affiliate/sdk'

// Create tracker instance
const tracker = new AffiliateTracker({
  apiUrl: 'https://api.yoursite.com',
})

// Initialize tracking (call once on page load)
tracker.init()

That's it! The SDK will automatically:

  1. Detect referral parameters in the URL (?ref=abc123)
  2. Store tracking data in a cookie
  3. Send a click event to your tracking server

Configuration Options

const tracker = new AffiliateTracker({
  // Required
  apiUrl: 'https://api.example.com', // Your API server URL

  // Optional
  cookieDomain: '.example.com',    // Cookie domain (default: current domain)
  cookieExpiration: 30,            // Cookie expiration in days (default: 30)
  debug: false,                    // Enable debug logging (default: false)
  referralParams: ['ref', 'aff'],  // URL params to detect (default: ['ref', 'aff', 'affiliate', 'via'])
  
  // Retry configuration
  retry: {
    maxAttempts: 3,                // Max retry attempts (default: 3)
    initialDelay: 1000,            // Initial delay in ms (default: 1000)
    maxDelay: 30000,               // Max delay in ms (default: 30000)
    backoffMultiplier: 2,          // Backoff multiplier (default: 2)
  },
})

API Reference

new AffiliateTracker(config)

Creates a new tracker instance.

Parameters:

  • config.apiUrl (required): Your API server URL
  • config.cookieDomain (optional): Cookie domain for cross-subdomain tracking
  • config.cookieExpiration (optional): Cookie expiration in days (default: 30)
  • config.debug (optional): Enable debug logging (default: false)
  • config.referralParams (optional): Array of URL parameter names to detect
  • config.retry (optional): Retry configuration for failed requests

tracker.init()

Initializes the tracker. Call this once when your page loads.

  • Detects referral parameters in the current URL
  • Sets tracking cookie if referral is detected
  • Sends click event to the tracking server
tracker.init()

tracker.getReferralData()

Returns the current referral data if available.

Returns: ReferralData | null

const referral = tracker.getReferralData()
if (referral) {
  console.log('Referred by:', referral.affiliateId)
  console.log('Campaign:', referral.campaign)
}

ReferralData structure:

interface ReferralData {
  affiliateId: string    // Affiliate identifier
  linkCode?: string      // Referral link code
  campaign?: string      // Campaign name
  utmSource?: string     // UTM source
  utmMedium?: string     // UTM medium
  utmCampaign?: string   // UTM campaign
  timestamp: number      // When referral was recorded
  expiresAt: number      // Expiration timestamp
}

tracker.hasReferral()

Checks if there is an active (non-expired) referral.

Returns: boolean

if (tracker.hasReferral()) {
  // Show affiliate-specific content
}

tracker.trackEvent(eventType, metadata?)

Tracks a custom event.

Parameters:

  • eventType (required): Event type identifier (e.g., 'signup', 'purchase')
  • metadata (optional): Additional event data

Returns: Promise<TrackEventResponse>

// Track a signup event
await tracker.trackEvent('signup', {
  plan: 'pro',
  value: 99,
})

// Track a purchase event
await tracker.trackEvent('purchase', {
  orderId: 'order_123',
  amount: 149.99,
  currency: 'USD',
})

tracker.clear()

Clears all tracking data (cookie and localStorage).

tracker.clear()

tracker.isInitialized()

Checks if the tracker has been initialized.

Returns: boolean

URL Parameters

The SDK automatically detects these URL parameters:

| Parameter | Description | |-----------|-------------| | ref | Referral code | | aff | Affiliate code | | affiliate | Affiliate identifier | | via | Referral source | | affiliate_id | Affiliate ID | | aid | Affiliate ID (short) | | campaign | Campaign name | | utm_source | UTM source | | utm_medium | UTM medium | | utm_campaign | UTM campaign |

Example URLs:

https://yoursite.com/?ref=abc123
https://yoursite.com/?aff=partner1&campaign=summer-sale
https://yoursite.com/?ref=xyz&utm_source=twitter&utm_medium=social

Framework Examples

Vanilla JavaScript

<script type="module">
  import { AffiliateTracker } from '@affiliate/sdk'

  const tracker = new AffiliateTracker({
    apiUrl: 'https://api.example.com',
  })

  tracker.init()

  // Track events on button clicks
  document.getElementById('signup-btn').addEventListener('click', () => {
    tracker.trackEvent('signup_click')
  })
</script>

React

import { useEffect } from 'react'
import { AffiliateTracker } from '@affiliate/sdk'

// Create tracker instance outside component
const tracker = new AffiliateTracker({
  apiUrl: process.env.REACT_APP_API_URL!,
})

function App() {
  useEffect(() => {
    tracker.init()
  }, [])

  const handleSignup = async () => {
    await tracker.trackEvent('signup', { plan: 'pro' })
    // Continue with signup logic
  }

  return (
    <button onClick={handleSignup}>
      Sign Up
    </button>
  )
}

React with Custom Hook

import { useEffect, useState, useCallback } from 'react'
import { AffiliateTracker, ReferralData } from '@affiliate/sdk'

const tracker = new AffiliateTracker({
  apiUrl: process.env.REACT_APP_API_URL!,
})

export function useAffiliateTracker() {
  const [referralData, setReferralData] = useState<ReferralData | null>(null)
  const [isInitialized, setIsInitialized] = useState(false)

  useEffect(() => {
    tracker.init()
    setReferralData(tracker.getReferralData())
    setIsInitialized(true)
  }, [])

  const trackEvent = useCallback(
    async (eventType: string, metadata?: Record<string, unknown>) => {
      return tracker.trackEvent(eventType, metadata)
    },
    []
  )

  return {
    referralData,
    isInitialized,
    hasReferral: tracker.hasReferral(),
    trackEvent,
  }
}

// Usage in component
function SignupPage() {
  const { referralData, trackEvent } = useAffiliateTracker()

  const handleSignup = async () => {
    await trackEvent('signup', { referredBy: referralData?.affiliateId })
  }

  return (
    <div>
      {referralData && <p>Referred by: {referralData.affiliateId}</p>}
      <button onClick={handleSignup}>Sign Up</button>
    </div>
  )
}

Next.js (App Router)

// app/providers.tsx
'use client'

import { useEffect } from 'react'
import { AffiliateTracker } from '@affiliate/sdk'

const tracker = new AffiliateTracker({
  apiUrl: process.env.NEXT_PUBLIC_API_URL!,
})

export function AffiliateProvider({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    tracker.init()
  }, [])

  return <>{children}</>
}

// app/layout.tsx
import { AffiliateProvider } from './providers'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <AffiliateProvider>{children}</AffiliateProvider>
      </body>
    </html>
  )
}

Next.js (Pages Router)

// pages/_app.tsx
import { useEffect } from 'react'
import type { AppProps } from 'next/app'
import { AffiliateTracker } from '@affiliate/sdk'

const tracker = new AffiliateTracker({
  apiUrl: process.env.NEXT_PUBLIC_API_URL!,
})

export default function App({ Component, pageProps }: AppProps) {
  useEffect(() => {
    tracker.init()
  }, [])

  return <Component {...pageProps} />
}

Vue 3

<!-- App.vue -->
<script setup lang="ts">
import { onMounted } from 'vue'
import { AffiliateTracker } from '@affiliate/sdk'

const tracker = new AffiliateTracker({
  apiUrl: import.meta.env.VITE_API_URL,
})

onMounted(() => {
  tracker.init()
})

const handleSignup = async () => {
  await tracker.trackEvent('signup')
}
</script>

<template>
  <button @click="handleSignup">Sign Up</button>
</template>

Vue 3 Composable

// composables/useAffiliateTracker.ts
import { ref, onMounted } from 'vue'
import { AffiliateTracker, ReferralData } from '@affiliate/sdk'

const tracker = new AffiliateTracker({
  apiUrl: import.meta.env.VITE_API_URL,
})

export function useAffiliateTracker() {
  const referralData = ref<ReferralData | null>(null)
  const isInitialized = ref(false)

  onMounted(() => {
    tracker.init()
    referralData.value = tracker.getReferralData()
    isInitialized.value = true
  })

  const trackEvent = async (
    eventType: string,
    metadata?: Record<string, unknown>
  ) => {
    return tracker.trackEvent(eventType, metadata)
  }

  return {
    referralData,
    isInitialized,
    hasReferral: () => tracker.hasReferral(),
    trackEvent,
  }
}

Troubleshooting

Cookies not being set

  1. Check domain configuration: If tracking across subdomains, set cookieDomain to .yourdomain.com
  2. HTTPS required: Secure cookies require HTTPS in production
  3. Third-party cookie blocking: The SDK falls back to localStorage if cookies are blocked

Referral not detected

  1. Check URL parameters: Ensure the URL contains one of the supported parameters
  2. Custom parameters: If using custom parameter names, configure referralParams
  3. Debug mode: Enable debug: true to see console logs
const tracker = new AffiliateTracker({
  apiUrl: 'https://api.example.com',
  debug: true, // Enable debug logging
})

API requests failing

  1. Check CORS: Ensure your API server allows requests from your domain
  2. Network issues: The SDK automatically retries failed requests
  3. Check API URL: Verify the apiUrl is correct and accessible

TypeScript errors

Ensure you have the correct TypeScript version (5.0+) and the types are properly resolved:

{
  "compilerOptions": {
    "moduleResolution": "bundler"
  }
}

Browser Support

  • Chrome 80+
  • Firefox 75+
  • Safari 13+
  • Edge 80+

The SDK uses modern JavaScript features but is compiled to ES2020 for broad compatibility.

Privacy Considerations

  • IP addresses are hashed before storage
  • Cookies are first-party only
  • No personal data is collected without explicit tracking calls
  • Respects browser cookie preferences

License

MIT