Files
zeekayandHanzo Dev 01fb7e5953 rename EVENT_INGEST_KEY -> PUBLISHABLE_KEY
The value is a pk- prefixed PUBLISHABLE key (the Stripe vocabulary, and what
the build-time gate already tests for). EVENT_INGEST_KEY hid that.

One substitution covers all three spellings, since the framework prefixes wrap
the same token: EVENT_INGEST_KEY -> PUBLISHABLE_KEY, NEXT_PUBLIC_* and VITE_*
follow. KMS already carries deploy/PUBLISHABLE_KEY (env prod) with the same
value, written and read back first, so no build can reach a name that does not
exist yet.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-05 16:25:04 -07:00

51 lines
2.0 KiB
TypeScript

'use client'
import { usePathname } from 'next/navigation'
import { AnalyticsProvider, usePageview } from '@hanzo/event/react'
/** The ONE Hanzo telemetry front door — POST api.hanzo.ai/v1/event. Cloud fans the
* single batched stream out to the web (analytics), product (insights) and error
* lenses, so there is no second analytics SDK and no second error SDK. The client
* never sends the org; Cloud resolves the tenant from the publishable key. */
const HOST = 'https://api.hanzo.ai'
/** Publishable ingest key (pk_…), minted per org via POST /v1/ingest/keys. Every
* visitor here is logged out, so no bearer can ride the request and this
* write-only, bundle-safe key IS how anonymous pageviews and errors resolve to an
* org. Unset → events are best-effort and dropped at the edge. */
const INGEST_KEY = process.env.NEXT_PUBLIC_PUBLISHABLE_KEY?.trim() || undefined
/** Honor an explicit browser opt-out — Global Privacy Control first, then legacy
* DNT. Opting out suppresses pageviews AND errors. */
function consented(): boolean {
if (typeof navigator === 'undefined') return true
const nav = navigator as Navigator & {
globalPrivacyControl?: boolean
doNotTrack?: string | null
}
if (nav.globalPrivacyControl === true) return false
const dnt = nav.doNotTrack
return dnt !== '1' && dnt !== 'yes'
}
function Pageview() {
usePageview(usePathname())
return null
}
/** Telemetry root. The provider owns the ONE @hanzo/event client: it fires the
* first pageview, registers auto error capture (window.onerror +
* unhandledrejection) and flushes on unload. <Pageview> adds one per client-side
* route change — the provider's autoPageview already covers the initial load, so
* pages are counted exactly once. */
export function Analytics({ children }: { children: React.ReactNode }) {
return (
<AnalyticsProvider
config={{ product: 'store', host: HOST, ingestKey: INGEST_KEY, enabled: consented() }}
>
<Pageview />
{children}
</AnalyticsProvider>
)
}