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

@colada_app/web-sdk

v0.3.0

Published

Colada attribution SDK for the browser

Readme

@colada_app/web-sdk

Attribution for the browser. Resolves which ad campaign brought a visitor to your site, and reports conversions back so the ad platforms can optimise on them.

Under 7KB gzipped, no dependencies.

Install

npm install @colada_app/web-sdk

Or a script tag, no build step:

<script src="https://cdn.jsdelivr.net/npm/@colada_app/[email protected]/dist/colada.min.js"></script>

Pin the version, as above. A branded cdn.coladaapp.io/web-sdk/v0.3.0/colada.min.js will replace this once its DNS is in place; until then that host does not resolve.

Use

import { colada } from "@colada_app/web-sdk";

await colada.init({ publicTenantKey: "pk_live_…" });

// On every page load, not just after login — see below.
if (user) colada.identify(user.id);

colada.track("Purchase", { amount: 249, currency: "SAR", orderId: order.id });

Four methods is the whole integration. init() handles the rest.

Routing on the campaign

const attr = colada.getAttribution();
if (attr?.matched && attr.customParams.attributionStoreId) {
  router.push(`/store/${attr.customParams.attributionStoreId}`);
}

getAttribution() is synchronous and returns a frozen snapshot, so it is safe to call from a render. It returns null until the attribution resolves — which is not the same as "no campaign". An unattributed visitor comes back as a snapshot with matched: false.

Don't block your render on init(). Use the callback:

const off = colada.onAttribution((attr) => { /* re-render */ });

identify() — the most important call you make

Device storage cannot cross a browser boundary. A visitor who taps your ad inside Instagram is in Instagram's own storage jar; the same person in Safari an hour later is, to any SDK, a different device. No API bridges them, on any platform.

identify() is what does. We resolve the campaign by your user id, so once you tell us who someone is, their attribution follows them across browsers, in-app WebViews, new devices, and Safari clearing local storage.

It is also required for events: track() without it is dropped, because an event with no user cannot be attributed to anyone.

Call it once — and clear it on logout

The user id is persisted, so a page load does not detach events from the person. Call identify() after login or sign-up; later pages restore it automatically.

await colada.init({ publicTenantKey: "pk_live_…" });
colada.identify(user.id);        // after login or sign-up

This makes clearUser() mandatory on logout. A persisted id on a shared browser means one person logs out, the next browses, and their purchase is attributed to the first — silent misattribution that nothing downstream can detect.

colada.clearUser();              // every logout path

Wire it into every path that ends a session, not just the logout button — token expiry and server-side session invalidation are the ones people miss. clearUser() flushes anything the outgoing user has queued before dropping the identity, so their pending events cannot go out under whoever logs in next. Your deviceId is untouched: it identifies the browser, not the person.

If you would rather the SDK never held an identity across page loads, call clearUser() on unload and identify() on every page — the behaviour is then equivalent to not persisting.

Pair it with a Login event

identify() sends nothing by itself. If you call it after a login, follow it with the event:

colada.identify(user.id);
colada.track("Login");

Our API binds the attribution to a user on Login and CompleteRegistration. Without one of those, binding waits for whatever event happens next.

It is not authentication

identify() takes your own opaque user identifier. It does not log anyone in, and you should not pass an email, a phone number, or a session token.

Events

Download · AddToCart · PlaceAnOrder · CompleteRegistration · Search · Purchase · Subscribe · InitiateCheckout · ViewContent · Login · ViewCheckout · ViewSubscription

Anything else is rejected. Pass metadata.amount as a number on revenue events — a purchase without one still counts as a conversion but contributes nothing to revenue, and the SDK warns when that happens.

Retries are safe. Every event carries a stable id, purchases are keyed on your orderId, and events that fail while offline are queued and replayed when the network returns.

track() needs identify() first — an event with no user cannot be attributed to anyone, so it is dropped with a console warning rather than sent. Nothing is queued for later, because holding it would attribute this visitor's activity to whoever logs in next. Since the identity is restored on page load, this normally only affects a visitor who has never identified at all.

The returned deliveryStatus reports what our API did with the event, not confirmation that an ad platform accepted it. Treat ok: true as "we received and recorded it".

Options

| Option | Default | | |---|---|---| | publicTenantKey | — | required. Safe in browser source | | apiBase | Colada's API | you almost certainly do not need this. Local dev, staging, or a first-party proxy on your own domain. Must be https unless localhost — init() refuses anything else rather than failing quietly | | cookieDomain | off | set to ".yoursite.com" to share one visitor across subdomains | | stripParam | false | remove colada_cid from the visible URL after capture | | debug | false | log every decision; also throws on an unknown event name | | timeoutMs | 10000 | per-request timeout |

What it collects

A random id we generate and store on your origin, the operating system, and the campaign parameters on the landing URL. No fingerprinting — no canvas, fonts, or hardware probing. No reading of your page content, forms, or cookies. The visitor's IP is seen by our API the same way it sees any request; the SDK never reads or sends it.

colada.debug() returns everything the SDK currently knows, which answers most integration questions on its own.

Support

Nothing here throws in production. A failed call returns a result you can inspect rather than breaking your page.