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

@affiliateo/web

v4.2.0

Published

Affiliateo web SDK — affiliate attribution and tracking for web apps

Downloads

1,861

Readme

@affiliateo/web

Affiliateo web SDK. track affiliate visits and pass attribution metadata to your Stripe checkout.

Install

npm install @affiliateo/web

Setup

  1. Connect your Stripe account on the Affiliateo dashboard
  2. Wrap your app in <AffiliateoProvider> with your campaign ID
  3. At checkout time, call getAttribution() and pass the result to Stripe metadata

Step 1. wrap your app

// app/layout.tsx (Next.js App Router) or _app.tsx (Pages Router)
import { AffiliateoProvider } from '@affiliateo/web';

export default function RootLayout({ children }) {
  return (
    <AffiliateoProvider campaignId="YOUR_CAMPAIGN_ID">
      {children}
    </AffiliateoProvider>
  );
}

The provider:

  • Reads ?ref= from the URL when a visitor arrives
  • Stores attribution in localStorage so it survives navigation
  • Sends pageview events to Affiliateo for click tracking

Step 2. in your checkout button (client-side)

'use client'
import { getAttribution } from '@affiliateo/web';

async function handleCheckout() {
  const attribution = getAttribution();

  const res = await fetch('/api/checkout', {
    method: 'POST',
    body: JSON.stringify({ attribution }),
  });

  const { url } = await res.json();
  window.location.href = url;
}

getAttribution() reads affiliateo_ref, affiliateo_visitor_id, and affiliateo_campaign_id from localStorage and returns them as an object, ready to pass to Stripe.

Step 3. in your checkout API route (server-side)

// app/api/checkout/route.ts
export async function POST(req) {
  const { attribution } = await req.json();

  const session = await stripe.checkout.sessions.create({
    line_items: [{ price: 'price_xxx', quantity: 1 }],
    mode: 'payment',
    success_url: 'https://yoursite.com/success',
    cancel_url: 'https://yoursite.com/cancel',
    metadata: attribution,
  });

  return Response.json({ url: session.url });
}

That's it. Affiliateo's webhook will automatically read the metadata and credit the right affiliate when the payment succeeds.

How it works

  1. Visitor clicks affiliate link → yoursite.com?ref=pinkproton
  2. <AffiliateoProvider> reads ?ref=pinkproton from the URL and saves it in localStorage
  3. As the visitor browses, attribution stays in their browser
  4. At checkout, getAttribution() reads localStorage and returns the attribution object
  5. Your server passes it as Stripe metadata when creating the checkout session
  6. When Stripe fires the checkout.session.completed webhook, Affiliateo reads the metadata and credits the affiliate

Why localStorage and not cookies?

  • Not blocked by Safari ITP or most privacy tools
  • No CSRF concerns

GDPR / ePrivacy. merchant responsibility

The SDK writes persistent identifiers (affiliateo_visitor_id, affiliateo_ref, affiliateo_campaign_id) to the visitor's localStorage and sends pageview events that include the visitor's IP, user agent, and approximate geolocation to Affiliateo's servers. Under EU ePrivacy (Article 5(3)) and GDPR, persistent identifiers stored on a visitor's device require prior consent the same way cookies do.

If you serve visitors in the EU/EEA, UK, or any jurisdiction with equivalent rules, you are responsible for obtaining consent before this script loads, the same way you would for Google Analytics, Meta Pixel, or any other analytics tool. Typical approaches:

  • Gate the <AffiliateoProvider> (or the <script src="…/t.js"> tag) behind your cookie banner's "accept" callback so it only loads after consent.
  • Document Affiliateo in your privacy policy as a processor (see our Data Processing Agreement) and list the categories of data collected.

Affiliateo acts as your data processor for visitor analytics. You are the controller and decide the lawful basis for processing your visitors' data.

Alternative: vanilla HTML (no React)

If you're not using React, use the tracking script directly instead of the provider:

<script defer
  data-campaign="YOUR_CAMPAIGN_ID"
  src="https://affiliateo.com/t.js"
></script>

Then in your checkout flow (vanilla JS):

const attribution = {
  affiliateo_ref: localStorage.getItem('affiliateo_ref'),
  affiliateo_visitor_id: localStorage.getItem('affiliateo_visitor_id'),
  affiliateo_campaign_id: localStorage.getItem('affiliateo_campaign_id'),
};

// Send to your server with the rest of your checkout payload
fetch('/api/checkout', {
  method: 'POST',
  body: JSON.stringify({ attribution }),
});

Track conversion goals

Pageviews auto-track. For specific moments that matter to your funnel (signup_completed, trial_started, initiate_checkout, etc.), use track() or HTML data attributes.

From React

'use client'
import { useEffect } from 'react'
import { useAffiliateRef } from '@affiliateo/web'

export default function SignupSuccess() {
  const { track } = useAffiliateRef()
  useEffect(() => {
    track('signup_completed', { plan: 'free' })
  }, [])
  return <div>Welcome!</div>
}

HTML data attributes (zero JS, works everywhere)

<button data-affiliateo-goal="initiate_checkout"
        data-affiliateo-goal-price="49"
        data-affiliateo-goal-plan="pro">
  Subscribe
</button>

The SDK auto-fires the goal on click. Optional data-affiliateo-goal-* attributes become metadata (kebab-case → snake_case, up to 10 params).

Scroll-depth tracking

<section data-affiliateo-scroll="pricing_viewed">
  ...your pricing content...
</section>

Fires the first time any pixel of the section overlaps the viewport. Maximum permissiveness — if the user scrolled enough to see even a sliver, it counts. Earlier versions required 50% visibility, which was unreachable for tall sections (a pricing page with comparison tables silently dropped out of every funnel). Great for landing pages where you want to know which sections convert.

Goal naming rules

Lowercase letters, digits, underscores, hyphens, colons. Max 64 chars. Metadata bounded to 4KB JSON.

Identify signed-in users (cross-device stitching)

Without identify(), the same person browsing on phone and buying on laptop counts as two visitors. Call it once after sign-in:

'use client'
import { useEffect } from 'react'
import { useAffiliateRef } from '@affiliateo/web'
import { useUser } from './your-auth'

export default function AuthBoundary({ children }) {
  const { identify } = useAffiliateRef()
  const user = useUser()
  useEffect(() => {
    if (user) identify(user.id)
  }, [user])
  return <>{children}</>
}

Idempotent. safe to fire on every page load while a user is signed in. user_id only. The SDK does not accept, collect, or transmit email or any other PII.

API

<AffiliateoProvider campaignId="..." apiUrl?="...">

React provider. Wrap your app once. Reads ?ref= from URL, persists to localStorage, sends pageview events, sets up data-attribute + scroll listeners.

Props:

  • campaignId (required): your Affiliateo campaign ID
  • apiUrl (optional): defaults to https://affiliateo.com

useAffiliateRef()

React hook that returns { refCode, visitorId, track, identify }.

  • track(eventName, metadata?). fire a custom goal
  • identify(userId). link this visitor to a merchant user_id (no PII)

getAttribution()

Client-side function. Returns an object with affiliateo_ref, affiliateo_visitor_id, and affiliateo_campaign_id from localStorage. Pass directly as Stripe metadata.

Framework support

Works with any JavaScript framework or vanilla JS:

  • Next.js (App Router & Pages Router)
  • Remix / React Router
  • Vite + React
  • Vanilla JS/HTML (use the <script> tag instead)