<p>A traffic spike on a small website can be surprisingly difficult to explain.</p>
<p>On October 28, my text graphics tool, <a href="https://gummytype.com" rel="noopener noreferrer">GummyType</a>, received a sudden increase in visits. I hadn't run a campaign or a batch test.</p>
<p>I used three sources to investigate:</p>
<ul>
<li>Vercel Web Analytics.</li>
<li>First-party event records stored in Upstash Redis.</li>
<li>Vercel request logs and firewall data.</li>
</ul>
<p>Each answered a different question.</p>
<h2>
- Separate visitors, sessions, events, and requests
</h2>
<p>A Vercel snapshot showed 111 visitors and 236 page views over the previous 24 hours.</p>
<p>My event logs covered a separate, narrower window: approximately 17:32–17:53, Beijing time.</p>
<p>That window contained:</p>
<div class="table-wrapper-paragraph"><table>
<thead>
<tr>
<th>Metric</th>
<th>Count</th>
</tr>
</thead>
<tbody>
<tr>
<td>Session IDs</td>
<td>81</td>
</tr>
<tr>
<td>Page-view events</td>
<td>177</td>
</tr>
<tr>
<td>Sessions containing only one page-view event</td>
<td>55</td>
</tr>
<tr>
<td>Sessions with a completed PNG export</td>
<td>2</td>
</tr>
</tbody>
</table></div>
<p>These numbers describe different things.</p>
<p>My session ID is stored in <code>sessionStorage</code> and expires after 30 minutes without a recorded event. It isn't a persistent identifier for a person.</p>
<p>Likewise, CDN requests include resources such as images and scripts. Thousands of requests don't mean thousands of visitors.</p>
<h2>
- Read “direct” as missing attribution
</h2>
<p>My source classification includes this check:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight typescript"><code><span class="k">if </span><span class="p">(</span><span class="o">!</span><span class="nx">referrer</span><span class="p">)</span> <span class="k">return</span> <span class="dl">"</span><span class="s2">direct</span><span class="dl">"</span><span class="p">;</span>
</code></pre>
</div>
<p>That is the meaning of direct <strong>in my implementation</strong>: no referring page was available when the session started.</p>
<p>It doesn't identify a channel.</p>
<p>A copied link, an app opening a URL, or automation navigating directly could all produce missing attribution. The label alone cannot distinguish them.</p>
<h2>
- Check browser information separately
</h2>
<p>The strongest additional clue came from Vercel's browser breakdown.</p>
<p>A later snapshot classified 44 visitors, approximately 40%, as using WeChat.</p>
<p>Two sampled homepage requests contained different WeChat versions in their user-agent strings:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight plaintext"><code>MicroMessenger/8.0.62
MicroMessenger/8.0.79
</code></pre>
</div>
<p>This supported WeChat usage as an explanation for part of the traffic.</p>
<p>It did not reveal the original message, group, or article. User-agent information is also a clue rather than proof of a human visitor.</p>
<p>Browser type and referring source answer different questions. A visit can be classified as WeChat in one report and direct in another without contradiction.</p>
<h2>
- Separate suspicious browsing from attack evidence
</h2>
<p>Some sessions switched pages rapidly. One recorded 17 page views in roughly a minute.</p>
<p>The firewall also showed requests for paths such as:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight plaintext"><code>/.env
/wp-admin/install.php
/phpinfo.php
</code></pre>
</div>
<p>Those probes were suspicious, but I couldn't establish that they belonged to the same activity as the analytics spike.</p>
<p>At the time I checked server health, Vercel reported 0% function errors and 0% timeouts.</p>
<p>Another distinction matters here: several GET requests close together can include framework prefetching. They don't necessarily represent someone viewing every requested page. Client-side page-view events provide different evidence.</p>
<h2>
- Identify what the instrumentation cannot answer
</h2>
<p>My export flow records an attempt ID across stages such as:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight plaintext"><code>png_export_started
png_generated
png_export_completed
</code></pre>
</div>
<p>That helps distinguish an export attempt from a page visit.</p>
<p>However, ordinary text edits and style changes weren't fully tracked. A session with one page-view event could still have spent time experimenting without exporting.</p>
<p>Also, a completed export event reports the browser delivery outcome. It doesn't independently verify that a file was saved to disk.</p>
<h2>
The conclusion remains incomplete
</h2>
<p>I found evidence of WeChat visits, rapid browsing, and unrelated-looking vulnerability probes.</p>
<p>I did not find enough evidence to label the entire spike as organic growth or an attack.</p>
<p>The next useful instrumentation step is a once-per-session interaction event for the first text or style edit, without collecting the user's text.</p>
<p>That would make the funnel clearer:<br>
</p>
<div class="highlight js-code-highlight">
<pre class="highlight plaintext"><code>Page opened → Tool edited → Export completed
</code></pre>
</div>
<p>The investigation helped me narrow the possibilities. It also exposed where my data stops being able to answer the question.</p>
<p><em>Disclosure: I used AI assistance to analyze the data and draft this article. The figures describe snapshots collected on October 28, 2026.</em></p>
Original source
Read the original article on dev.to