# Integrating Mitr Analytics — a guide for AI coding assistants

This file is written to be handed directly to an AI assistant (Claude,
ChatGPT, Copilot, Cursor, etc.) — either pasted into a chat, or placed in a
repo where the assistant can read it. Following it end-to-end, an assistant
should be able to fully wire up Mitr Analytics in a client's codebase
without needing back-and-forth beyond the two questions in Step 1.

If you are that assistant: work through the steps in order. Steps 1–2 need
information only the human has. Steps 3 onward you can do yourself by
reading the project you're working in.

---

## Step 1 — Get the two things you need from the human

Ask (only if not already provided):

1. **Site ID** — a UUID from the Mitr dashboard at
   https://app.mitranalytics.dev (Integration Hub → their app's card, or the
   "SDK Setup" step of the "Add New App" wizard).
2. **Platform** — is this a website (plain HTML, or a JS framework), or a
   Flutter app (iOS/Android/desktop)? If it's a Flutter app, you'll also
   need the **Secret Key** from the same dashboard screen.

All web snippets below load the SDK from `https://mitranalytics.dev/vendor/mitr.js`,
which is live and is the canonical URL. Events are sent to
`https://api.mitranalytics.dev/api/v1`, which is the SDK's built-in default —
you only need to set `baseUrl` / `data-base-url` when pointing at a
self-hosted or staging backend.

If you prefer not to depend on a third-party origin, you can self-host
instead: copy `mitr.js` into the project's static assets and point `src` at
that path. The API is identical either way.

If the human doesn't have a Site ID yet, tell them: *"Go to
https://app.mitranalytics.dev → Integration Hub → Add New App, choose your
platform, and enter your domain (for a website) or bundle/package ID (for an
app). You'll get a Site ID immediately, plus a Secret Key if you chose a
non-web platform. If you don't have an account yet, you can create one there
for free — 10,000 events a month, no credit card."*
You cannot generate a Site ID yourself — it must come from their dashboard.

**Do not invent a placeholder Site ID and ship it.** Use a literal
placeholder like `YOUR_SITE_ID` if the human hasn't given you a real one
yet, and tell them to swap it in.

---

## Step 2 — Detect the platform (if not already told)

Look at the repo you're working in:

| You find...                                      | Platform            | Go to |
|---------------------------------------------------|----------------------|-------|
| `pubspec.yaml` with `flutter:` section             | Flutter app          | Step 3C |
| `package.json` with `"next"` dependency            | Next.js              | Step 3B |
| `package.json` with `"react"` (no Next)            | React SPA            | Step 3B |
| `package.json` with `"vue"` / `"nuxt"`             | Vue / Nuxt           | Step 3B |
| Plain `.html` files, no framework                  | Static site          | Step 3A |
| A WordPress/Shopify/Webflow/Squarespace/Wix site (no local codebase — human describes it) | No-code platform | Step 3A (no-code variant) |
| No JS repo at all, human describes "my website"    | Ask which of the above, or default to Step 3A no-code variant | — |

---

## Step 3A — Plain HTML / static site / no-code platform

Paste this once, right before `</head>` or the closing `</body>` tag:

```html
<script src="https://mitranalytics.dev/vendor/mitr.js"
        data-site-id="YOUR_SITE_ID"
        async defer></script>
```

That's it — no other code is required. It auto-tracks page views,
including client-side route changes if the site later adds one.

**No-code platforms** (WordPress, Shopify, Webflow, Squarespace, Wix): the
human needs to paste the exact same snippet into their platform's
"Custom Code" / "Header Scripts" / "Tracking Code" section — every one of
these platforms has such a setting, usually under Site Settings →
Advanced/Custom Code. You cannot do this step yourself if you don't have
repo access to their site — give them the snippet and the location to
paste it (search "custom code" or "header scripts" in their platform's own
settings if unsure of the exact menu path, since these menus change over
time).

Do not add a secret key anywhere in web output. It isn't needed and
shouldn't be embedded in public HTML/JS.

---

## Step 3B — JS framework (React, Next.js, Vue, Nuxt, etc.)

Add the SDK once near your app's root/entry point — do **not** add it to
every page/component.

> **There is no framework-specific package.** `mitr-react`, `mitr-vue`,
> `mitr-next`, and an npm package named `mitr` do not exist — do not run
> `npm install` for any of them, and do not import `MitrProvider` or
> `MitrPlugin`. Every JS framework uses the same script tag below. There is
> also no `apiKey` and no `mk_live_...` key: credentials are a Site ID
> (UUID) and, for non-web platforms only, a Secret Key.

**Plain script tag (works in any framework, simplest option):**
Add to the root HTML template (`public/index.html` for CRA/Vite, or via
your framework's head-injection API):
```html
<script src="https://mitranalytics.dev/vendor/mitr.js" data-site-id="YOUR_SITE_ID" async defer></script>
```

**Next.js (App Router) — `app/layout.jsx`:**
```jsx
'use client';
import Script from 'next/script';

export default function RootLayout({ children }) {
  return (
    <html><body>
      {children}
      <Script src="https://mitranalytics.dev/vendor/mitr.js" data-site-id="YOUR_SITE_ID" strategy="afterInteractive" />
    </body></html>
  );
}
```

**React SPA — call once at app startup instead of a script tag, if you
prefer JS-first init:**
```jsx
useEffect(() => { window.Mitr.init('YOUR_SITE_ID'); }, []);
```

Auto-tracking already covers client-side route changes (it patches
`history.pushState`/`popstate`) — you do not need to add per-route tracking
calls for React Router, Vue Router, or similar.

**Custom events**, wherever the relevant action happens in the code (e.g. a
submit handler, a purchase-confirmation component):
```js
window.Mitr.track('signup_completed', { plan: 'pro' });
```

**On login/logout**, if the app has auth:
```js
window.Mitr.identify(user.id); // after login
window.Mitr.reset();           // on logout
```

Full API reference: [JavaScript SDK docs](/docs/js-sdk).

---

## Step 3C — Flutter app (iOS / Android / desktop / Flutter Web)

1. Add the dependency (adjust the path to wherever this SDK suite lives
   relative to the client's project — if it's not vendored locally, tell
   the human it needs to be, since this SDK isn't on pub.dev yet):
   ```yaml
   dependencies:
     mitr_flutter:
       path: ../path/to/mitr-sdk-suite/mitr_flutter
   ```
   Then run `flutter pub get`.

2. Initialize once, at the top of `main()`, using **both** the Site ID and
   the Secret Key from Step 1:
   ```dart
   import 'package:mitr_flutter/mitr_flutter.dart';

   Future<void> main() async {
     WidgetsFlutterBinding.ensureInitialized();
     await MitrAnalytics.instance.initialize(
       siteId: 'YOUR_SITE_ID',
       secretKey: 'YOUR_SECRET_KEY',
     );
     runApp(const MyApp());
   }
   ```

3. Add automatic screen tracking to the app's router:
   ```dart
   MaterialApp(
     navigatorObservers: [MitrNavigationObserver()],
     // ...
   )
   ```
   (Use `observers:` instead if the app uses `GoRouter`.)

4. Custom events, wherever relevant in the app's code:
   ```dart
   await MitrAnalytics.instance.track('purchase_completed', meta: {'value': 49.99});
   ```

5. On login/logout, if the app has auth:
   ```dart
   MitrAnalytics.instance.identify(user.id); // after login
   MitrAnalytics.instance.reset();           // on logout
   ```

Full API reference: [Flutter SDK docs](/docs/flutter-sdk).

---

## Step 4 — Verify it worked

1. Run the site/app and navigate around.
2. In the Mitr dashboard → Integration Hub, open the app's card and click
   "Check connection" (or, if mid-wizard, the "Verify Connection" step) —
   it should flip from "Pending" to "Connected" within a few seconds of the
   first event being sent.
3. If it doesn't:
   - **Web**: open devtools → Network tab, find the request to
     `.../api/v1/event`. A `403` means the page's domain doesn't match what
     was registered in the dashboard (common cause: testing on a different
     domain/subdomain than the one registered — `localhost` is always
     allowed in non-production environments). A `404` on the site itself
     means the Site ID is wrong or the app was deleted.
   - **Flutter (debug builds)**: check the console — `initialize()` fires a
     diagnostic ping and logs the result immediately (`MITR TRACKING [DEV
     SUCCESS]` or `[DEV ERROR]` with the reason, most commonly a wrong
     Secret Key).

---

## Things to never do

- Never put a Flutter/mobile **Secret Key** into web-facing HTML/JS — web
  doesn't need one and it would be publicly visible in page source.
- Never pass a raw email, name, or other PII into `track`/`identify`/
  `pageView` metadata — only pass an opaque user id to `identify`; the SDK
  hashes it before it's sent. Metadata fields (`meta`/`utm`) are for
  non-identifying event context (e.g. `{ plan: 'pro' }`), not personal data.
- Never call `init`/`initialize` more than once per app instance, and never
  block app startup waiting on it — both SDKs degrade gracefully (queue
  locally, retry later) if the network or backend is temporarily
  unavailable.
