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

deferlytics

v0.2.0

Published

Performance-first delayed analytics bootstrapper for GA4 and Yandex Metrica

Readme

Deferlytics

English | Русский

Performance-first delayed analytics bootstrapper for GA4 and Yandex Metrica.

Deferlytics starts with a tiny browser bootstrap, buffers explicit analytics events, delays heavy vendor scripts, then replays queued events through native vendor APIs after consent, bot checks and the selected load strategy allow loading.

It does not emulate GA4 or Yandex Metrica internals. Native vendor automatic tracking starts only after vendors load. Events before that moment are captured only if they are explicitly sent through Deferlytics.

Why

Analytics scripts are useful, but they are often loaded in the critical path. That can compete with rendering, hydration, user interaction and Core Web Vitals.

Deferlytics keeps the early page path small:

tiny bootstrap
  -> event queue
  -> delayed loader
  -> vendor loading
  -> vendor init
  -> native replay
  -> live dispatch

The bootstrap captures only explicit calls such as page() and track(). GA4 and Yandex Metrica are loaded later, outside the critical path.

Install

npm install deferlytics

Browser Usage

Put the bootstrap as early as possible in <head>, configure analytics, then load the runtime later.

<script src="/node_modules/deferlytics/dist/bootstrap.iife.js"></script>
<script>
  fastAnalytics.init({
    loadStrategy: "idle",
    skipBots: true,
    skipLighthouse: true,
    consent: {
      required: false,
      defaultStatus: "granted"
    },
    vendors: {
      ga4: {
        enabled: true,
        measurementIds: ["G-XXXXXXX", "G-YYYYYYY"],
        sendPageView: false
      },
      yandexMetrica: {
        enabled: true,
        counterIds: [12345678, 87654321],
        webvisor: false,
        clickmap: true,
        trackLinks: true,
        accurateTrackBounce: true,
        defer: true
      }
    }
  });

  fastAnalytics.page();
  fastAnalytics.track("hero_cta_click", { placement: "hero" });
</script>
<script defer src="/node_modules/deferlytics/dist/loader.iife.js"></script>

Before loader.iife.js runs, calls are written to window.__fastAnalyticsQueue. After vendors are ready, queued events are replayed once and future calls are dispatched live.

ESM Usage

import { init, page, track } from "deferlytics";

init({
  loadStrategy: "idle",
  vendors: {
    ga4: {
      enabled: true,
      measurementIds: ["G-XXXXXXX", "G-YYYYYYY"],
    },
  },
});

page();
track("signup_click", { plan: "pro" });

The ESM entrypoint is browser-safe on import. Runtime work starts when API methods are called.

API

fastAnalytics.init(config);
fastAnalytics.page(params);
fastAnalytics.track(eventName, params);
fastAnalytics.identify(userId, traits);
fastAnalytics.consent(status);
fastAnalytics.flush();
fastAnalytics.loadVendors();

The same methods are exported from the ESM entrypoint:

import {
  init,
  page,
  track,
  identify,
  consent,
  flush,
  loadVendors,
} from "deferlytics";

Config

fastAnalytics.init({
  debug: false,
  loadStrategy: "idle",
  loadTimeout: 3000,
  skipBots: true,
  skipLighthouse: true,
  maxQueueSize: 100,
  consent: {
    required: false,
    defaultStatus: "granted"
  },
  vendors: {
    ga4: {
      enabled: true,
      measurementIds: ["G-XXXXXXX", "G-YYYYYYY"],
      sendPageView: false
    },
    yandexMetrica: {
      enabled: true,
      counterIds: [12345678, 87654321],
      webvisor: false,
      clickmap: true,
      trackLinks: true,
      accurateTrackBounce: true,
      defer: true
    }
  }
});

Load Strategies

  • immediate: load vendors as soon as runtime initializes.
  • load: load after the window.load event.
  • idle: load during requestIdleCallback, with a timeout fallback.
  • interaction: load after the first user interaction.
  • timeout: load after loadTimeout.
  • manual: load only when loadVendors() is called.

Manual loading:

fastAnalytics.init({
  loadStrategy: "manual",
  vendors: {
    ga4: { enabled: true, measurementId: "G-XXXXXXX" }
  }
});

fastAnalytics.track("early_event");
fastAnalytics.loadVendors();

Consent

fastAnalytics.init({
  consent: {
    required: true,
    defaultStatus: "pending"
  },
  vendors: {
    ga4: { enabled: true, measurementId: "G-XXXXXXX" }
  }
});

fastAnalytics.track("lead_form_open");

// Call this after the user grants analytics consent.
fastAnalytics.consent("granted");

When consent is denied or required and still pending, vendor scripts are not loaded. The queue can continue accepting explicit events. If consent is granted before the loader starts, that early consent event is used as the initial runtime consent state.

Bot and Lighthouse Skip

By default, Deferlytics skips vendor loading for common bots, Lighthouse, PageSpeed, headless and webdriver-like environments:

fastAnalytics.init({
  skipBots: true,
  skipLighthouse: true
});

measurementId and counterId are still supported for single-counter setups. Use measurementIds and counterIds when a site sends events to multiple GA4 streams or Yandex Metrica counters.

When analytics are skipped, the queue can still accept events, but GA4 and Yandex Metrica scripts are not loaded.

Vendor Mapping

GA4:

  • page() -> gtag("event", "page_view", ...) after all configured measurement IDs are initialized.
  • track(name, params) -> gtag("event", name, params) after all configured measurement IDs are initialized.
  • identify(userId, traits) -> gtag("set", "user_id", userId)

Yandex Metrica:

  • page() -> ym(counterId, "hit", url, ...) for every configured counter.
  • track(name, params) -> ym(counterId, "reachGoal", name, params) for every configured counter.
  • identify(userId, traits) -> ym(counterId, "userParams", traits) for every configured counter.

If a vendor script is already present on the page, Deferlytics reuses it instead of adding a duplicate script tag.

Vanilla Examples

See examples/vanilla.

Available scenarios:

Next.js Example

See examples/nextjs/README.md.

For SPA navigation, call page() on route changes. Deferlytics does not infer framework route transitions automatically.

Performance Recommendations

  • Put bootstrap.iife.js early, but keep the inline config small.
  • Use idle, interaction, timeout or manual instead of immediate for production pages.
  • Keep sendPageView: false for GA4 and call page() explicitly.
  • Track only business-critical early events before vendors load.
  • Avoid adding heavy custom plugins to the bootstrap layer.
  • Keep consent checks outside the critical rendering path when possible.

Limitations

  • Deferlytics buffers explicit events, not every native vendor automatic event.
  • Vendor automatic tracking starts only when the vendor script loads.
  • SPA route changes should call page() manually.
  • Scroll, click, visibility and performance plugins are not included in the MVP runtime yet.
  • Deferlytics is a routing and replay layer, not a replacement analytics backend.

Development

npm install
npm run typecheck
npm run test
npm run build
npm pack --dry-run

The package publishes only:

dist/
examples/
README.md
README_RU.md
LICENSE
package.json