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

@tavojs/analytics

v1.0.0

Published

Google Analytics and Google Tag Manager integration for Tavo.js apps.

Readme

@tavojs/analytics

Google Analytics and Google Tag Manager support for Tavo.js apps.

This is one package with two installation modes. Choose direct Google Analytics for a small, code-owned analytics setup. Choose Google Tag Manager when tags and triggers should be managed in GTM; configure the GA4 tag in the GTM container instead of also enabling direct GA.

The package also supports Google's Advanced and Basic Consent Mode loading models. immediate is the backward-compatible default and loads Google with the configured consent defaults. after-consent emits only an inert local runtime until the application records an analytics grant and calls loadAnalytics. manual loads only after an explicit call.

Install

npm install @tavojs/analytics

Direct Google Analytics

import { createAnalyticsPlugin } from "@tavojs/analytics";
import { defineConfig } from "@tavojs/core/config";

export default defineConfig({
  plugins: [
    createAnalyticsPlugin({
      googleAnalytics: { measurementId: "G-XXXXXXXXXX" }
    })
  ]
});

Google Tag Manager

import { createAnalyticsPlugin } from "@tavojs/analytics";
import { defineConfig } from "@tavojs/core/config";

export default defineConfig({
  plugins: [
    createAnalyticsPlugin({
      googleTagManager: { containerId: "GTM-XXXXXXX" }
    })
  ]
});

Track Events

import { track, trackPageView } from "@tavojs/analytics/client";

track("sign_up", { method: "email" });
trackPageView({ page_path: "/pricing" });

Client helpers are SSR-safe and return false when the browser snippet is not available. GTM mode pushes named objects to the selected data layer; direct GA mode queues gtag commands.

Consent

Queue consent defaults before Google scripts load, then update them from the consent UI:

createAnalyticsPlugin({
  consent: {
    default: {
      ad_personalization: "denied",
      ad_storage: "denied",
      ad_user_data: "denied",
      analytics_storage: "denied"
    },
    urlPassthrough: true
  },
  googleAnalytics: {
    measurementId: "G-XXXXXXXXXX"
  }
});
import { updateConsent } from "@tavojs/analytics/client";

updateConsent({ analytics_storage: "granted" });

Your application remains responsible for collecting valid consent and choosing defaults appropriate to its policy and jurisdictions.

Strict prior-consent loading

Use after-consent when no Google request or application analytics event may occur before an explicit analytics grant:

createAnalyticsPlugin({
  loading: {
    strategy: "after-consent",
    preConsentEvents: "drop"
  },
  consent: {
    default: {
      ad_personalization: "denied",
      ad_storage: "denied",
      ad_user_data: "denied",
      analytics_storage: "denied"
    }
  },
  googleTagManager: {
    containerId: "GTM-XXXXXXX",
    initialData: { app_name: "my-app" }
  }
});

Apply the saved or newly selected preference in browser code:

import {
  disableAnalytics,
  loadAnalytics,
  trackPageView,
  updateConsent
} from "@tavojs/analytics/client";

if (preferences.analytics) {
  updateConsent({ analytics_storage: "granted" });
  const result = await loadAnalytics();
  if (result.status === "loaded") {
    // This is an intentional post-consent view, not replayed history.
    trackPageView();
  }
} else {
  updateConsent({ analytics_storage: "denied" });
  disableAnalytics();
}

Before a grant, track, trackPageView, and pushToDataLayer return false and do not buffer application events. Concurrent load calls share one request. A failed load remains failed until loadAnalytics({ retry: true }) is called.

disableAnalytics() immediately blocks new application events and queues denied Google consent values. It cannot undo data already transmitted or unload executed third-party code. Reload the page after withdrawal when strict process isolation is required; cookie removal remains the consent-management layer's responsibility.

Lifecycle state is available through getAnalyticsState() and subscribeAnalyticsState(listener).

Page Views

The package does not patch browser history. In direct GA mode, GA4 Enhanced Measurement can observe history changes. In GTM mode, use a History Change trigger or call trackPageView from app navigation code. Do not enable two approaches for the same navigation.

With deferred loading, the plugin deliberately does not replay the page viewed before consent. If the current page should count after a first successful load, send it explicitly as shown above.

Current Tavo.js Limitation

Tavo.js Plugin API v1 exposes keyed document-head contributions but not a body-start contribution. The plugin installs the functional GTM JavaScript snippet in the head, but cannot place GTM's optional <noscript> iframe immediately after the opening <body> tag. Visitors with JavaScript disabled therefore are not measured.

The inline bootstrap is declared as unsafe head HTML. The plugin manifest declares the required unsafeHeadHtml permission with an inspection-visible reason, and installing this trusted plugin enables it. Tavo.js rejects the contribution if that manifest permission is missing.

More Documentation

  • docs/framework-usage.md
  • docs/google-analytics.md
  • docs/google-tag-manager.md
  • docs/testing-and-publishing.md

Project Policies