feat(market): send pageviews to Hanzo Insights

The marketplace shipped with no telemetry of any kind — no pageviews, no
sessions, no errors — so there was no way to say whether anyone uses it, or
which collection they came for. It is one of seven Lux surfaces going dark in
the same way, and all seven report through @hanzo/event, which posts to our own
door at api.hanzo.ai and to nobody else. A marketplace's traffic is not a thing
to hand to a third party, so no tag manager and no vendor script.

The provider wraps the client tree at the root, which is what makes every route
counted from one place. It sits outside the dynamically loaded wallet and
account providers on purpose: that chunk carries wagmi, IAM and the gui engine,
and a visitor whose wallet never arrives is exactly the visitor worth hearing
about. The provider counts the first load and usePageview counts every
navigation after it, so a single-page app stops looking like one visit that
never moves.

The ingest key is publishable — it attributes a write and can read nothing, so
it belongs in the bundle the way a public address does. An env override lets a
deploy swap it; the literal is what makes the site report today, since the
image is built with no arguments.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-08-13 11:49:15 -07:00
co-authored by Hanzo Dev
parent 338372bf11
commit 0bcee42adf
2 changed files with 33 additions and 1 deletions
+1
View File
@@ -12,6 +12,7 @@
"lint": "next lint"
},
"dependencies": {
"@hanzo/event": "^0.3.21",
"@hanzo/gui": "^7.3.0",
"@hanzo/iam": "^0.13.8",
"@luxfi/ui": "7.4.10",
+32 -1
View File
@@ -1,10 +1,41 @@
'use client'
import dynamic from 'next/dynamic'
import { usePathname } from 'next/navigation'
import { AnalyticsProvider, usePageview } from '@hanzo/event/react'
import type { ReactNode } from 'react'
const Providers = dynamic(() => import('./providers').then((m) => m.Providers), { ssr: false })
// The market measured nothing: not a pageview, not a session, not an error. Six
// other Lux surfaces were equally dark, so nobody could answer which of them
// anyone actually uses. `@hanzo/event` is the ONE client the fleet reports
// through — it posts to api.hanzo.ai/v1/event and to nobody else, which is the
// point: the traffic of a marketplace is not a thing to hand to a third party.
//
// It wraps `Providers` rather than sitting inside it. That chunk carries wagmi,
// IAM and the gui engine and is loaded on its own; a visitor whose wallet stack
// never arrives is precisely the visitor worth hearing about, so the counter
// must not ride in the same box as the thing it counts.
//
// The key is publishable — it attributes a write and can read nothing, so it
// belongs in the bundle the way a public address does. A deploy can override it
// through the env; the literal is what makes the site report today, since this
// image is built with no arguments.
const INGEST_KEY = process.env.NEXT_PUBLIC_PUBLISHABLE_KEY || 'pk-gUZp6ZVfhJzSwK-rb4oLbVkpCnMBx5uSCpxf_5yEhQk'
// The provider counts the first load. This counts every navigation after it —
// without it a single-page app looks like one visit that never moves.
function Pageviews() {
usePageview(usePathname())
return null
}
export function ClientProviders({ children }: { children: ReactNode }) {
return <Providers>{children}</Providers>
return (
<AnalyticsProvider config={{ product: 'market', ingestKey: INGEST_KEY }}>
<Pageviews />
<Providers>{children}</Providers>
</AnalyticsProvider>
)
}