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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@jeroen.bakker/just-attribute

v0.4.5

Published

Realtime privacy-conscious marketing attribution for the web

Downloads

1,396

Readme

just-attribute

This is not the greatest script in the world, no. This is just-attribute.

This package is intended to help websites track realtime (marketing) attribution in a privacy-conscious way. It does so by not storing anything about the user or the pages they visit, only URL parameters and optionally referrers are taken into account and logged.

Unlike tools such as Google Analytics where it might take over a day for attribution data to be available, you can use the data this package gathers immediately, inside the browser or anywhere else.

This is not meant to be a full replacement of an analytics tool, which usually measures things such as sessions, landing pages, interactions, revenue and more.
This just attributes, and it is small enough (around 1kb gzipped) that it can be used alongside such tools if you want to.

Installation

This package is on npm:

npm install @jeroen.bakker/just-attribute

Usage

In its most basic form logging interactions (pageviews) is as simple as:

import { InteractionLogger } from '@jeroen.bakker/just-attribute';

const logger = new InteractionLogger();
logger.pageview();

This will build an Interaction out of the current pageview, taking into account URL parameters and optionally the referrer. If the interaction is deemed to have changed attribution it will be logged.

If you want to disable the automatic processing of the referrer you can set detectReferrals to false in the options parameter of the InteractionLogger constructor, or disable it after construction since all settings are exposed on the instance.

// Disable detectReferrals through the constructor
const logger = new InteractionLogger({detectReferrals: false});
// or at any other time
logger.settings.detectReferrals = false;

When it is time to finalize the list of interactions (i.e. when a user "converts"), run the log of interactions through one of the included attribution models and clear the log.

import { InteractionLogger, firstInteraction } from '@jeroen.bakker/just-attribute';

const logger = new InteractionLogger();

// Do whatever you want with the attribution, such as sync it to your server
// it might also be a good idea to sync the logs themselves to learn from them or to debug attribution
const attribution = firstInteraction(logger.interactionLog());

// Clear the log so you don't endlessly collect interactions that have already been attributed
logger.clearLog();

The simplest attribution model is the last-interaction model, which is essentially the same as accessing the latest interaction at any time.

const logger = new InteractionLogger();
console.log(logger.lastInteraction());
// e.g. {source: 'foo', medium: 'bar', timestamp: 1689880963075}

Attribution models

Attribution is modeled from the log of interactions by an attribution model implementation.
This package comes with implementations for several common attribution models.

Single interaction models:

Multi-interaction models:

Additionally, you can easily implement your own models.

Single interaction models will simply return the attributed interaction.
Multi-interaction models return a list of weighted interactions, where the weights are a ratio that add up to 1 that you can apply to something like an order value.

A simple function is provided to distribute a value over a list of weighted interactions.

Attributing traffic

Maybe your use case doesn't have a real "conversion" and there is no clear point at which you want to determine attribution.
Perhaps you just want to know where the people who visit your site come from.

Since just-attribute doesn't track users or sessions like an analytics tool, it can't really give you statistics on these things.
But it can still be used to get a sense of where people come from, and how often your site is visited.

You can use the onAttributionChange() method to register a callback that will be triggered any time attribution changes.
This would occur whenever someone first visit, the first time after a session has expired, or whenever there are new UTM parameters or there is a new referrer.

Essentially this triggers whenever someone goes to your site, and as such it can be used to attribute new traffic.

const logger = new InteractionLogger();

logger.onAttributionChange((interaction) => {
    // Store information about the interaction on a server or in some analytics tool
    // where this data can be aggregated and visualized
    fetch('/attribute-traffic', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(interaction),
    });
});

// Only after registering this callback should you process the pageview
logger.pageview();

Middleware

You can enrich interactions or exclude them by registering interaction middlewares.

A middleware in this context is anything that satisfies the InteractionMiddleware interface.
Meaning it accepts an interaction and the same URL and referrer that were used to determine its values, and returns a new interaction, that could have any of its properties changed or have new ones added.

Unlike some implementations of middleware, it is not responsible for calling the next one in line.
They are simply executed by the logger itself after the initial interaction has been determined in the order they were registered.

Once all middlewares are done it is determined whether attribution has changed, and if so the interaction is logged.

A few middlewares have been provided:

  • Google Ads
    This sets a source / medium of google / cpc for any URL containing a gclid parameter.
    Additionally, the parameter is logged as an important parameter, meaning attribution will change if it has a different value in a new interaction.
  • Facebook Ads
    Similar to the above middleware, it sets a source / medium of facebook / cpc for any URL containing a fbclid parameter.
  • ref transformer
    If a URL conains a ref parameter this will set its value as the source and sets the medium to referral.

Please see the source of these middlewares for further details on their behavior.

Mapping referrals from search engines and social networks

Two middlewares have been provided to automatically turn referrals from well-known search engines or social networks into organic search or organic social traffic, respectively.

For example:

import { InteractionLogger, ReferralMapper } from '@jeroen.bakker/just-attribute';

const logger = new InteractionLogger();

// By not passing in a list of search engines or social networks we use the default lists
logger.registerInteractionMiddleware(ReferralMapper.newSearchEngineMiddleware());
logger.registerInteractionMiddleware(ReferralMapper.newSocialNetworkMiddleware());

// Usually you would just call logger.pageview()
// but calling processInteraction() directly makes it easier to demonstrate the transformation
logger.processInteraction({source: 'www.google.com', medium: 'referral'});
logger.lastInteraction(); // Returns {source: 'Google', medium: 'organic'}

logger.processInteraction({source: 'www.reddit.com', medium: 'referral'});
logger.lastInteraction(); // Returns {source: 'reddit', medium: 'social'}

This is done by comparing referring domains to a small list of large search engines and social networks.
These lists have been manually compiled by using the searchengine-and-social-list from Matomo as a starting point.

The compiled lists have been kept intentionally small so that they don't add too much overhead if you decide to bundle them with the logger.
But if you want to save even more on data or need to include a larger list you could also run the middlewares on the interaction log, server-side.

If you notice any obvious services missing from these lists feel free to open an issue or pull request.
Additionally, you can pass in your own list if you need more niche or regional services to be recognised.

Asynchronous attribution

This package is split into two main components:

  • Interaction logging: logging pageviews that lead to a change in attribution.
  • Attribution modeling: using the logged pageviews to determine the final attribution.

The attribution modeling does not need to happen in the browser.
As long as the logged interactions are synchronized somewhere, the attribution models can be applied whenever you want.

If you have the necessary pageview data you could reconstruct the interaction log and apply the attribution models to old data.

Or you could apply multiple attribution models to compare the outcomes.

Acknowledgements

This is purely intended to be used on the web, mobile apps have not been taken into account.
There is currently no planned support for tracking redeemed discount codes or other promotions which could be used to attribute orders.

Planned:

  • Add out of the box implementation for running attribution models in BigQuery using javascript UDFs
  • Describe how to contribute
  • Add a code style linter/fixer to make contributing easier
  • Set up GitHub action to publish to npm
  • Figure out browser support (should be pretty good if you don't need to support IE or Opera mini)

Undecided:

  • Whether to log the page URL as part of the interaction, this would allow you to get information about landing pages and how they perform.
    This is not intended as a full analytics tool, but this would take almost no effort to add and could provide a lot of value.
    This can always be implemented as a middleware, but if it adds enough value it might make more sense to just enable it out of the box.