Add analytics to a Bolt app with its AI agent

undefined

Updated

To add analytics to a Bolt app, connect AgentFirstStack to Bolt as a custom MCP connector, paste the prompt below, and publish. Bolt's agent then has AgentFirstStack's tools: it creates the analytics site, adds the tracker to your app's HTML head, and after you publish it runs verify and the setup check. One thing to know first: Bolt's hosting has no documented way to serve the tracker from your own domain, so on bolt.host the tracker loads from analytics.agentfirststack.com, and visitors with an ad blocker aren't counted. If you host the project on Netlify instead, you can fix that. Other builders and tools: add analytics with an AI agent.

1. Connect AgentFirstStack to Bolt

In the chat box: + > Connectors > Manage connectors > Custom MCP server. Use the HTTP transport and the URL https://agentfirststack.com/mcp. Bolt offers three kinds of authentication: API key, MCP OAuth, or none.

  • MCP OAuth is the safer bet. AgentFirstStack's MCP server supports OAuth 2.1 with dynamic client registration: you sign in with Google, create a project named after your app's domain, and choose full access. The project is yours from the start.
  • API key works if Bolt sends it as Authorization: Bearer or X-API-Key, the two headers AgentFirstStack accepts. Bolt's docs don't say which header it uses, so if tool calls fail with 401, switch to OAuth.

Why MCP rather than letting the agent run curl: Bolt runs your project in StackBlitz WebContainers, inside your browser. The WebContainers docs describe requests from there failing on CORS, and AgentFirstStack's API doesn't send CORS headers, so API calls from Bolt's terminal may not get through. The connector calls the tools from Bolt's side.

2. Paste the prompt

Paste this into the Bolt chat

Add analytics to this app with AgentFirstStack, using the AgentFirstStack MCP connector I added. 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, or its bolt.host or netlify.app address. 3. Get the install code (analytics_get_install_instructions). If the project has an index.html at its root (a Vite app), add the snippet inside <head> there. If it's Next.js or Astro, use that framework's layout. Never put an API key in .env or in frontend code: anything there ends up in the published site. Bolt's hosting can't proxy the tracker through our 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 (or click Update). After I say it's live, 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.

Bolt's docs say it "focuses on JavaScript-based web technologies" and don't name one default stack, so the agent checks the project. In a Vite app, index.html at the project root is the page every route uses:

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

Page changes inside the app count without more code: the tracker records a page view on every history.pushState, replaceState and back or forward navigation, which is how React Router and similar routers work. For a Next.js or Astro project, follow the Next.js or Astro guide instead. You can check the agent's edit in Bolt's code view, where you can open and edit files yourself.

Keys: not in .env

Bolt is direct about this: values in a project's ordinary environment variables can be read by browser code, and "that value ends up in what's sent to anyone visiting your published site." The tracker doesn't need a key, only the public site id, so the snippet is safe. An AgentFirstStack API key is different. If the app sends conversions from the server (a paid order, a verified sign-up), put the key in Bolt Cloud's Secrets, which "only work with server functions", and send the event from a server function with the visitor id the page passes along (window.afsa.visitorId()).

Publish, then verify

Bolt publishes to an address ending in bolt.host, or your own domain on a paid plan. Later changes "aren't automatically applied to your published site": click Update after the agent's edits. Then ask the agent to verify. It runs analytics_verify_install, which fetches the live page, finds the tag, checks whether events arrived and lists fixes, and afs_check_setup, which lists what else the setup needs.

Visit the published URL once yourself first, in a normal browser. Bolt's preview doesn't count: it runs on your own machine, inside the editor, and isn't on your app's domain, so its events are dropped. Bolt's docs also note that ad blockers and VPNs can break the preview itself.

On Netlify: serve it from your own domain

Bolt can still deploy to Netlify, at a netlify.app address or your own domain. If you host the project there from its GitHub repository, add a Netlify Edge Function on /_a/* that forwards to AgentFirstStack with the site's proxy key. The Astro guide has the full function; it doesn't depend on the framework. Put first_party_proxy.proxy_key from GET /v1/sites/:id/install in Netlify's environment variables as AFS_PROXY_KEY with the Functions scope, then change the snippet's src to /_a/s.js. The tracker and its events are then first-party, so visitors with ad blockers count too. The proxy key matters: the collector only trusts the forwarded visitor IP from requests that carry it, and without it every visitor looks like Netlify's one address.

Things that trip people up

  • Forgetting Update. The agent's edit isn't live until you publish again; verify reports snippet_present failing until then.
  • Shared suffixes. bolt.host and netlify.app addresses are fine as site domains (your-app.netlify.app); netlify.app on its own is refused.
  • Duplicated projects. Bolt's docs say a duplicated project needs its custom domain re-pointed. The analytics site follows the domain, so the duplicate's events are dropped until its domain matches.
  • Instructions for later chats. Add a line to the project's Knowledge (project settings): "This app uses AgentFirstStack analytics; ids are in AGENTFIRSTSTACK.md; run afs_check_setup before changing tracking."

FAQ

Can Bolt's agent run the setup with curl?

Not reliably. Bolt's terminal runs in WebContainers inside your browser, where requests to APIs without CORS headers can fail, and AgentFirstStack's API doesn't send them. Use the MCP connector, or run the API side from a coding agent with a real terminal.

Why doesn't this guide use a first-party proxy on bolt.host?

Bolt's hosting docs describe no way to forward a path to another server with a header. On Netlify you can, with an Edge Function. Without a proxy, ad blockers block the tracker.

Does the API key end up in my app?

No. The tracker needs only the public site id. The key lives in the connector (or nowhere, with OAuth), and for server events in Bolt Cloud Secrets.

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

Yes, every History API navigation is a page view. Hash routes (#/page) need data-hash="true" on the script tag.

Does the tracker use cookies?

No. By default a visitor is a hash of a daily salt, the site, the IP address and the user agent. Nothing is stored in the browser unless you switch the site to persistent mode.

Bolt and StackBlitz belong to StackBlitz, Inc.; Netlify belongs to its owners. AgentFirstStack isn't affiliated with either. Bolt details come from its help center (MCP connectors, supported technologies, code view, secrets, server functions, publishing, Netlify, project settings, preview issues) and the WebContainers docs, checked on 6 November 2026.