> ## Documentation Index
> Fetch the complete documentation index at: https://docs.insito.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Screen tracking

> Auto-discover the screens your app uses, target surveys per-screen, and audit the screen-map view.

Screen tracking surfaces which routes your users actually visit. The
data feeds two systems:

1. **Per-screen triggers** — `screen_viewed:/checkout` automatically
   fires when the user lands on `/checkout`, so you can wire a
   survey to any path without adding `trigger()` calls everywhere.
2. **Screen map** in the dashboard — shows which paths exist,
   ordered by visit count.

## Expo Router

Drop the hook in your root layout. Zero config.

```tsx app/_layout.tsx theme={null}
import { Stack } from "expo-router";
import { InsitoProvider, useInsitoScreenTracking } from "@insito/react-native";

export default function RootLayout() {
  useInsitoScreenTracking();
  return (
    <InsitoProvider>
      <Stack />
    </InsitoProvider>
  );
}
```

What happens:

* The hook reads `usePathname()` from `expo-router`.
* Each new (non-duplicate) pathname is recorded via
  `MicroSurvey.recordScreenVisit(pathname)`.
* If the user has been identified, the SDK also fires a trigger
  named `screen_viewed:<pathname>` — fire-and-forget, swallowing
  errors. This means the dashboard can target a survey to a
  specific screen without your app shipping any new code.

## React Navigation

For projects that use bare React Navigation (no Expo Router),
forward `onStateChange` to the SDK:

```tsx theme={null}
import { NavigationContainer } from "@react-navigation/native";
import { MicroSurvey } from "@insito/react-native";

<NavigationContainer onStateChange={MicroSurvey.onNavigationStateChange}>
  ...
</NavigationContainer>
```

The SDK walks the navigation state, finds the current focused route's
name, and records it. Same auto-trigger behaviour as the Expo Router
hook.

## Manual screen recording

If your routing library isn't supported (or you're not using one),
call `recordScreenVisit` directly:

```tsx theme={null}
import { MicroSurvey } from "@insito/react-native";

useEffect(() => {
  MicroSurvey.recordScreenVisit("home");
}, []);
```

Note this method isn't on the public type surface (it's marked
`@internal` for hot-path tests) — but it's safe to call from host
code.

## Data flow

```mermaid theme={null}
sequenceDiagram
  participant App
  participant SDK
  participant API

  App->>SDK: usePathname → "/checkout"
  SDK->>SDK: ScreenMap.record("/checkout")
  Note over SDK: Aggregates locally for 60s
  SDK->>API: POST /v1/sdk/screen-map { screens: {...} }
  SDK-->>App: screen_map_flushed { screens }
```

Local aggregation reduces network chatter. The SDK debounces visits
into a 60-second window, then flushes the accumulated counts in one
batch. If the app moves to the background or inactive state before the timer
fires, the SDK flushes immediately; a failed flush is retried on the next
scheduled flush.

## Viewing screens in the dashboard

[admin.insito.app](https://admin.insito.app) → your project →
**Screens** tab. Lists every path Insito has seen, sorted by visit
count, with a search box.

Use this to:

* Audit your information architecture (which screens are users
  actually using?).
* Target a survey to a specific path — paste the path into a
  survey's trigger field with the `screen_viewed:` prefix, e.g.
  `screen_viewed:/checkout/success`.
* Spot dark corners — screens with low visit counts that aren't
  marketing assumed dead-ends.

## Limits and gotchas

* Paths are stored verbatim. If your route has dynamic params
  (`/products/[id]`), Expo Router gives you the templated form,
  not the literal — good. If you're using React Navigation with
  manual `params`, the screen name omits them — also good.
* Each flush sends at most 200 paths (`POST /v1/sdk/screen-map`), so keep
  screen names bounded — collapse dynamic segments to templated forms
  (`/products/[id]`) rather than literal ids to avoid an unbounded path set.
* The hook is a **no-op** if `expo-router` isn't installed. You'll
  see one debug warning in development, then silence.
