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

kenzi-web-marketing-analytics

v1.0.0

Published

Lightweight web marketing analytics wrapper for Angular, React, and TypeScript browser apps

Downloads

37

Readme

kenzi-web-marketing-analytics

Lightweight marketing analytics for Angular, React, and TypeScript browser apps.

Developed by Kenzi.ai.

kenzi-web-marketing-analytics exposes one TypeScript API and routes events to supported web marketing providers:

  • Google Analytics 4 through gtag
  • Google Ads conversion tracking through gtag
  • Meta Pixel through fbq
  • Custom HTTP endpoint tracking

This package is web/browser only. It is not a Capacitor plugin, mobile SDK, native Firebase SDK wrapper, Meta native SDK wrapper, or iOS/Android package. It can be imported safely in SSR builds because browser-only work is guarded until runtime initialization.

Compatibility

  • Angular standalone apps
  • Angular SSR-safe apps
  • React apps
  • React SSR frameworks when initialized only in the browser
  • Regular TypeScript browser apps
  • Future Vue wrappers
  • Modern browsers with ES2020 support

The runtime has no Angular or React dependency and guards all browser globals, so importing it during SSR does not access window, document, or localStorage.

Provider scripts are injected by default in the browser:

  • Google: injects https://www.googletagmanager.com/gtag/js?id=<measurementId>
  • Meta: injects https://connect.facebook.net/en_US/fbevents.js

Set autoInjectScript: false per provider only when the host app already loads that provider script through Google Tag Manager, a consent manager, or manually managed tags.

Install

npm install kenzi-web-marketing-analytics

Local package inside this repo:

npm install ./packages/kenzi-web-marketing-analytics

Usage

import {
  KenziWebMarketingAnalytics,
  KENZI_MARKETING_EVENTS,
} from 'kenzi-web-marketing-analytics';

await KenziWebMarketingAnalytics.initialize({
  debug: false, // Enables console diagnostics when true; keep false in production unless troubleshooting.

  google: {
    enabled: true, // Enables Google Analytics 4 and Google Ads dispatch.

    measurementId: 'G-XXXXXXX', // GA4 web stream measurement ID from Google Analytics Admin > Data streams > Web.

    adsConversionId: 'AW-XXXXXXX', // Google Ads conversion ID from Google Ads > Goals > Conversions; used to initialize Ads gtag config.

    autoInjectScript: true, // Default true; injects gtag.js automatically. Set false only if GTM/consent tooling already loads it.

    conversions: {
      lead: 'AW-XXXXXXX/LEAD_LABEL', // Google Ads conversion send_to value from the Lead conversion action tag snippet.
      purchase: 'AW-XXXXXXX/PURCHASE_LABEL', // Google Ads conversion send_to value from the Purchase conversion action tag snippet.
      complete_registration: 'AW-XXXXXXX/SIGNUP_LABEL', // Google Ads conversion send_to value from the Signup conversion action tag snippet.
    },

    enhancedEcommerce: true, // Keeps GA4 ecommerce params such as items/value/currency for enhanced ecommerce reporting.
  },

  meta: {
    enabled: true, // Enables Meta Pixel dispatch.

    pixelId: '123456789', // Pixel ID from Meta Events Manager > Data sources > Pixel settings.

    autoInjectScript: true, // Default true; injects fbevents.js automatically. Set false only if the app already loads Meta Pixel.

    autoPageView: true, // Sends Meta Pixel PageView on initialization. Keep false if you only want manual/router page views.
  },

  campaignTracking: {
    enabled: true, // Captures UTM params and ad click IDs from the landing URL.

    storageKey: 'kenzi_campaign', // localStorage key used to persist campaign attribution.

    expirationDays: 30, // Number of days to keep attribution before it expires.

    autoAttachToEvents: true, // Default true; attaches stored campaign fields to outgoing events.
  },

  consent: {
    enabled: true, // Sends Google consent defaults through gtag consent mode.

    default: {
      analyticsStorage: 'granted', // Use granted/denied based on your consent banner's analytics category.
      adStorage: 'granted', // Use granted/denied based on your consent banner's advertising cookies category.
      adUserData: 'granted', // Use granted/denied based on permission to send user data for ads measurement.
      adPersonalization: 'granted', // Use granted/denied based on permission for personalized ads.
    },
  },

  routerTracking: {
    enabled: true, // Tracks browser history route changes in SPAs; framework router hooks can still call pageView manually.
  },
});

await KenziWebMarketingAnalytics.pageView({
  path: '/contact',
  title: 'Contact Us',
});

await KenziWebMarketingAnalytics.logEvent({
  name: KENZI_MARKETING_EVENTS.LEAD,
  params: {
    source: 'contact_form',
  },
});

await KenziWebMarketingAnalytics.trackPurchase({
  amount: 250,
  currency: 'AED',
  transactionId: 'INV-1001',
});

Angular Standalone Setup

Initialize once in browser startup code. In SSR apps, call this only in the browser, or call it universally and rely on the package's browser guards.

import { isPlatformBrowser } from '@angular/common';
import { APP_INITIALIZER, PLATFORM_ID, inject, Provider } from '@angular/core';
import { KenziWebMarketingAnalytics } from 'kenzi-web-marketing-analytics';

export const provideMarketingAnalytics = (): Provider => ({
  provide: APP_INITIALIZER,
  multi: true,
  useFactory: () => {
    const platformId = inject(PLATFORM_ID);

    return async () => {
      if (!isPlatformBrowser(platformId)) {
        return;
      }

      await KenziWebMarketingAnalytics.initialize({
        google: {
          enabled: true,
          measurementId: 'G-XXXXXXX',
        },
        meta: {
          enabled: true,
          pixelId: '123456789',
        },
      });
    };
  },
});

React Setup

This is a framework-neutral TypeScript package, so it works in React as long as initialization runs in the browser.

import { useEffect } from 'react';
import { KenziWebMarketingAnalytics } from 'kenzi-web-marketing-analytics';

export function MarketingAnalyticsBoot() {
  useEffect(() => {
    void KenziWebMarketingAnalytics.initialize({
      google: {
        enabled: true,
        measurementId: 'G-XXXXXXX',
      },
      meta: {
        enabled: true,
        pixelId: '123456789',
      },
    });
  }, []);

  return null;
}

Track React route/page changes from your router integration:

import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { KenziWebMarketingAnalytics } from 'kenzi-web-marketing-analytics';

export function AnalyticsRouteTracker() {
  const location = useLocation();

  useEffect(() => {
    void KenziWebMarketingAnalytics.pageView({
      path: `${location.pathname}${location.search}`,
      title: document.title,
    });
  }, [location.pathname, location.search]);

  return null;
}

Track Angular route changes from your app shell or analytics service:

import { NavigationEnd, Router } from '@angular/router';
import { filter } from 'rxjs';
import { KenziWebMarketingAnalytics } from 'kenzi-web-marketing-analytics';

router.events.pipe(filter((event): event is NavigationEnd => event instanceof NavigationEnd)).subscribe((event) => {
  void KenziWebMarketingAnalytics.pageView({
    path: event.urlAfterRedirects,
    title: document.title,
  });
});

Configuration

Google

await KenziWebMarketingAnalytics.initialize({
  google: {
    enabled: true,
    measurementId: 'G-XXXXXXX',
    adsConversionId: 'AW-XXXXXXX',
    conversions: {
      lead: 'AW-XXXXXXX/LEAD_LABEL',
      purchase: 'AW-XXXXXXX/PURCHASE_LABEL',
    },
    autoInjectScript: true,
    autoPageView: false,
    sendPageViewOnInitialize: false,
    enhancedEcommerce: true,
  },
});

The package injects the standard gtag.js script by default. autoInjectScript defaults to true; you do not need to pass it for normal browser usage. Set autoInjectScript: false only if the host application already owns script loading through Google Tag Manager, a consent manager, or server-rendered tags.

conversions maps application-level event names to Google Ads conversion labels. When a mapped event is logged, the package sends both the GA4 event and a conversion event with send_to.

autoPageView controls the initial GA4 config page view. It defaults to false because Angular, React, and other SPA apps usually send page views from router changes. sendPageViewOnInitialize remains supported as a backward-compatible alias.

enhancedEcommerce documents that ecommerce params should be sent through this package unchanged for GA4 reports. Pass GA4 ecommerce fields such as items, value, currency, coupon, and transaction_id in params or use trackPurchase.

Meta Pixel

await KenziWebMarketingAnalytics.initialize({
  meta: {
    enabled: true,
    pixelId: '123456789',
    autoInjectScript: true,
    autoPageView: true,
    autoConfig: true,
  },
});

The package injects Meta Pixel's browser script by default and calls fbq('init', pixelId). autoInjectScript defaults to true; you do not need to pass it for normal browser usage. Set autoInjectScript: false only when the host application already loads Meta Pixel.

Set autoPageView: true if you want an immediate Meta Pixel PageView after initialization. In SPAs with routerTracking or manual pageView calls, keep this false unless you intentionally want the first page view sent during initialization.

Campaign Tracking

await KenziWebMarketingAnalytics.initialize({
  campaignTracking: {
    enabled: true,
    storageKey: 'kenzi_campaign',
    expirationDays: 30,
    autoAttachToEvents: true,
  },
});

Campaign tracking captures these URL parameters when present and stores them in localStorage until expiration:

utm_source, utm_medium, utm_campaign, utm_term, utm_content, utm_id, gclid, gbraid, wbraid, fbclid, ttclid, li_fat_id

Stored campaign values are attached to provider event params unless explicitly overridden by event params.

Set autoAttachToEvents: false when you only want campaign data available through getCampaign() or sent to a custom backend manually.

Consent

await KenziWebMarketingAnalytics.initialize({
  consent: {
    enabled: true,
    default: {
      analyticsStorage: 'granted',
      adStorage: 'granted',
      adUserData: 'granted',
      adPersonalization: 'granted',
    },
  },
});

Consent defaults are sent to Google through gtag('consent', 'default', ...) before Google provider initialization. Use values from your cookie/consent banner. Supported values are granted and denied.

For stricter markets, start with denied values and update consent from your app after the user accepts. For markets where analytics and ads measurement are already covered by your consent flow before initialization, pass granted values.

Router Tracking

await KenziWebMarketingAnalytics.initialize({
  routerTracking: {
    enabled: true,
    includeHash: false,
  },
});

Router tracking watches browser history.pushState, history.replaceState, and popstate changes, then sends pageView for SPA navigation. This is framework-neutral and works in Angular, React, Vue, and regular TypeScript browser apps.

Set includeHash: true when hash changes are meaningful routes in your app, such as /docs#getting-started or hash-based routers.

For maximum control over titles, route names, and duplicate prevention, a framework router hook can call pageView manually instead of using routerTracking.

Custom Endpoint

await KenziWebMarketingAnalytics.initialize({
  customEndpoint: {
    enabled: true,
    url: 'https://api.example.com/analytics/events',
    headers: {
      'x-client': 'website',
    },
    includeCampaign: true,
  },
});

The custom endpoint receives a JSON POST payload containing the original event name, mapped provider name, sanitized params, timestamp, and stored campaign data.

Set includeCampaign: false if the endpoint should receive event params only. Advanced tests or custom runtimes can pass fetchImplementation; normal browser apps should use the default window.fetch.

Defaults

| Option | Default | Notes | | --- | --- | --- | | debug | false | Enables ***kenzi-marketing*** console diagnostics only when true. | | google.autoInjectScript | true | Injects gtag.js unless explicitly false. | | google.autoPageView | false | Best for SPAs; use router/manual page views instead. | | google.sendPageViewOnInitialize | false | Backward-compatible alias for initial GA4 page view behavior. | | google.enhancedEcommerce | true | Ecommerce params are preserved. | | meta.autoInjectScript | true | Injects Meta Pixel fbevents.js unless explicitly false. | | meta.autoPageView | false | Sends initial Meta PageView only when true. | | meta.autoConfig | Meta default | Set false to call fbq('set', 'autoConfig', false, pixelId). | | campaignTracking.storageKey | kenzi_campaign | localStorage attribution key. | | campaignTracking.expirationDays | 30 | Attribution lifetime. | | campaignTracking.autoAttachToEvents | true | Adds stored campaign params to outgoing events. | | routerTracking.includeHash | false | Hash is included only when explicitly true. | | customEndpoint.includeCampaign | true | Campaign object is included in endpoint payload unless false. |

Event Naming Strategy

Use one application-level event contract in website code, then let this package translate that event to the closest provider-specific name.

Do not scatter GA4, Google Ads, or Meta Pixel event names across product code. Providers do not always use the same standard names. For example:

  • App/business event: complete_registration
  • GA4 recommended event: sign_up
  • Meta Pixel standard event: CompleteRegistration

The preferred pattern is:

await KenziWebMarketingAnalytics.logEvent({
  name: 'complete_registration',
  params: {
    method: 'email',
  },
});

Event Name Autocomplete

The package exports readable event constants for TypeScript autocomplete:

import {
  KENZI_MARKETING_EVENTS,
  KENZI_STANDARD_MARKETING_EVENTS,
  type StandardMarketingEventName,
} from 'kenzi-web-marketing-analytics';

Use KENZI_MARKETING_EVENTS for dot-autocomplete:

await KenziWebMarketingAnalytics.logEvent({
  name: KENZI_MARKETING_EVENTS.LEAD,
});

Use KENZI_STANDARD_MARKETING_EVENTS when you need the full list of event string values for iteration or validation.

By default, logEvent maps known standard business events to provider standard events where a standard equivalent exists. To bypass provider mapping:

await KenziWebMarketingAnalytics.logEvent({
  name: 'internal_experiment_seen',
  params: {
    variant: 'A',
  },
  useProviderStandardEvents: false,
});

Route an operation to specific providers:

await KenziWebMarketingAnalytics.logEvent({
  name: 'campaign_landing_view',
  params: {
    campaign: 'ramadan_2026',
  },
  providers: ['google'],
});

Provider Mappings

| App event | Google/GA4 event | Meta Pixel event | Recommended params example | | --- | --- | --- | --- | | sign_up, complete_registration | sign_up | CompleteRegistration | { method: 'email' } | | login | login | login | { method: 'email' } | | page_view | page_view | PageView | { page_title: 'Contact Us', page_location: '/contact' } | | screen_view | screen_view | PageView | { screen_name: 'home' } | | search | search | Search | { search_term: 'apartments' } | | view_content | select_content | ViewContent | { content_type: 'service', item_id: 'seo' } | | view_item | view_item | ViewContent | { item_id: 'sku_123', item_name: 'Plan', value: 250, currency: 'AED' } | | add_to_cart | add_to_cart | AddToCart | { item_id: 'sku_123', value: 250, currency: 'AED' } | | begin_checkout | begin_checkout | InitiateCheckout | { value: 250, currency: 'AED' } | | purchase | purchase | Purchase | Prefer trackPurchase({ amount, currency }) | | lead, generate_lead | generate_lead | Lead | { source: 'contact_form' } | | contact | contact | Contact | { method: 'whatsapp' } | | schedule | schedule | Schedule | { service: 'demo' } | | subscribe | subscribe | Subscribe | { plan: 'monthly', value: 99, currency: 'AED' } | | start_trial | start_trial | StartTrial | { plan: 'pro', trial_days: 14 } |

Project-specific funnel events should still use logEvent. Keep event names lowercase snake_case, stable, and report-friendly. Avoid placing user-identifying data, product names, order IDs, phone numbers, emails, timestamps, or free text in event names.

API

initialize(options?)

Initializes configured providers and returns enabled provider names.

await KenziWebMarketingAnalytics.initialize(options);

pageView(options?)

Tracks a web page view. Defaults to the current browser URL and document title when available.

await KenziWebMarketingAnalytics.pageView({
  path: '/contact',
  title: 'Contact Us',
  location: 'https://example.com/contact',
  referrer: 'https://google.com',
  params: {
    language: 'en',
  },
  providers: ['google', 'meta'],
});

providers can route the page view to selected enabled providers. If omitted, all enabled providers receive it.

logEvent(options)

Tracks a standard or custom marketing event.

await KenziWebMarketingAnalytics.logEvent({
  name: 'lead',
  params: {
    source: 'contact_form',
  },
  providers: ['google', 'meta', 'customEndpoint'],
  useProviderStandardEvents: true,
});

useProviderStandardEvents defaults to true. Set it to false only when you want the exact raw event name sent to providers.

trackPurchase(options)

Tracks a purchase with validated amount and ISO 4217 currency code.

await KenziWebMarketingAnalytics.trackPurchase({
  amount: 250,
  currency: 'AED',
  transactionId: 'INV-1001',
  params: {
    item_id: 'plan_pro',
    item_name: 'Pro Plan',
  },
  providers: ['google', 'meta'],
});

setUserId(options)

Sets the Google user ID where supported. Meta Pixel and custom endpoint providers ignore this call.

await KenziWebMarketingAnalytics.setUserId({
  userId: '12345',
});

setUserProperty(options)

Sets a Google user property where supported.

await KenziWebMarketingAnalytics.setUserProperty({
  key: 'language',
  value: 'en',
});

getCampaign()

Returns the currently stored campaign, if available and not expired.

const campaign = KenziWebMarketingAnalytics.getCampaign();

clearCampaign()

Clears stored campaign attribution.

KenziWebMarketingAnalytics.clearCampaign();

Development

npm install
npm run verify