On this page
Wire stores Google Search Console data in a local SQLite database. Every content decision (what to rewrite, what to merge, what to create) references this data. The database is the foundation that makes Wire's SEO automation possible.
How Data Gets In
python -m wire.chief data
python -m wire.chief data --force # Re-fetch even if data is fresh
The data command walks every topic in your site, lists every content page, and fetches keyword metrics from the GSC API. For each page, Wire stores impressions, clicks, average position, and CTR for every keyword the page ranks for.
Data is stored in three tables:
| Table | What it holds |
|---|---|
| Content | Page slug, topic, title. One row per page |
| Keyword | Keyword text, deduplicated across all pages |
| Snapshot | Page-keyword metrics: impressions, clicks, position, CTR, date |
Fresh data (under 28 days old) is skipped on the next run unless you pass --force. This prevents unnecessary API calls during frequent workflow runs.
What the Database Enables
Overlap Detection
find_overlaps() runs a SQL self-join on the Snapshot table to find page pairs sharing keywords. For each pair it computes shared keyword count, overlap ratio, traffic share, and total shared impressions.
The deduplication system uses these metrics to classify each overlap and decide whether to merge, differentiate, or ignore.
Opportunity Scoring
Every keyword is scored with impressions * (1-CTR). A keyword with 500 impressions and 2% CTR scores 490, meaning high demand that your page is not capturing. The reword system uses these scores to prioritize which pages get rewritten first.
Content Gap Detection
find_content_gaps() finds keywords ranked by 3+ pages where no page ranks well (best position above 20) and no page slug matches the keyword. These represent search demand with no focused content.
Dead Page Detection
find_dead_pages() identifies pages with impressions below the site median threshold and older than 180 days. Combined with overlap data, Wire determines whether other pages already cover the dead page's keywords, making it safe to archive.
Keyword Ownership
keyword_ownership_batch() tells Wire which pages in a topic own specific keywords. This prevents the enrich pipeline from adding content to the wrong page when another page already ranks better for that keyword.
Trending Keywords
trending_keywords() finds the highest-impression keywords across all topics. This feeds into the weekly market report to ensure reports prioritize topics with actual search demand.
Database Location
The database lives at {site_dir}/.wire/gsc.db, in the site root, not in the Wire installation. Each site has its own database. The .wire/ directory is gitignored by default.
CTR in the AI Era
Traditional CTR benchmarks (position 1 = 28%, position 2 = 15%) are from before AI Overviews, ChatGPT Search, and Perplexity started intercepting search traffic. For niche B2B sites in 2026, real CTR is roughly one-tenth of published benchmarks.
| Position | Traditional CTR | AI-era CTR (2026) |
|---|---|---|
| 1 | 28% | 2.8% |
| 2 | 15% | 1.5% |
| 3 | 10% | 1.0% |
| 4-5 | 5-7% | 0.5-0.7% |
| 6-10 | 2-4% | 0.2-0.4% |
This means impressions are a stronger signal than clicks for niche sites. Wire's opportunity scoring accounts for this by weighting impressions, not clicks.
Why Local-First Beats API-On-Demand
Most SEO tools query Google's API on every interaction. Wire downloads the data once, stores it locally, and runs every analysis from the database. Three advantages compound from this architecture.
Speed. A SQL query takes milliseconds. An API call takes 2-5 seconds. When Wire runs find_overlaps() across 142 pages, it completes in under a second. An API-on-demand tool would make 142 separate requests, over 5 minutes of wall time, plus rate limit pauses.
Cost control. GSC's API has a daily quota. Tools that query on every user interaction burn through quota fast. Wire's quota usage is fixed: one fetch cycle per topic, regardless of how many analyses you run afterward. The data command hits the API once. Every subsequent command (audit, deduplicate, reword, enrich) reads from the local database with zero additional calls.
Reproducibility. The local database is a snapshot. Two analyses run on the same snapshot produce identical results. This matters for debugging and for comparing changes across workflow cycles. When you run audit on Monday and audit on Friday, the data difference is explicit: one snapshot versus another, not random API variance.
The approach mirrors what large SEO teams do manually with spreadsheets: download the data, analyze locally, act on the analysis. Wire automates the analysis step.
The Impression-First Thesis
The traditional SEO playbook optimizes for clicks. Wire optimizes for impressions. The reasoning is structural, not contrarian.
Seer Interactive's analysis of AI Overview impact found that AI Overviews reduce organic CTR by 34-61% depending on query type. Ahrefs' December 2025 study measured a 58% CTR reduction at position one when an AI Overview is present. Position one with a 2.8% CTR means 97.2% of impressions never become clicks.
Click-based scoring in this environment is misleading. A keyword with 500 impressions and 5 clicks looks like a 1% CTR failure. But that keyword represents 500 people who searched for your topic. 495 of them saw an AI Overview that answered their question. The 5 who clicked through are the ones the AI Overview failed to satisfy, and they are disproportionately valuable because they wanted more than a summary.
Wire's opportunity formula, impressions * (1-CTR), captures this. It scores 500 impressions at 1% CTR as 495. It scores 50 impressions at 10% CTR as 45. The first keyword has 11x more untapped demand. That is where content investment should go.
This thesis has a testable prediction: sites that optimize for impression-weighted keywords will outperform sites that optimize for click-weighted keywords over 6-12 months, because impression-weighted optimization targets the queries where AI Overviews intercept the most traffic, and those AI Overviews will change, fail, or lose user trust over time.
Authentication
Wire uses Google OAuth for GSC access. You need GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in your .env file (Desktop app OAuth client from Google Cloud Console), then you run python -m wire.chief gsc-auth once. That command opens your browser for consent and writes token.json next to wire.yml. Wire auto-refreshes the token on every subsequent call. See the getting started guide for the full walkthrough.