Skip to content

Integrating Mitr Analytics β€” a guide for AI coding assistants

This page is written to be handed directly to an AI assistant (Claude, ChatGPT, Copilot, Cursor, etc.) β€” pasted into a chat, or fetched by an agent from /docs/ai-integration.md (plain markdown, same content). Following it end-to-end, an assistant should be able to fully wire up Mitr Analytics in a client's codebase without 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 (Integration Hub β†’ their app's card, or the "SDK Setup" step of the "Add New App" wizard).
  2. Platform β€” a website (plain HTML or a JS framework), or a Flutter app (iOS/Android/desktop)? Flutter also needs the Secret Key from the same dashboard screen.

Web snippets load the SDK from https://mitranalytics.dev/vendor/mitr.js, the canonical URL. Events go to https://api.mitranalytics.dev/api/v1, the SDK's built-in default β€” set data-base-url only to point at a self-hosted or staging backend. You can also self-host mitr.js from your own static assets; the API is identical either way.

If the human doesn't have a Site ID yet, tell them: "Go to your Mitr dashboard β†’ 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." You cannot generate a Site ID yourself.

Do not invent a placeholder Site ID and ship it. Use a literal placeholder like YOUR_SITE_ID until the human gives you a real one.

Step 2 β€” Detect the platform (if not already told)

You find...PlatformGo to
pubspec.yaml with flutter: sectionFlutter appStep 3C
package.json with "next"Next.jsStep 3B
package.json with "react" (no Next)React SPAStep 3B
package.json with "vue" / "nuxt"Vue / NuxtStep 3B
Plain .html files, no frameworkStatic siteStep 3A
WordPress/Shopify/Webflow/Squarespace/Wix (human describes it)No-code platformStep 3A (no-code variant)
No JS repo at allAsk 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:

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

That's it β€” no other code 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 pastes the exact same snippet into their platform's "Custom Code" / "Header Scripts" / "Tracking Code" section β€” every one of these platforms has such a setting.

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 β€” not to every page/component.

Plain script tag (simplest, works anywhere):

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

Next.js (App Router) β€” app/layout.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 startup instead of a script tag, if preferred:

useEffect(() => { window.Mitr.init('YOUR_SITE_ID'); }, []);

Auto-tracking already covers client-side route changes β€” no per-route tracking calls needed for React Router, Vue Router, or similar.

Custom events, wherever the relevant action happens:

window.Mitr.track('signup_completed', { plan: 'pro' });

On login/logout, if the app has auth:

window.Mitr.identify(user.id); // after login
window.Mitr.reset();           // on logout

Full API reference: JavaScript SDK.

Step 3C β€” Flutter app (iOS / Android / desktop / Flutter Web)

  1. Add the dependency (adjust the path to wherever this SDK lives relative to the client's project β€” tell the human it needs to be vendored locally, since it isn't on pub.dev yet):
    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 Secret Key from Step 1:
    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:
    MaterialApp(
      navigatorObservers: [MitrNavigationObserver()],
      // ...
    )
    (Use observers: instead if the app uses GoRouter.)
  4. Custom events, wherever relevant:
    await MitrAnalytics.instance.track('purchase_completed', meta: {'value': 49.99});
  5. On login/logout, if the app has auth:
    MitrAnalytics.instance.identify(user.id); // after login
    MitrAnalytics.instance.reset();           // on logout

Full API reference: 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" β€” 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 (common cause: testing on a different domain/subdomain β€” localhost is always allowed in non-production environments). A 404 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, most commonly flagging 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.
  • 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.

Have questions about integration or security? Drop us a line directly.