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

gtm-core

v1.0.0

Published

TypeScript reactive library for Google Tag Manager with configurable priority system, RxJS, and automatic duplicate prevention in Frontend and SSR environments.

Readme

🎯 GTM Core - v1.0.0 – Priority System Edition

TypeScript reactive library for Google Tag Manager with configurable priority system, RxJS, and automatic duplicate prevention in Frontend and SSR environments.


🚀 What’s New

  • Configurable priorities: 1 = critical, 2 = high, 3+ = low
  • Multiple events per priority: FIFO within each level
  • Immediate processing for priority 1
  • Debounce & batching customizable per event

⚡ Installation

npm install gtm-core

Optional for schema validation with Zod:

npm install zod

📦 File Structure

tu-project/
├── lib/
│   └── gtm.ts            ← Central GTM configuration
├── hooks/
│   └── useGTM.ts         ← Optional custom hook
├── context/
│   └── GTMContext.tsx    ← Optional React context
├── pages/ or src/
│   ├── App.tsx           ← Global initialization
│   ├── HomePage.tsx      ← Example view
│   └── ProductPage.tsx   ← Another example view
└── package.json

1. Basic Configuration

import { PriorityGTMManager, EventPriorityConfig } from 'gtm-core';

interface AppEvents {
  criticalError: { error: string };             // P1 – Critical
  userClick:     { element: string; page: string }; // P2 – Important
  pageView:      { page: string; title: string };   // P3 – General
  scrollDepth:   { page: string; depth: number };   // P3 – General
}

const events: EventPriorityConfig<AppEvents> = {
  criticalError: { priority: 1, debounceMs: 0 },
  userClick:     { priority: 2, debounceMs: 100, maxPerBatch: 5 },
  pageView:      { priority: 3, debounceMs: 300, maxPerBatch: 3 },
  scrollDepth:   { priority: 3, debounceMs: 1000, maxPerBatch: 2 }
};

export const gtm = new PriorityGTMManager<AppEvents>({
  gtm:       { gtmId: 'GTM-XXXXXXX' },           // ← Your GTM ID
  events,
  batcher:   { batchSize: 8, batchIntervalMs: 1500, priorityAware: true },
  reactMode: { enabled: true, globalDebounceMs: 50 }
});

2. Global Initialization

import React, { useEffect } from 'react';
import { gtm } from './lib/gtm';

function App({ Component, pageProps }) {
  useEffect(() => {
    gtm.init().subscribe({
      next: () => console.log('✅ GTM initialized'),
      error: (e) => console.error('❌ GTM init error:', e)
    });
  }, []);

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

export default App;

3. Sending Events with pushSync

3.1 Page View

useEffect(() => {
  gtm.pushSync({ page: '/home', title: 'Home' }, 'pageView');
}, []);

3.2 User Click

<button onClick={() =>
  gtm.pushSync({ element: 'cta', page: '/home' }, 'userClick')
}>
  Click me
</button>

3.3 Critical Error

try {
  await processPayment();
} catch (error) {
  gtm.pushSync({ error: error.message }, 'criticalError');
}

4. Debounce & Batching

  • P1 (priority: 1): debounceMs: 0 → immediate
  • P2 (priority: 2): debounceMs: 100 ms → short burst grouping
  • P3 (priority: 3): debounceMs: 300 ms → longer grouping

Batcher groups up to batchSize events or every batchIntervalMs, respecting priorities if priorityAware: true.


5. SSR Support (Next.js)

import Document, { Html, Head, Main, NextScript } from 'next/document';
import { gtm } from '../lib/gtm';

class MyDocument extends Document {
  render() {
    const script = gtm.renderSSRScriptSync();
    return (
      <Html>
        <Head>{script && <div dangerouslySetInnerHTML={{ __html: script }} />}</Head>
        <body><Main /><NextScript/></body>
      </Html>
    );
  }
}

export default MyDocument;

6. Hooks & Context (Optional)

Custom Hook

import { useCallback } from 'react';
import { gtm } from '../lib/gtm';

export function useGTM() {
  const push = useCallback((data, type) => gtm.pushSync(data, type), []);
  const trackPage = useCallback((page, title) => push({ page, title }, 'pageView'), [push]);
  const trackClick = useCallback((el, pg) => push({ element: el, page: pg }, 'userClick'), [push]);
  return { push, trackPage, trackClick };
}

React Context

import React, { createContext, useContext } from 'react';
import { gtm } from '../lib/gtm';

const GTMContext = createContext(gtm);
export const GTMProvider = ({ children }) => (
  <GTMContext.Provider value={gtm}>{children}</GTMContext.Provider>
);
export const useGTM = () => useContext(GTMContext);

Wrap your app in GTMProvider if using.


7. Debug & Metrics

// Discarded events
gtm.buffer.getDiscardedEvents().subscribe(({ reason, event }) => {
  console.warn('Discarded:', reason, event);
});

// Processed batches
gtm.batcher.getBatchEvents().subscribe(be => {
  console.log(`Batch ${be.reason} (P=${be.avgPriority?.toFixed(1)}):`, be.batch);
});

8. Summary of Steps

  1. Install: npm install gtm-core
  2. Configure: Define your AppEvents and EventPriorityConfig
  3. Initialize: Call gtm.init() in your root component
  4. Send: Use gtm.pushSync(data, 'eventType') in each view
  5. Adjust: Tune debounceMs, maxPerBatch, batcher, reactMode

GTM Core - v1.0.0 handles your critical, important, and general events automatically, both on client and SSR. 🎉