net/http middleware in Go, and Rack middleware in Ruby. Mount it around the handler that serves your marketing site, and each page load is reported to Page views in the background. Agents, crawlers, and people all get your site exactly as before.
All four implement one contract:
- Only
GETrequests to non-asset paths are reported; assets and every other method pass through unobserved. - The handler runs first, so the beacon carries the real response status and the request duration. The visitor’s
User-Agent,Accept, and connecting IP are forwarded for server-side classification. - It records the response’s representation (
htmlormarkdown, read from the response’s content-type) and, when Agentify attached one, the journey id that stitches this view to the agentified read. Both are captured automatically; you set nothing. - The beacon is fire-and-forget and fails open. A missing key, a network error, a non-204, a timeout, or a malformed report is handed to
onErrorand swallowed. The middleware never delays or breaks the page.
Configure the key
Reporting uses azc_ key with the page-views:write scope. TypeScript is standalone: the key rides inline on the middleware as apiKey, with no createSeller and no signing secrets. The other three SDKs read it from a page_views_key / PageViewsKey field on the client you already build for the guard; when that field is unset, they fall back to the combined API key.
PageViewsTimeout defaults to DefaultPageViewTimeout (2 seconds), and the other SDKs use an equally short page-view default (timeoutMs in TypeScript, page_view_timeout_seconds in Ruby), long enough to send the beacon, short enough never to sit on a page.
Mount the middleware
page-views:write key.
Combining with Agentify
Page views and Agentify are independent opt-ins: run either alone or both. When you run both, Page views must be the outer middleware, wrapping Agentify, and this ordering is load-bearing, not cosmetic.- It is the only way Page views sees agent traffic at all. The Agentify middleware short-circuits agent requests: on a match it returns markdown and never calls the inner handler. A Page views beacon mounted inside Agentify would therefore never fire for those requests, silently dropping exactly the agent page views you most want to measure. Only the outer layer observes them.
- It stitches the journey. Being outside is also how the page view picks up the journey id Agentify attaches to its response, tying the marketing view to the agentified read on one journey.
use build a stack instead: in WSGI the last wrap is outermost, so Page views is applied second; in Rack the first use is outermost, so Page views is mounted first. In every case the result is the same: Page views sits on the outside of Agentify.
Options
Each middleware takes the same options, named in its language’s idiom:
The key itself is not an option here: TypeScript passes
apiKey inline on the middleware, while Python, Go, and Ruby configure it once on the client as page_views_key / PageViewsKey. Behind a proxy that rewrites the scheme or host, set the URL override so the reported path comes from the public URL rather than the one your process sees: only the path is ever reported.
Report without the middleware
Any language or framework can report by calling the REST endpoint directly, once per page-contentGET. Each SDK also exposes a one-shot reporter for when the middleware boundary does not fit (a background job, a custom router, a hand-rolled handler):
A direct reporter carries the same body the middleware sends, and can set
representation and the journey id explicitly rather than deriving them from a response it never saw.
Failing open, observably
The middleware exists to add a measurement, never an outage or a delay: any error on the reporting path leaves the response untouched. That silence is deliberate, and it means a misconfigured key looks exactly like a working page, so wire the error hook to your logger:OnError falls back to the client’s configured Logger.
Next steps
REST endpoint
The underlying request: body, response, and errors.
Overview
What is captured, how viewers are classified, and the key scope.