Hosted App Analytics
Privacy-friendly traffic analytics for Gencow-hosted frontend apps, including automatic script injection, Dashboard metrics, country attribution, and query scrubbing
Gencow-hosted apps get privacy-friendly web analytics without adding a third-party tracker. When you deploy frontend HTML through Gencow, the platform injects a same-origin analytics script, records scrubbed pageview events, and shows traffic inside the app's Dashboard Analytics tab.
The analytics path is owned by Gencow:
Browser on your hosted app
-> /_gencow/analytics.js
-> POST /_gencow/analytics/event
-> Gencow Analytics collector
-> Dashboard Analytics tabYour app does not need to know the analytics database, table names, rollup strategy, or storage backend. The public contract is the same-origin script and collector route.
When It Runs
Analytics runs for frontend pages served by Gencow static/fullstack hosting:
bun run build
gencow deploy --static dist/The platform injects a deferred script into HTML responses:
<script defer src="/_gencow/analytics.js" data-deploy="<deployId>"></script>You usually do not add this tag yourself. Gencow injects it when the deployed asset is HTML and analytics is enabled for the app/site.
| Deployment shape | Behavior |
|---|---|
| Gencow-hosted HTML | Script is injected automatically |
| Gencow-hosted SPA route | Route changes are tracked through History API hooks |
| Gencow-hosted asset-only deploy | No HTML means no script injection |
| Externally hosted frontend | Automatic injection is not available |
The analytics endpoints are reserved platform paths. Do not create app routes
under /_gencow/analytics.js or /_gencow/analytics/event.
What Gets Tracked
The default event is pageview. The script records the first pageview and SPA
route changes. It sends a bounded payload with safe browser metadata:
| Field | Meaning |
|---|---|
eventName |
pageview by default, or a custom event name |
url / path |
Current page URL after query scrubbing |
referrer |
Referrer after same-origin and query scrubbing rules |
utm_* |
Standard UTM fields when present |
screen |
Screen width/height bucket, not a high-precision fingerprint |
language |
Browser language |
timestamp |
Client timestamp; server receive time remains authoritative |
deployId |
Current deploy id when available |
You can record a simple custom event from browser code:
window.gencow?.analytics?.track?.("signup_completed");Keep event names short and non-sensitive. Do not include user ids, emails, tokens, prompt text, storage grant URLs, or form values in event names.
Privacy And Security
Gencow analytics is designed for aggregate product traffic, not user tracking.
- raw IP is not stored
- email, name, user id, cookies, localStorage, sessionStorage, request bodies, form values, prompts, and file contents are not collected
- the collector uses request-scope IP only to derive a visitor/session key and a country code
- country attribution stores country only; region and city are not collected
- DNT/GPC is respected by the browser script
- known crawler, smoke-test, oversized, and rate-spike traffic can be dropped
- if analytics storage is unavailable, the collector fails open so page loads are not blocked
The query scrubber keeps ordinary attribution data and removes secret-like
parameters before storage. UTM fields such as utm_source, utm_medium,
utm_campaign, utm_term, and utm_content are allowed. Parameters such as
token, code, secret, key, password, session, and grant are removed
even if they appear beside UTM fields.
Example:
https://example.com/pricing?utm_source=newsletter&token=abc&code=oauthStored page dimension:
/pricing?utm_source=newsletterDashboard Metrics
Open Dashboard -> App -> Analytics to inspect traffic.
| Metric | Meaning |
|---|---|
| Visitors | Distinct privacy-preserving visitor keys for the selected period |
| Visits | Session count for the selected period |
| Pageviews | Count of pageview events |
| Views per visit | Pageviews divided by visits |
| Bounce rate | Share of visits with a single pageview when the backend can compute it |
| Visit duration | Aggregate visit duration when enough session data is available |
| Current visitors | Recent active visitor estimate |
Reports group the same traffic by source, page, country, device, browser, OS, and goals/events. Row clicks add filters to the current Dashboard view so you can answer questions such as:
| Question | Dashboard path |
|---|---|
| Which pages attracted traffic this week? | Select 7d -> Pages |
| Did a campaign send useful visitors? | Select date range -> Sources -> filter by UTM source |
| Which countries are visiting after launch? | Countries report |
| Are mobile users bouncing more? | Devices report -> compare bounce rate |
Country Attribution
Country is derived at collection time. Gencow first uses trusted country headers from the edge/proxy when available. If no country header is present, the platform can use a local country GeoIP database to derive a country code from the request-scope client IP. Only the country dimension is stored.
If the country database is unavailable, analytics remains available and country
falls back to Unknown. Your app still loads normally.
Custom Domains
Analytics follows the active Gencow site mapping. Official subdomains and active custom domains both use the same same-origin script path:
https://my-app.gencow.app/_gencow/analytics.js
https://www.example.com/_gencow/analytics.jsThe collector resolves the app/site from the request host and platform domain mapping. It does not trust client-sent app ids or site ids for ownership.
Troubleshooting
| Symptom | Check |
|---|---|
| No pageviews after deploy | Confirm the deployed HTML is served by Gencow and includes /_gencow/analytics.js |
| SPA navigation not counted | Confirm the app uses normal History API navigation; hard reloads and route changes should both send pageviews |
Country shows Unknown |
Edge country headers or the platform country database may be unavailable |
| Local browser not counted | DNT/GPC may be enabled, or browser extensions may block analytics requests |
| Custom domain traffic missing | Confirm the domain is active and serving the Gencow-hosted app |
Analytics should never require provider API keys, database credentials, or application secrets in frontend code.