{"_id":"@addilytics/astro","name":"@addilytics/astro","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@addilytics/astro","version":"0.0.1","description":"Astro server analytics and bundled navigation tracking.","type":"module","license":"MIT","publishConfig":{"access":"public"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./browser":{"types":"./dist/browser.d.ts","default":"./dist/browser.js"}},"dependencies":{"addilytics":"0.0.1"},"peerDependencies":{"astro":"^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"},"devDependencies":{"@astrojs/node":"^11.1.5","@types/node":"^24.0.0","astro":"^7.3.1","tsx":"^4.20.0","typescript":"^6.0.3"},"scripts":{"build":"tsc -p tsconfig.json","check":"tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json","test":"pnpm build && tsx --test --test-concurrency=1 test/*.test.ts test/*.test.mjs","test:compat":"pnpm build && node test/compat.mjs"},"_nodeVersion":"26.0.0","_id":"@addilytics/astro@0.0.1","dist":{"integrity":"sha512-VblnBy9dVhXwWGjD1oTlj3Nk5BvHLzi5jwAB5TIfEavU65SavPsD4VoeVv1RPVOwacoB4XvWQvPm8w6fHffXLg==","shasum":"33a25a5327eda1a54304810287cc0c13fa808c75","tarball":"https://registry.npmjs.org/@addilytics/astro/-/astro-0.0.1.tgz","fileCount":6,"unpackedSize":13909,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDNYWkQaQgwoR/WcTqCopQaNH8VQWKMr9x8lW14eLsDkAIgfH/eYQfjQ+CnQLLCfPm9fvsn7kcTkCNMGKtnIlzSdnI="}]},"_npmUser":{"name":"embedvr","email":"npm@helium.email"},"directories":{},"maintainers":[{"name":"embedvr","email":"npm@helium.email"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/astro_0.0.1_1789127069472_0.3291259443391492"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-11T11:44:29.290Z","0.0.1":"2026-09-11T11:44:29.608Z","modified":"2026-09-11T11:44:29.794Z"},"maintainers":[{"name":"embedvr","email":"npm@helium.email"}],"description":"Astro server analytics and bundled navigation tracking.","license":"MIT","readme":"# @addilytics/astro\n\nAstro middleware that records pageviews after Astro has produced the final response. It does not\nread, clone, or replace the response body.\n\n```ts\n// src/middleware.ts\nimport { addilytics } from '@addilytics/astro';\n\nexport const analytics = addilytics({\n\tendpoint: 'https://addilytics.example',\n\tsiteKey: import.meta.env.ADDILYTICS_KEY\n});\n\nexport const onRequest = analytics;\n```\n\nIf you compose middleware with `sequence()`, put authentication or session initialization first,\nAddilytics second, and routes or response-mutating middleware after it. Astro runs earlier\nmiddleware as outer layers, so Addilytics still sees the final status and headers from later\nmiddleware.\n\n```ts\nimport { sequence } from 'astro:middleware';\n\nexport const onRequest = sequence(sessionMiddleware, analytics, responseMiddleware);\n```\n\nThis order matters in hybrid and client modes. Addilytics answers relay requests without calling\nlater middleware. Resolve identity from `Astro.locals` only when an earlier middleware populates it.\nA resolver that reads the raw request can stay inside the Addilytics options.\n\nThe adapter ignores Astro's `/_astro/` assets along with the core asset filters. It records only\neligible final HTML responses. Redirects, JSON responses, and server errors are skipped by default.\nMiddleware runs for on-demand rendered routes. A prerendered page served as a static file or directly\nfrom a CDN never reaches Astro's server middleware. Use client mode below when those first views\nmust count.\n\n## Custom events\n\nExport the middleware instance when an endpoint needs to record an event.\n\n```ts\nimport type { APIRoute } from 'astro';\nimport { analytics } from '../middleware';\n\nexport const POST: APIRoute = async (context) => {\n\tawait analytics.track(context, 'newsletter_signup', {\n\t\tprops: { plan: 'weekly' }\n\t});\n\treturn new Response(null, { status: 204 });\n};\n```\n\n`track()` uses the same bot filtering and identity rules as the core client.\n\n## Identity and background delivery\n\nUse `user` when identity depends on `Astro.locals` or another part of the Astro context.\n\n```ts\nexport const analytics = addilytics({\n\tendpoint: 'https://addilytics.example',\n\tsiteKey: import.meta.env.ADDILYTICS_KEY,\n\tuser: (context) => context.locals.user?.id\n});\n```\n\nRegister the middleware that populates `Astro.locals` before `analytics` in `sequence()`.\n\nOn Cloudflare, the adapter uses `context.locals.runtime.ctx.waitUntil()` when available. On other\nplatforms it waits for delivery before returning. Supply `waitUntil` for another adapter:\n\n```ts\nexport const analytics = addilytics({\n\tendpoint: 'https://addilytics.example',\n\tsiteKey: import.meta.env.ADDILYTICS_KEY,\n\twaitUntil: (context) => context.locals.waitUntil\n});\n```\n\nAnalytics failures never replace or reject an otherwise successful application response.\n\n## Browser navigation modes\n\nServer tracking remains the default. Use `hybrid` when Astro serves the first document and a client\nrouter handles later navigations. Use `client` when the browser should own every pageview. Client\nmode keeps custom server events enabled but skips automatic server document capture.\n\nSet the same mode and relay path on both sides:\n\n```ts\n// src/middleware.ts\nexport const analytics = addilytics({\n\tendpoint: process.env.ADDILYTICS_ENDPOINT!,\n\tmode: 'hybrid',\n\trelayPath: '/internal/analytics',\n\tsiteKey: process.env.ADDILYTICS_SITE_KEY!\n});\n\nexport const onRequest = analytics;\n```\n\n```astro\n<!-- src/layouts/Layout.astro -->\n<script>\n\timport { installAddilytics } from '@addilytics/astro/browser';\n\n\tinstallAddilytics({\n\t\tendpoint: '/internal/analytics',\n\t\tmode: 'hybrid'\n\t});\n</script>\n```\n\nThe browser entry listens for Astro's `astro:page-load` event, which runs after a navigation commits.\nIt also records persisted back-forward cache restores. Repeated calls to `installAddilytics()` reuse\nthe active tracker instead of attaching duplicate listeners. Call `destroy()` on the returned\ntracker to remove them.\n\nHash-only changes are ignored by default. Set `trackHashChanges: true` to count them. The browser\nsends only a generated event ID, timestamp, pathname, allowlisted campaign query, and referrer to\nthe same-origin relay. The server adds request metadata and user identity before delivery. The site\nkey and ingest endpoint stay in server code, and the adapter does not load a hosted script.\n\nThe relay accepts only its exact configured path. It rejects cross-origin requests, invalid JSON,\nand oversized or malformed payloads before they reach the application route.\n","readmeFilename":"","_rev":"1-a4ca32734133f4d4e0950788f9229520"}