@performance-now-app/vite-tracking-plugin
v1.1.0
Published
Vite plugin for tracking and analytics
Maintainers
Readme
@pnw-platform/pnw-vite-tracking-plugin
A Vite plugin for injecting tracking and analytics scripts into your HTML at build time. Supports multiple vendors, SPA route change detection, anti-flicker guards, cross-domain tracking, and custom page events — all configured declaratively in vite.config.js.
Features
- Multi-vendor — Configure one or more tracking vendors; each gets its own init script and route handler.
- SPA route change detection — Monitors
popstate,pushState,replaceState, andpn:pageupdateevents, notifying all vendors on every navigation. - Anti-flicker — Injects compile-time CSS to hide elements until experiment/tracking scripts are ready, with configurable timeout fallback.
- Cross-domain / subdomain tracking — Appends query parameters for shared session tracking across domains.
- Custom data attributes — Pass arbitrary
data-*attributes to the injected script tag for runtime configuration. - Page events — Fire
window.pnevt()calls on SPA route changes matching glob patterns. - Framework-agnostic — Works with Vue, React, Svelte, or any Vite-based project.
Installation
npm install @pnw-platform/pnw-vite-tracking-pluginQuick Start
// vite.config.js
import { defineConfig } from "vite";
import pnwViteTrackingPlugin from "@pnw-platform/pnw-vite-tracking-plugin";
export default defineConfig({
plugins: [
pnwViteTrackingPlugin([
{
performancenow: {
client_key: "your-client-key",
},
},
]),
],
});This injects a tracking script pointing to https://your-client-key.fastrk.cc/default/dist/ into the <head> of your HTML.
Configuration
The plugin accepts an array of vendor config objects. Each object has a single key — the vendor name — whose value is that vendor's configuration.
pnwViteTrackingPlugin([
{ vendorName: { /* vendor config */ } },
{ anotherVendor: { /* vendor config */ } },
])Vendor: performancenow
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| client_key | string | (required) | The vendor's unique client key. Used to build the default endpoint URL. |
| endpoint | string | https://{client_key}.fastrk.cc | Custom tracking endpoint URL. Overrides the default. |
| redirect_key | string | "default" | Path segment appended to the endpoint URL (/{redirect_key}/dist/). |
| subdomain_tracking | boolean | false | Appends ?xd=true to the script URL for cross-domain session sharing. |
| anti_flicker | boolean \| AntiFlickerConfig | false | Enables anti-flicker guard. See Anti-Flicker below. |
| data_attrs | Array<{ key: string, value: boolean }> | [] | Custom data-* attributes set on the injected <script> tag. Keys are normalized from kebab-case to camelCase. |
| page_events | Array<PageEvent> | [] | SPA route-based custom events. See Page Events below. |
Example — full configuration
pnwViteTrackingPlugin([
{
performancenow: {
client_key: "my-store",
endpoint: "https://custom.endpoint.com/track",
redirect_key: "v2",
subdomain_tracking: true,
anti_flicker: { timeout: 3000 },
data_attrs: [
{ key: "disable-experiments", value: true },
{ key: "debug-mode", value: false },
],
page_events: [
{ key: "viewed_home", url: "/" },
{ key: "viewed_product", url: "/products/**" },
{ key: "viewed_cart", url: "/cart" },
{ key: "viewed_checkout", url: "/checkout/*" },
],
},
},
]);Anti-Flicker
When anti_flicker is enabled, the plugin injects a <style> block at head-prepend that hides elements with the .pn-hide-until-replaced class:
.pn-hide-until-replaced {
visibility: hidden !important;
opacity: 0 !important;
}At runtime, the injected script:
- Sets a fallback timer (default 5 s, configurable via
anti_flicker.timeout) that forcibly reveals hidden elements if the tracking script fails to load. - Exposes
window.__pnReplacerReady()— call this from your experiment/replacer code to signal success and clear the timer early. - Removes the hidden class on
script.onloadandscript.onerror.
Usage in your replacer code:
// Call as early as possible once experiments are applied
window.__pnReplacerReady();Page Events
Page events fire window.pnevt(key, { to, from }) whenever the SPA route changes to a URL matching a glob pattern.
| Option | Type | Description |
|--------|------|-------------|
| key | string | Event name slug (alphanumeric, underscores, hyphens). Passed as the first argument to window.pnevt(). |
| url | string | Glob pattern matched against the navigated-to URL at runtime. Uses picomatch with { bash: true }. |
The page events registry is stored at window.__pn_page_events as an array of { key, re } objects (the glob is compiled to a regex at build time).
Cross-Domain / Subdomain Tracking
Set subdomain_tracking: true to append ?xd=true to the tracking script URL. The client-side tracking code reads this parameter and enables shared session tracking across domains (e.g., store.example.com → checkout.example.com).
Custom Data Attributes
Use data_attrs to pass runtime configuration to the tracking script via data-* attributes:
data_attrs: [
{ key: "disable-experiments", value: true },
{ key: "debug-mode", value: false },
]This produces:
<script src="..." data-disable-experiments="true" data-debug-mode="false"></script>Keys are normalized from kebab-case to camelCase automatically (e.g., "disable-experiments" → data-disable-experiments).
SPA Route Change Detection
The plugin injects a runtime script that:
- Monitors browser navigation — intercepts
popstate,pushState, andreplaceState. - Listens for
pn:pageupdateevents — forwards custom events dispatched by your app (e.g., frompage_update.js). - Notifies all vendors — each vendor's
onRouteChanged(to, from)handler is called with the new and previous URL.
This enables automatic tracking of virtual pageviews in single-page applications without manual instrumentation.
TypeScript
Type definitions are included:
import type { VendorConfig, AntiFlickerConfig, PageEvent } from "@pnw-platform/pnw-vite-tracking-plugin";Supported Vendors
| Vendor | Description | |--------|-------------| | performancenow | Full-featured tracking vendor supporting endpoint configuration, anti-flicker, page events, data attributes, and subdomain tracking. |
License
ISC
