@stackonward/analytics-nuxt
v0.2.4
Published
Provider-neutral Nuxt analytics module with consent, SPA views, composables, directives, and autocapture
Downloads
1,415
Maintainers
Readme
@stackonward/analytics-nuxt
Provider-neutral analytics lifecycle for Nuxt with typed tracking, consent,
SPA page views, a v-analytics directive, and privacy-aware browser
autocapture.
Provider integrations normally install this module for the application. Install
it directly when composing a custom AnalyticsTransport or lifecycle
participant.
Install
pnpm add @stackonward/analytics-nuxtNuxt and Vue are peer dependencies. See Compatibility.
Setup
export default defineNuxtConfig({
modules: ["@stackonward/analytics-nuxt"],
analytics: {
applicationId: "product-a",
environment: "production",
consent: { required: true },
autoCapture: {
internalDomains: ["product.example"],
moduleRules: [{ selector: "header", module: "navigation" }],
captureText: false,
},
},
});The module creates the provider-neutral runtime but does not register a destination transport. Install a provider integration or register a custom transport before expecting delivery.
Track product events
Product event catalogs stay in the application:
type ProductEvent =
| { name: "creation_started"; properties: { creation_type: string } }
| { name: "creation_completed"; properties: { duration_ms: number } };
const analytics = useAnalytics<ProductEvent>();
const result = await analytics.track({
name: "creation_started",
properties: { creation_type: "video" },
});track and pageView return the complete AnalyticsTrackResult; inspect its
status instead of treating the call as unconditional success. status exposes
the runtime lifecycle, and retry() retries a failed lifecycle activation.
Consent
Consent presentation and persistence belong to the product or its consent management platform:
import { onMounted } from "vue";
const consent = useAnalyticsConsent();
onMounted(() => {
const savedDecision = localStorage.getItem("analytics-consent");
if (savedDecision === "granted") consent.grant();
if (savedDecision === "denied") consent.deny();
});With the default consent.required: true, Google Consent Mode loads with storage
denied. Page views still record as cookieless pings until the visitor grants
cookies. Denial keeps storage denied and does not stop those pings. Setting
required: false starts with consent granted; that is a product policy decision,
not a persistence mechanism.
Declarative metadata
Use v-analytics when autocapture needs semantic fields that cannot be derived
from the DOM:
<button
v-analytics="{
name: 'upgrade_cta',
action: 'open_checkout',
module: 'pricing',
properties: { plan: 'pro' },
}"
>
Upgrade
</button>Invalid directive metadata is removed from the registry and reported through bounded diagnostics when debug mode is enabled.
Options
| Option | Default | Purpose |
| ------------------------------------ | ------- | ------------------------------------------------------------------------------ |
| enabled | true | Enables lifecycle activation and event delivery |
| applicationId | "" | Adds application_id context when non-empty |
| environment | "" | Adds application_environment context when non-empty |
| debug | false | Emits bounded browser diagnostics as stackonward:analytics-diagnostic events |
| consent.required | true | Starts unknown; GTM still loads under Consent Mode. false starts granted |
| autoCapture.pageViews | true | Tracks the initial route and successful SPA navigations |
| autoCapture.elementClicks | true | Captures configured interactive elements |
| autoCapture.linkClicks | true | Captures classified link interactions |
| autoCapture.captureText | false | Includes bounded element text only when explicitly enabled |
| autoCapture.allowedQueryParameters | [] | Preserves only approved query parameters in captured URLs |
Autocapture also supports include/exclude selectors, link types, module rules, ancestor depths, element IDs/classes, event-name overrides, and device breakpoints. Unknown top-level and nested configuration keys are rejected.
Custom providers
A provider module can access the injected runtime from a Nuxt plugin, register one transport and any script/consent lifecycle participant, and retain the returned unregister functions. Participant IDs must be unique and registration closes after activation begins.
Server rendering can validate and enqueue provider-neutral events, but browser
lifecycle participants and retry() are unavailable during SSR and fail with
LifecycleError.
Lifecycle states
disabled, idle, waiting-for-consent, starting, active, failed, and
disposed are observable through useAnalytics().status. Provider start/stop
failures move the runtime to failed; disposal aggregates participant failures
instead of silently ignoring them.
Compatibility
- Node.js 20 or newer
- Nuxt
>=3.15.0 <5 - Vue
>=3.5.0 <4
Related packages
@stackonward/analytics-coreprovides the provider-neutral contracts and browser engine.@stackonward/google-tag-manager-nuxtprovides consent-aware GTM composition.
