Add analytics to a Replit app with Replit Agent
undefined
To add analytics to a Replit app, paste the prompt below into Replit Agent. Replit Agent edits files and runs commands in its workspace, so it can get an AgentFirstStack key, create the site, and add a small route to your app's backend that serves the tracker from your own domain. Then come the two Replit steps people miss: secrets you set in the workspace don't reach the published app on their own, and edits aren't live until you republish. Other tools and platforms: add analytics with an AI agent.
The prompt
Add analytics to this app with AgentFirstStack. It's free, open-source analytics built for agents, and you can do all of it yourself: there is no signup form, and no email or verification is needed. 1. Read https://agentfirststack.com/llms.txt and https://analytics.agentfirststack.com/llms.txt. 2. If the AGENTFIRSTSTACK_API_KEY secret exists, use it and read AGENTFIRSTSTACK.md. Otherwise get a key with one request: curl -X POST https://agentfirststack.com/v1/signup Store api_key as the Replit secret AGENTFIRSTSTACK_API_KEY (never in code or in the frontend). Name the project after the domain: PATCH https://agentfirststack.com/v1/me. 3. Create a site for the published domain (the custom domain, or the .replit.app address). Read GET /v1/sites/:id/install, and store first_party_proxy.proxy_key as the secret AFS_PROXY_KEY. 4. In the backend, add a route for /_a/* that forwards to https://analytics.agentfirststack.com with the x-afs-proxy-key header, the visitor's IP (first X-Forwarded-For entry) as X-Forwarded-For, and the visitor's user agent. Register it before any static-file or SPA fallback route. Then add <script defer src="/_a/s.js" data-site="..."> to the <head> of the frontend's HTML. 5. Create goals for sign-ups, purchases and the main buttons, and send conversions only the server knows about from the backend as server events. 6. Add an email destination, a weekly report, and alerts for a traffic drop and for no data. 7. Tell me to add AGENTFIRSTSTACK_API_KEY and AFS_PROXY_KEY under Production app secrets and to republish. After I have, open the published URL, run verify and fix what it reports. 8. Write the site id and the secret names (never the values) in AGENTFIRSTSTACK.md, create a claim link with POST https://agentfirststack.com/v1/claim-link, then run GET https://agentfirststack.com/v1/setup?services=analytics and work through its next_steps until it says "ready": true. When you're done, tell me what you set up, how you verified it, and give me the claim link.
Serve the tracker from your app
Ad blockers block requests to analytics.agentfirststack.com. Replit says every web app it builds "includes a frontend and backend", so the backend can serve the tracker under your own domain instead, and those visitors count too. The tracker posts to the path it was loaded from, so /_a/s.js sends its events to /_a/e. In an Express backend:
// Before express.static and any SPA fallback route
app.use("/_a", express.text({ type: "*/*" }), async (req, res) => {
const ip = String(req.headers["x-forwarded-for"] || "").split(",")[0].trim() || req.socket.remoteAddress || "";
const r = await fetch("https://analytics.agentfirststack.com" + req.originalUrl, {
method: req.method,
headers: {
"x-afs-proxy-key": process.env.AFS_PROXY_KEY,
"x-forwarded-for": ip,
"user-agent": req.get("user-agent") || "",
"accept-language": req.get("accept-language") || "",
"content-type": "text/plain",
},
body: req.method === "POST" ? req.body : undefined,
});
res.status(r.status);
for (const h of ["content-type", "cache-control"]) if (r.headers.get(h)) res.set(h, r.headers.get(h));
res.send(Buffer.from(await r.arrayBuffer()));
});
A Flask or FastAPI backend does the same in a few lines: forward the path, the query string, the body, the user agent and those two headers. app.use("/_a", ...) matches the prefix in both Express 4 and 5.
The proxy key is what makes this work. The collector trusts a forwarded visitor IP only from requests carrying x-afs-proxy-key, the site's own secret. Without it every visitor arrives with your Replit server's address and merges into one, and verify reports proxy_key. Replit's docs don't say which header carries the visitor's address in a published app; the route above takes the first X-Forwarded-For entry, the common convention. If verify passes but the visitor count looks far too low, that's the thing to check.
One trade-off: location. Your backend can't see where visitors are, so the collector falls back to its view of your server, and country and city show your server's location. Visitor counts, pages, sources and devices are right. If location matters more to you than visitors with ad blockers, use the direct snippet instead (src="https://analytics.agentfirststack.com/s.js"), which gets the location from the visitor's own request.
Secrets: workspace and production
Replit stores secrets encrypted and gives them to your app as environment variables. The catch is in Replit's troubleshooting docs: "Secrets you set in the Project Editor do not automatically carry over to your published app." Add AGENTFIRSTSTACK_API_KEY and AFS_PROXY_KEY again under Publishing > Adjust settings > Production app secrets. Until you do, the published proxy sends no key and server events fail with 401.
Neither value belongs in the frontend. The tracker tag carries only the site id, which is public.
Connect the MCP server (optional)
Replit Agent can use remote MCP servers: + Add MCP server, paste the HTTPS endpoint, and add headers under Advanced settings. Use https://agentfirststack.com/mcp with the header X-API-Key set to your key; AgentFirstStack accepts it as well as Authorization: Bearer. The agent then calls tools like analytics_verify_install and afs_check_setup directly, and you can ask it about traffic in chat.
Publish, then verify
Replit is clear that "changes in the Project Editor do not automatically replace the live release", so republish after the agent's edits. Agent-built apps publish as Autoscale or Reserved VM deployments (Static deployments aren't compatible with them), at your-app.replit.app or your own domain. Then open the published URL once in a normal browser and run the checks:
K=$AGENTFIRSTSTACK_API_KEY
curl -s -X POST https://analytics.agentfirststack.com/v1/sites/$SITE/verify -H "Authorization: Bearer $K"
curl -s "https://agentfirststack.com/v1/setup?services=analytics" -H "Authorization: Bearer $K"
Verify fetches your published page, finds the tag, fetches /_a/s.js through your route to make sure it serves the tracker, checks whether events arrived with the proxy key, and lists fixes.
The dev URL doesn't count. The workspace preview runs at UUID.servername.replit.dev, which is private by default and only live while you work. A site accepts events only from its own domain and subdomains, so preview visits are dropped and stay out of your numbers. replit.app and replit.dev on their own are refused as site domains (shared suffixes); your-app.replit.app is fine.
Custom domains: Replit asks for an A record and a replit-verify TXT record, with Cloudflare's proxy turned off ("DNS only"). That rules out a Cloudflare Worker route on a Replit-hosted domain, which is why the proxy lives in your backend.
FAQ
Why does verify pass in the workspace but events never show up?
Probably the dev URL. Events from *.replit.dev aren't your site's domain, so they're dropped. Republish and test on the published address.
Server events return 401 in the published app only. Why?
Workspace secrets don't carry over to the published app. Add the key under Production app secrets and republish.
Why do all visitors show the same country?
That's the first-party proxy: your backend doesn't know visitor locations, so the collector sees your server's. Counts are right. Switch to the direct snippet if location matters more than visitors with ad blockers.
Does the tracker count page changes in a single-page app?
Yes. It records a page view on every History API navigation (pushState, replaceState, back and forward), so React Router and similar routers need nothing extra.
What does it cost?
The hosted service is free, with fair-use limits such as 10 analytics sites per account. The code is open source (AGPL-3.0), so you can run it yourself on Cloudflare Workers.
Related
- AnalyticsAdd analytics with an AI agentThe prompt, the checks, and every tool and platform.
- AnalyticsAdd analytics to a Lovable appindex.html, Cloud secrets and the published URL.
- AnalyticsAdd analytics to a Bolt appindex.html, .env and publishing.
- AnalyticsAdd analytics to a v0 appapp/layout.tsx, Vercel env vars and previews.
- AnalyticsAdd analytics with Claude CodeOne prompt in the terminal, then questions over MCP.
- All servicesOne MCP server for every serviceAnalytics, tags, mail and replay tools on one key.
- AnalyticsGoogle Analytics MCP comparedRead GA4, or let the agent create the analytics.
- Server-side conversion trackingMeta, Google Ads, TikTok and GA4, counted once.