<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ImageAPI AI</title>
    <description>The latest articles on DEV Community by ImageAPI AI (@imageapi_ai_060a84ea83609).</description>
    <link>https://dev.to/imageapi_ai_060a84ea83609</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4167083%2F99fb4465-e867-4000-9baf-8440c18ebc26.jpg</url>
      <title>DEV Community: ImageAPI AI</title>
      <link>https://dev.to/imageapi_ai_060a84ea83609</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/imageapi_ai_060a84ea83609"/>
    <language>en</language>
    <item>
      <title>Ask Claude Code why your traffic spiked (an MCP walkthrough)</title>
      <dc:creator>ImageAPI AI</dc:creator>
      <pubDate>Wed, 14 Oct 2026 14:18:41 +0000</pubDate>
      <link>https://dev.to/imageapi_ai_060a84ea83609/ask-claude-code-why-your-traffic-spiked-an-mcp-walkthrough-3eld</link>
      <guid>https://dev.to/imageapi_ai_060a84ea83609/ask-claude-code-why-your-traffic-spiked-an-mcp-walkthrough-3eld</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I built measuremy.site, the analytics tool used in this post. All the numbers below are from my own site, including the unflattering ones.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I check analytics dashboards about once a week, and when I do, I mostly look at the chart, see a bump, and move on without knowing what caused it. What I actually wanted was to ask "why did traffic jump on Monday?" in the same place I already work, my terminal with Claude Code open, and get an answer with numbers.&lt;/p&gt;

&lt;p&gt;This walkthrough connects website analytics to Claude Code over MCP (Model Context Protocol), then uses it to answer three questions about a real site:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How is traffic doing?&lt;/li&gt;
&lt;li&gt;What caused that spike, and was it even human?&lt;/li&gt;
&lt;li&gt;Did the post I published actually bring anyone?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Connect the MCP server
&lt;/h2&gt;

&lt;p&gt;The server is remote and signs in with OAuth, so there's no API key to paste into a config file. In Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--scope&lt;/span&gt; user &lt;span class="nt"&gt;--transport&lt;/span&gt; http measuremysite https://a.measuremy.site/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--scope user&lt;/code&gt; makes it available in every project, not just the current one. Restart Claude Code (&lt;code&gt;claude -c&lt;/code&gt; keeps your conversation), run &lt;code&gt;/mcp&lt;/code&gt;, pick &lt;code&gt;measuremysite&lt;/code&gt; and choose &lt;strong&gt;Authenticate&lt;/strong&gt;. A browser window opens, you sign in with an emailed code (or start the trial) and pick the site.&lt;/p&gt;

&lt;p&gt;If you haven't added tracking to your site yet, you can skip the steps above and paste one sentence instead. The agent connects the server, asks you to sign in, and adds the script tag to your layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add measuremy.site analytics to this project: connect the measuremy.site MCP server at https://a.measuremy.site/mcp for all my projects (claude mcp add --scope user; it signs in with OAuth, no key, and one sign-in covers every site), then tell me how to sign in. Details: measuremy.site/llms.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tracker itself is one deferred script tag with no cookies, so there's no consent banner to add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;defer&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://a.measuremy.site/t.js"&lt;/span&gt; &lt;span class="na"&gt;data-key=&lt;/span&gt;&lt;span class="s"&gt;"pk_..."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cursor, VS Code, Codex and Gemini CLI connect to the same URL; the config for each is in the &lt;a href="https://measuremy.site/docs/mcp" rel="noopener noreferrer"&gt;MCP docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. "How is traffic doing?"
&lt;/h2&gt;

&lt;p&gt;My first question was "give me an overview of the last 30 days". Claude calls &lt;code&gt;get_overview&lt;/code&gt; and &lt;code&gt;get_timeseries&lt;/code&gt;, and gets back plain JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pageviews"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1066&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"visitors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;478&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"top_sources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(direct)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"visitors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;362&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"google.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"visitors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"news.ycombinator.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"visitors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reddit.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"visitors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interesting part was the daily series, which Claude summarised better than the chart did for me:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Day&lt;/th&gt;
&lt;th&gt;Visitors&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Oct 3 (launch: Show HN + Reddit)&lt;/td&gt;
&lt;td&gt;115&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oct 4–8&lt;/td&gt;
&lt;td&gt;36–71&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oct 9–13&lt;/td&gt;
&lt;td&gt;11–20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That's the classic post-launch decay. Its follow-up observation was the useful one: almost everything I'd done since launch (directory listings, docs, SEO pages) pays off over weeks, so nothing was replacing the launch traffic in the short term. Fair.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. "What caused that spike? Was it a bot?"
&lt;/h2&gt;

&lt;p&gt;Next: "find the traffic spikes in the last two weeks and explain the biggest ones". Claude calls &lt;code&gt;find_traffic_spikes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;How a spike is detected matters, so here's the method. Every hour is compared with the same hour of the week in earlier weeks, so a quiet Sunday night and a busy Monday morning each have their own baseline. An hour counts as a spike when it has at least 10 extra pageviews and is at least 50% above normal. Then each spike's causes are ranked: which source, landing page and event rose above &lt;em&gt;their own&lt;/em&gt; normal level.&lt;/p&gt;

&lt;p&gt;Here's one from my site (trimmed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-08T22:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pageviews_above_baseline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"causes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"google.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"lift"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"share_of_spike"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"lift"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/docs/install"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"lift"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"likely_bot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pageviews"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"browser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Chrome"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"os"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Linux"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On a dashboard, that hour looks like a nice burst of Google traffic. In fact it was 28 pageviews in 9 seconds, all Chrome on Linux: a crawler with a Google referrer. The spike's summary says plainly not to count it as a marketing win, which is exactly the mistake I'd have made by eyeballing the chart.&lt;/p&gt;

&lt;p&gt;The biggest real spike was on Oct 5: +32 pageviews in one hour, 98% of it direct traffic landing on the homepage and the live demo. "Direct" is the unhelpful answer: those visits came from somewhere, I just hadn't tagged the link. Which leads to the third question.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. "Did my post bring anyone?"
&lt;/h2&gt;

&lt;p&gt;The fix for "it was all direct" is to tag every link you share. You can ask Claude to do it as part of writing the post:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I'm posting this on Reddit, make me a tracked link to the homepage."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It calls &lt;code&gt;create_tracked_link&lt;/code&gt;, which returns a UTM-tagged URL and logs the campaign so later visits and signups are credited to it. A few days later:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How did my Reddit post do?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;get_campaign_results&lt;/code&gt; answers with real numbers. My launch-week Reddit post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"campaign"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reddit-launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"visitors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"converted_visitors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"first_visit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-04T03:47:23Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"last_visit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-04T18:52:36Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Twelve visitors over about 15 hours and nothing after that. That's humbling, but it's useful: a Reddit post's life is about a day, so judge it the next day and move on.&lt;/p&gt;

&lt;p&gt;The same query showed me something worse: five tracked links I'd created on Oct 6 had &lt;strong&gt;zero&lt;/strong&gt; visits. Those posts either never went out or were removed by moderators. I wouldn't have noticed without asking.&lt;/p&gt;

&lt;p&gt;Two more habits make this loop work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Log what you do.&lt;/strong&gt; When you publish, deploy or send an email, ask Claude to add an annotation ("record that I posted on dev.to"). Spikes list any annotation from the 24 hours before them, so the cause sits next to the jump.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask what to do next.&lt;/strong&gt; &lt;code&gt;get_growth_actions&lt;/code&gt; ranks channels and pages by what converted and suggests what to repeat. It's only as good as your tagging, which is another reason to tag everything.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'd tell myself a month ago
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ask questions, don't stare at charts.&lt;/strong&gt; "Why did X happen?" gets a ranked answer; a chart gets a shrug.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assume spikes are bots until shown otherwise.&lt;/strong&gt; One in my top three was.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag every link you share.&lt;/strong&gt; "Direct" was 76% of my visitors, and most of it is unexplained because I didn't.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expect launch traffic to decay within days.&lt;/strong&gt; Plan the next thing before the launch, not after.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;You can browse the live dashboard for my own site, with the same data as above, no signup: &lt;a href="https://measuremy.site/share/measuremy.site?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=devto-spike-tutorial" rel="noopener noreferrer"&gt;measuremy.site/share/measuremy.site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To connect your own site, the &lt;a href="https://measuremy.site/guides/claude-code-analytics?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=devto-spike-tutorial" rel="noopener noreferrer"&gt;Claude Code setup guide&lt;/a&gt; has the one-sentence prompt. There's a 30-day free trial with no card, then paid plans.&lt;/p&gt;

&lt;p&gt;If you try it, I'd like to hear one thing: did the install work first time in your agent? And what would you want to ask about your own traffic that this can't answer yet?&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>analytics</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I replaced my analytics dashboard with an MCP server on Cloudflare Workers</title>
      <dc:creator>ImageAPI AI</dc:creator>
      <pubDate>Tue, 06 Oct 2026 17:55:06 +0000</pubDate>
      <link>https://dev.to/imageapi_ai_060a84ea83609/i-replaced-my-analytics-dashboard-with-an-mcp-server-on-cloudflare-workers-4o85</link>
      <guid>https://dev.to/imageapi_ai_060a84ea83609/i-replaced-my-analytics-dashboard-with-an-mcp-server-on-cloudflare-workers-4o85</guid>
      <description>&lt;p&gt;Open source- &lt;a href="https://github.com/developeron29/agentlytics-mcp" rel="noopener noreferrer"&gt;https://github.com/developeron29/agentlytics-mcp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I kept doing the same loop: open an analytics dashboard, stare at a chart, then paste numbers into my coding agent and ask "so what should I do next?". The agent was the part doing the thinking, and the dashboard was just a slow way to feed it data.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://github.com/developeron29/agentlytics-mcp" rel="noopener noreferrer"&gt;agentlytics-mcp&lt;/a&gt;: cookieless analytics for one website, with an &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;MCP&lt;/a&gt; server built in. Claude Code, Cursor or Codex connect to it and query the traffic directly. It runs on your own Cloudflare account (one Worker plus a D1 database), and it's MIT licensed.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it looks like in practice
&lt;/h3&gt;

&lt;p&gt;You ask questions in plain words:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Why did traffic jump yesterday?"&lt;/li&gt;
&lt;li&gt;"Where do people drop off between the homepage and signup?"&lt;/li&gt;
&lt;li&gt;"What's working, and what should I post next?"&lt;/li&gt;
&lt;li&gt;"Make a tracked link for my Reddit post, and check how it did next week."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent picks from 20 tools (&lt;code&gt;get_overview&lt;/code&gt;, &lt;code&gt;find_traffic_spikes&lt;/code&gt;, &lt;code&gt;explain_spike&lt;/code&gt;, &lt;code&gt;query_visits&lt;/code&gt;, &lt;code&gt;create_funnel&lt;/code&gt;, &lt;code&gt;create_tracked_link&lt;/code&gt;, &lt;code&gt;get_campaign_results&lt;/code&gt; and more) and answers with real numbers.&lt;/p&gt;

&lt;h3&gt;
  
  
  The architecture: one Worker, four jobs
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/t.js&lt;/code&gt;&lt;/strong&gt;: a tracker of about 1 KB. It counts pageviews (including SPA navigation) and custom events from &lt;code&gt;agentlytics.track("signup")&lt;/code&gt; or a &lt;code&gt;data-agentlytics-event&lt;/code&gt; attribute.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/collect&lt;/code&gt;&lt;/strong&gt;: takes the hit, drops bots, derives the visitor id, and writes a row to D1.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/mcp&lt;/code&gt;&lt;/strong&gt;: MCP as JSON-RPC over HTTP, behind a bearer key. I wrote it by hand, so the project has no runtime dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An hourly cron&lt;/strong&gt;: rolls events up into hourly totals, runs spike detection, and deletes raw events after 400 days.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Cookieless visitor counting
&lt;/h3&gt;

&lt;p&gt;There are no cookies and nothing is stored in the browser. To count unique visitors without tracking anyone, the visitor id is a two-step HMAC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;hmacHex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HASH_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;DAY_MS&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;visitor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;hmacHex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;|&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;|&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ua&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The salt changes every day, so the same person gets a new id tomorrow, and the IP and user agent themselves are never stored. Only the browser and OS names and the country Cloudflare reports are kept.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spike detection an agent can explain
&lt;/h3&gt;

&lt;p&gt;"Traffic is up" isn't useful. "Traffic is up because of a Hacker News link to /blog/foo" is. Every hour, the cron:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Compares each hour's pageviews with the &lt;strong&gt;median of the same hour-of-week over the previous 4 weeks&lt;/strong&gt; (or the same hour-of-day over the last 7 days for young sites).&lt;/li&gt;
&lt;li&gt;Uses the &lt;strong&gt;median absolute deviation&lt;/strong&gt; as the scale and flags hours with z ≥ 4 &lt;em&gt;and&lt;/em&gt; a minimum absolute lift, so tiny sites don't get alerts for 3 extra visits.&lt;/li&gt;
&lt;li&gt;Merges consecutive flagged hours into one spike, then &lt;strong&gt;attributes the excess&lt;/strong&gt; by comparing every source, page and event against its own baseline. Each cause gets a lift, a lift % and a share of the spike.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Annotations ("deployed v2", "posted on Reddit") made in the 24 hours before a spike show up next to it. When the agent publishes something through a tracked link and logs an annotation, the next spike explains itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;There's a Deploy to Cloudflare button that asks for three settings (your domain and two random keys). Or do it by hand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx wrangler d1 create agentlytics-mcp
npx wrangler secret put SITE_DOMAIN
npx wrangler secret put HASH_SECRET
npx wrangler secret put MCP_READ_KEY
npm run deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then connect your agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--scope&lt;/span&gt; user &lt;span class="nt"&gt;--transport&lt;/span&gt; http agentlytics https://YOUR-WORKER/mcp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer YOUR_MCP_READ_KEY"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or point your coding agent at the repo's &lt;code&gt;AGENTS.md&lt;/code&gt; and let it do all of the above.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limits
&lt;/h3&gt;

&lt;p&gt;One site per deploy, no dashboard (by design), and spike detection needs a few days of data before it's useful.&lt;/p&gt;

&lt;p&gt;If you'd rather not run it, I also run a hosted version, &lt;a href="https://measuremy.site" rel="noopener noreferrer"&gt;measuremy.site&lt;/a&gt;, with a dashboard, alerts and multi-site support. The repo has the same MCP tools.&lt;/p&gt;

&lt;p&gt;I'd love feedback, especially on the tool design: what would you want to ask your analytics that this can't answer?&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>cloudflare</category>
      <category>analytics</category>
      <category>privacy</category>
    </item>
  </channel>
</rss>
