How do I tell seasonality from a real SEO decline?
Short answer
Compare against the same weeks last year rather than the preceding period, then check whether category demand moved with you. If impressions fell while your position and CTR held, demand contracted and your performance didn't. Seasonality shows up as impressions falling with everything else stable. A real decline shows up as position or CTR moving while demand holds.
Period-over-period comparison invents most declines
Comparing this quarter to last quarter compares two different points in an annual cycle. If your category peaks in September, an October-versus-September read shows a decline every year and none of it means anything.
Year-over-year is the only comparison that holds the seasonal position constant. Use it as the primary read and keep period-over-period as a secondary signal for detecting sudden events.
Separate demand from performance
The distinction that settles this: impressions measure demand, position and CTR measure your performance. Seasonality moves the first and leaves the second alone.
| Impressions | Position | CTR | Diagnosis |
|---|---|---|---|
| Down | Held | Held | Demand contraction. Seasonal or category. Nothing broke. |
| Held | Down | Any | Real ranking loss. Competitive or technical. |
| Held | Held | Down | SERP composition changed around you. |
| Down | Down | Any | Both at once. Separate them before acting. |
The first row is the one teams misread most often, because the traffic chart looks identical to a genuine problem and the response to it is completely different.
Build the seasonal baseline properly
One year of history isn't enough to establish a pattern, since a single prior year could itself have been anomalous.
Pull three years of monthly impressions where available and compute the average share of annual volume each month carries. That gives you an expected shape. Then compare this year's month against its expected share rather than against the raw prior-year number.
Two refinements worth making:
Index rather than compare absolutes. If you grew 30% year over year, a flat month is actually a decline relative to your trajectory. Indexing to your own growth rate catches that.
Check the category, not just yourself. Your own history can't tell you whether the whole category contracted or you lost share within a stable one. Pull search volume trend for your head terms and compare the direction.
Read your movement against the category
Once you have your movement and the category's movement side by side:
Category down, you down proportionally. Seasonality or a demand shift. No action beyond forecasting.
Category flat, you down. A real decline. Investigate properly using Which pages and queries explain most of my organic decline?.
Category down, you down more. Both, and you need to size each. Compute your share of category volume in both periods. If share fell too, you have a real decline sitting inside a seasonal one.
Category up, you flat. The most easily missed. Your chart looks stable and you lost share while demand grew.
That last case is why "we held steady" is not automatically good news.
The structural decline that looks seasonal
There's a pattern now that mimics seasonality closely enough to fool a year-over-year comparison: an AI surface starting to answer a query category directly.
The signature is impressions holding or rising while clicks fall on informational queries specifically, with commercial queries unaffected. Pew Research found that when an AI summary appears, users click a source link in only about 1% of visits, and our own state of AI search research, covering more than 22,000 answers, found Google AI Mode returns a citation-rich answer in 97.4% of matched B2B queries.
This is not seasonal and it does not reverse next quarter. Split your year-over-year comparison by intent bucket before concluding anything, because a blended view will show an informational collapse and a commercial hold as one moderate decline that looks cyclical.
Automate the seasonal baseline
The obstacle is that seasonal analysis needs history, and history is exactly what a spreadsheet rebuilt each quarter lacks.
GSC Page Performance Summary returns the daily series per page, and Top Keywords for Site supplies the query-level detail, so both halves come from one run. Get Visibility Events adds month-over-month AI visibility movement, which is the series that distinguishes a structural shift from a cyclical one.
workflow-memory is what turns this into a baseline. Because the agent reads outputs from its own prior successful runs, the seasonal shape accumulates automatically rather than depending on anyone maintaining a reference file.

A monthly agent:
Start (schedule, 1st of month) → GSC Top Keywords for Site (this month, same month last year, and two years prior) → Get Visibility Events → workflow-memory (retrieve prior runs to extend the seasonal series) → Code (compute expected share of annual volume for this month, index actual against expected, split by intent bucket, and compare your movement against category direction) → Conditional (if under 24 months of history, report as provisional rather than asserting a seasonal pattern) → Prompt LLM (state whether the movement is seasonal, real, or both, with the share calculation shown) → Excel export → Send Email to the SEO lead.
The Conditional on history depth matters more than it looks. Declaring something seasonal on twelve months of data is a guess dressed as an analysis, and encoding the requirement stops that happening under reporting pressure.
FAQ
Related answers
- How do I test whether an organic lift was real and not seasonal or brand-driven?
- Which pages and queries explain most of my organic decline?
- How do I find the most likely cause of a traffic anomaly?
- How do I know whether a recovery came from our changes or the market?
Want a seasonal baseline that builds itself from your own history? Start a free Analyze AI trial and connect Search Console.
