Add analytics to a Lovable app with its AI agent

undefined

Updated

To add analytics to a Lovable app, connect AgentFirstStack to Lovable as a custom MCP server, paste one prompt into the project chat, and publish. Lovable's agent then has AgentFirstStack's tools: it creates the site, adds the tracker to the app's document head, and after you publish it verifies the live app and runs the setup check. You never handle an API key in the browser, and the project lands in your own AgentFirstStack dashboard because you signed in to connect it. One limit: Lovable's hosting has no documented way to serve the tracker from your own domain, so it loads from analytics.agentfirststack.com and visitors with an ad blocker aren't counted. For other builders and editors, see add analytics with an AI agent.

1. Connect AgentFirstStack to Lovable

Lovable lets every plan add custom MCP servers: Connectors > Add custom > MCP server. Use this URL:

https://agentfirststack.com/mcp

Then pick one way to authenticate:

  • OAuth (easiest). Leave the token empty. AgentFirstStack's MCP server supports OAuth 2.1 with dynamic client registration: you sign in with Google, choose "Create a new project" (name it after your app's domain) and pick full access. The project is yours from the start, so there's no claim link to open later.
  • Bearer token. If you already have a key, or get one from any terminal with curl -X POST https://agentfirststack.com/v1/signup, paste it as the connector's bearer token. Keep a copy in your password manager: the key is the account.

Two Lovable rules to know. Custom MCP servers "only give Lovable context in the project chat": the agent uses them while it builds, and your published app never calls them. And connections are per user, so a teammate who wants the agent to use AgentFirstStack connects it themselves.

2. Paste the prompt

Paste this into the Lovable project chat

Add analytics to this app with AgentFirstStack, using the AgentFirstStack MCP server I connected. Read https://agentfirststack.com/llms.txt and https://analytics.agentfirststack.com/llms.txt first. 1. Name the project after the app's domain (afs_update_project) if it has no name. 2. Create an analytics site (analytics_create_site) for the domain the app is published on: the custom domain if it has one, otherwise its .lovable.app address. If the app answers on both, set allowed_hostnames to the custom domain (*.example.com) plus the .lovable.app host. 3. Get the install code (analytics_get_install_instructions) and add the tracker script to the document head so every page has it. If the app uses TanStack Start, add <script async src="https://analytics.agentfirststack.com/s.js" data-site="SITE_ID"> inside <head> in the root route's document, next to <HeadContent />. If it's a React + Vite app, add the snippet to <head> in index.html. The site id is public; never put an API key in frontend code or in a VITE_ variable. Lovable's hosting can't proxy the tracker through the app's domain, so note in AGENTFIRSTSTACK.md that ad blockers block analytics here. 4. Create goals for sign-ups, purchases and the main buttons (data-afsa-event attributes on buttons work without code). 5. Add an email destination, a weekly report, and alerts for a traffic drop and for no data. 6. Tell me to publish. After I say it's published, run analytics_verify_install, fix what it reports, then run afs_check_setup with services ["analytics"] and work through its next_steps until it says ready. Write the site id in AGENTFIRSTSTACK.md (never a key), and tell me what you set up and how you verified it.

If you connected with a bearer token instead of OAuth, add a last line asking for a claim link (afs_create_claim_link), so you can see the project in the dashboard.

It depends on when the project was created. Lovable's docs say apps created from 13 May 2026 (22 June on Enterprise plans) use TanStack Start with server-side rendering. Older apps are React + Vite single-page apps.

TanStack Start apps. TanStack keeps the HTML document in the root route, src/routes/__root.tsx, where <HeadContent /> renders the head tags. Put the tracker next to it:

<head>
  <HeadContent />
  <script async src="https://analytics.agentfirststack.com/s.js" data-site="site_..." />
</head>

Rendered there, the tag is in the HTML the server sends, so verify can find it and the homepage proves your domain. async rather than defer because React streams the page; React's docs say defer doesn't work with streaming server rendering.

React + Vite apps. index.html is the one HTML file every route uses:

<head>
  <script defer src="https://analytics.agentfirststack.com/s.js" data-site="site_..."></script>
</head>

Either way, page changes inside the app are counted: the tracker wraps history.pushState and listens for popstate, which is how both React Router and TanStack Router navigate. Don't add a page-view hook on top; that counts each page twice.

On paid plans you can check or make the edit yourself in Lovable's code editor (it's read-only on the Free plan), or in GitHub through Lovable's two-way sync.

Why the direct snippet

Where the hosting allows it, AgentFirstStack's tracker is served from the site's own domain through a small proxy, because ad blockers block analytics.agentfirststack.com. That needs the host to forward a path such as /_a/* to another server with a secret header. Lovable's docs describe no such setting, so this guide uses the direct snippet and accepts that visitors with ad blockers aren't counted. If you deploy the app's code somewhere else from GitHub (Vercel, Netlify, Cloudflare), add that host's proxy from GET /v1/sites/:id/install and switch the src to /_a/s.js.

The API key and server events

The browser only needs the site id. The API key is only for the agent's tools and for server code, and Lovable keeps those apart for you. Its Secrets are "injected into your project's Edge Functions and server-side integrations at runtime", while anything in .env with a VITE_ prefix is "embedded into the client bundle at build time". Lovable also refuses VITE_ names in Secrets.

So when a conversion happens on the server (a verified sign-up, a paid order through a payment webhook), send it from an Edge Function with the key from Secrets:

// in a Lovable Cloud Edge Function (Deno)
await fetch(`https://analytics.agentfirststack.com/v1/sites/${Deno.env.get("AFS_SITE")}/events`, {
  method: "POST",
  headers: {
    authorization: `Bearer ${Deno.env.get("AGENTFIRSTSTACK_API_KEY")}`,
    "content-type": "application/json",
  },
  body: JSON.stringify({ events: [{ name: "signup", visitor_id: visitorId, user_id: userId }] }),
});

Get visitorId on the page with window.afsa.visitorId() and send it along with the sign-up or checkout request, so the event joins the visit that led to it. If you connected over OAuth, create the key for Secrets in the AgentFirstStack dashboard; OAuth sessions can't create API keys.

Publish, then verify

Nothing reaches your visitors until you publish, and later edits stay in the editor until you click Publish > Publish changes. The published app lives at your-app.lovable.app; on a paid plan you can connect your own domain. Then ask the agent to verify. It runs analytics_verify_install, which fetches the live page and checks the snippet, that the script loads, the Content-Security-Policy and whether events arrived, and afs_check_setup, which lists anything else the setup is missing.

Visit the published URL once yourself before verifying. The editor preview doesn't count: the preview's "open in new tab" link needs a Lovable login, and it isn't on your app's domain, so its events are dropped.

Things that trip people up

  • Two addresses. There's no way to remove the .lovable.app URL, even with a custom domain. A site accepts events only from its domain and subdomains, so if visitors can reach both, set allowed_hostnames to ["*.example.com", "your-app.lovable.app"]. That list replaces the default, so include your own domain. lovable.app on its own is refused as a site domain, because it's a shared suffix; your-app.lovable.app is fine.
  • Forgetting to publish. The agent's edit is in the editor, not live. Verify reports snippet_present failing until you publish.
  • Lovable's own analytics. Lovable has built-in analytics with its own script. Both can run; they don't interfere.
  • Instructions for later chats. Lovable reads AGENTS.md or CLAUDE.md at the top level of the project with every message, and also has Project settings > Instructions. Add a line there such as "This app uses AgentFirstStack analytics; ids are in AGENTFIRSTSTACK.md; run afs_check_setup before changing tracking."

FAQ

Can Lovable's agent set up analytics without an MCP server?

Lovable's docs don't say its agent can make arbitrary API calls such as POST /v1/signup, so connect the MCP server. Alternatively, run the setup from a coding agent with a terminal (Claude Code, Cursor, Codex) on the GitHub copy of the project.

Does the API key end up in my app's code?

No. The tracker needs only the public site id. The key lives in the MCP connector (or nowhere, with OAuth) and, for server events, in Lovable's Secrets, which only Edge Functions read.

Will it count page changes in a single-page app?

Yes. The tracker records a page view on every History API navigation, which covers React Router and TanStack Router. Hash routes (#/page) need data-hash="true" on the script tag.

Do I need a cookie banner for it?

The tracker sets no cookies and stores nothing in the browser by default. Whether your site needs a banner is a legal question; if a consent manager should decide, add data-require-consent="true" and call afsa('consent', true) after consent.

What does it cost?

The hosted service is free, with fair-use limits such as 10 analytics sites per account. Lovable's custom MCP servers are available on every plan; custom domains need a paid Lovable plan.

Lovable is a product of Lovable Labs. TanStack belongs to its owners. AgentFirstStack isn't affiliated with either. Lovable details come from its docs (custom MCP servers, SEO and rendering, secrets, publishing, custom domains, instructions, code mode), and TanStack details from the TanStack Router docs, checked on 6 November 2026.