Native apps
A native app has no <script> tag to load lytics.js into, so it talks to /ingest directly. The endpoint is a plain JSON POST with no key on it, which is the whole integration — there is no native SDK to install.
Two fields separate app traffic from website traffic in the same project:
platform—"ios"or"android". The browser snippet sends"web".app— which client sent it, e.g."myapp-mobile". Lowercase letters, digits,.,_and-, up to 64 characters. Websites set the same tag withdata-app.
Both show up in the dashboard’s Devices & apps card.
Sending an event
Section titled “Sending an event”await fetch("https://api.analytics.canarycoders.es/ingest", { method: "POST", headers: { "Content-Type": "application/json", // Native requests carry no Origin of their own, and ingest checks it // against the project's trusted domains. Send the product's own origin. Origin: "https://myapp.com", }, body: JSON.stringify({ domain: "myapp.com", // must be one of the project's trusted domains sessionId, // UUID v4, see below eventType: "page_view", // or "custom" with an eventName path: "/hotspot/teide", // the app's own route platform: "ios", app: "myapp-mobile", deviceType: "mobile", // or "tablet" — the app knows, no UA to read it off locale: "en-GB", }),});Ingest answers 204 to everything, including rows it drops, so there is nothing to branch on. Fire and forget.
Sessions
Section titled “Sessions”The browser snippet scopes a session to a tab (sessionStorage). An app has no tab, so mint a UUID v4, persist it, and rotate it after a stretch of inactivity — 30 minutes is the usual choice and what CanaryPulse’s own app uses. Sessions are how unique visitors are counted, so a single id that never rotates collapses the whole install into one visitor forever.
What the server does differently for native events
Section titled “What the server does differently for native events”- No bot classification. React Native’s default Android user agent is a bare
okhttp/4.12.0, which every bot list matches. Native events skip the check outright rather than being labelled crawlers and hidden from stats. oscomes from the platform tag (ios→ iOS,android→ Android) since there is no browser UA to parse, andbrowserstays empty.deviceTypecomes from the app, falling back tomobilewhen it is not sent.
Report the app’s own routes. They will not match the website’s URLs — /hotspot/teide in an app against /en/hotspots/tenerife/h/teide on the web — so Top pages lists both shapes side by side and the app tag is what tells them apart. Rewriting native routes into web URLs is rarely worth the mapping code.