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

@analytics-debugger/data-layer-helper-ts

v0.0.2

Published

TypeScript port of google/data-layer-helper — monitors and processes dataLayer arrays

Downloads

249

Readme

@analytics-debugger/data-layer-helper-ts

TypeScript port of google/data-layer-helper by David Vallejo — provides the ability to process messages passed onto a dataLayer queue.

Build and Test

This project uses vite-plus for building, testing, and type-checking.

npm install        # Install dependencies
vp build && npx dts-bundle-generator -o dist/index.d.ts src/index.ts  # Build all formats + types
vp build --watch   # Watch mode
vp test            # Run tests
vp check           # Type-check

Build Formats

| Format | File | Usage | | ------ | -------------------------------- | --------------------------- | | ESM | dist/index.js | import in modern bundlers | | CJS | dist/index.cjs | require() in Node.js | | IIFE | dist/data-layer-helper.iife.js | <script> tag in browsers |

Quick Start

npm install @analytics-debugger/data-layer-helper-ts

ES Module / CommonJS

import DataLayerHelper from "@analytics-debugger/data-layer-helper-ts";

const dataLayer = [];
const helper = new DataLayerHelper(dataLayer, {
  listener: function (model, message) {
    // Message has been pushed.
    console.log(model, message);
  },
});

CDN (jsDelivr)

<!-- Latest version -->
<script src="https://cdn.jsdelivr.net/npm/@analytics-debugger/data-layer-helper-ts/dist/data-layer-helper.iife.js"></script>

<!-- Pinned version -->
<script src="https://cdn.jsdelivr.net/npm/@analytics-debugger/[email protected]/dist/data-layer-helper.iife.js"></script>

<!-- ESM import -->
<script type="module">
  import DataLayerHelper from "https://cdn.jsdelivr.net/npm/@analytics-debugger/data-layer-helper-ts/dist/index.js";
</script>

IIFE (Browser)

<script src="https://cdn.jsdelivr.net/npm/@analytics-debugger/data-layer-helper-ts/dist/data-layer-helper.iife.js"></script>
<script>
  var dataLayer = [];
  var helper = new DataLayerHelper(dataLayer, {
    listener: function (model, message) {
      console.log(message);
    },
  });
</script>

What is a Data Layer Queue?

A data layer queue is simply a JavaScript array that lives on a webpage.

<script>
  dataLayer = [];
</script>

Page authors can append messages onto the queue in order to emit information about the page and its state.

<script>
  dataLayer.push({
    title: "Migratory patterns of ducks",
    category: "Science",
    author: "Bradley Wogulis",
  });
</script>

These messages are JavaScript objects containing a hierarchy of key/value pairs. They can be metadata about the page content, information about the visitor, or data about events happening on the page. This system allows tools like analytics libraries and tag management systems to access this data in a standard way.

The Abstract Data Model

When a DataLayerHelper is created, it maintains an internal "abstract data model". Each message pushed onto the dataLayer is merged into this model. You can retrieve values from the model using dot-notation:

dataLayer.push({ one: { two: { three: 4 } } });

helper.get("one.two.three"); // Returns 4
helper.get("one.two"); // Returns {three: 4}

As each message is processed, its key/value pairs are added to the abstract data model. If the key doesn't currently exist in the model, the pair is simply added. In the case of key conflicts, the action taken depends on the types of the existing and new values:

  • Arrays and Plain Objects — recursively merge when both values are the same type
  • Everything else — the new value overwrites the existing value

| Existing Value | New Value | Action | | --------------------- | ------------ | ----------------- | | Array | Array | Recursively merge | | Plain Object | Plain Object | Recursively merge | | Any other combination | Overwrite |

Overwriting Existing Values

When overwriting, the existing value is completely discarded:

// model: { a: [1, 2, 3] }
dataLayer.push({ a: "hello" });
// model: { a: 'hello' }

Recursively Merging Values

When recursively merging, each property in the new value is individually merged into the existing value:

// model: { one: 1, three: 3 }
dataLayer.push({ two: 2 });
// model: { one: 1, three: 3, two: 2 }

// model: { one: { two: 3 } }
dataLayer.push({ one: { four: 5 } });
// model: { one: { two: 3, four: 5 } }

Preventing Default Recursive Merge

To prevent the default recursive merge and overwrite instead, add a truthy _clear attribute to the pushed message. The _clear key itself is removed from the model after processing.

// model: { user: { name: 'Alice', role: 'admin' } }
dataLayer.push({ user: { name: "Bob" }, _clear: true });
// model: { user: { name: 'Bob' } }  — role is gone

This is especially useful for single page applications where you may not want outdated information in the data model when routing between pages.

Custom Functions

Pushing a function onto the dataLayer allows you to update the abstract data model with custom code. When a function is processed, the value of this will be the abstract data model interface.

Note: Arrow functions do not have their own this, so you must use a regular function.

dataLayer.push(function () {
  var name = this.get("user.name");
  this.set("greeting", "Hello, " + name);
});

The Abstract Data Model Interface

To safely access the abstract data model from within a custom function, an API with a getter and setter is provided:

  • this.get(key) — returns a value from the model using dot-notation
  • this.set(key, value) — creates or overwrites the given key with the new value

Listening for Messages

When creating a DataLayerHelper, you can specify a listener callback to be called whenever a message is pushed onto the dataLayer. This allows your code to be notified immediately whenever the dataLayer has been updated.

function listener(model, message) {
  // Message has been pushed.
  // The helper has merged it onto the model.
  // Now use the message and the updated model to do something.
}
var helper = new DataLayerHelper(dataLayer, { listener: listener });

Listening to the Past

By default (processNow: true), the helper processes all existing messages in the dataLayer on construction. The listener will be called once for each existing message, with the model representing the state at the time of that message.

To defer this processing:

var helper = new DataLayerHelper(dataLayer, {
  listener: listener,
  processNow: false,
});
// ... later
helper.process();

Registering Processors

You can register custom command processors that respond to command arrays:

helper.registerProcessor("event", function (name, params) {
  console.log("Event:", name, params);
});

dataLayer.push(["event", "click", { category: "nav" }]);
// Logs: Event: click {category: 'nav'}

Multiple processors can be registered for the same command name.

Delaying Processing

Use processNow: false to create the helper without processing existing messages. Call helper.process() later when you're ready.

API Summary

new DataLayerHelper(dataLayer, options?)

| Option | Type | Default | Description | | --------------- | ---------- | ------------- | ---------------------------------------------------------------- | | listener | function | — | Called on every push: (model, message, dataLayerName) => void | | processNow | boolean | true | Process existing entries on construction | | dataLayerName | string | 'dataLayer' | Optional identifier passed to the listener as the third argument |

helper.get(key)

Returns a value from the internal model using dot-notation.

helper.flatten()

Returns the entire dataLayer history merged into a single object (re-merges from scratch, does not use the internal model).

helper.process()

Manually processes all existing entries in the dataLayer.

helper.registerProcessor(commandName, processor)

Registers a command processor for the given command name.

Author

David Vallejo / Analytics Debugger S.L.U.

License

Apache-2.0