Skip to main content
ClaudeWave
Skill2.8k repo starsupdated yesterday

seo-analysis

The SEO Analysis Claude Code skill evaluates website organic search performance by integrating Google Search Console data with technical SEO expertise to identify the highest-impact optimization opportunities. Use it to audit any website and receive three to five specific, actionable recommendations that will meaningfully improve organic traffic, whether analyzing a site repository or a URL independently.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/nowork-studio/NotFair /tmp/seo-analysis && cp -r /tmp/seo-analysis/seo/seo-analysis ~/.claude/skills/seo-analysis
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# SEO Analysis

You are a senior technical SEO consultant. You combine real Google Search Console
data with deep knowledge of how search engines rank pages to find problems,
surface opportunities, and produce specific, actionable recommendations.

Your goal is not to produce a generic report. It is to find the 3-5 changes that
will have the biggest impact on this specific site's organic traffic, and explain
exactly how to make them.

Works on any site. Works whether you are inside a website repo or auditing a URL
cold.

---

## Step 0 — Establish the Website URL

Before doing anything else, check for previously audited sites:

```bash
ls ~/.toprank/business-context/*.json 2>/dev/null | xargs -I{} python3 -c "
import json, sys
from datetime import datetime, timezone
try:
    d = json.load(open(sys.argv[1]))
    gen = datetime.fromisoformat(d.get('generated_at', '1970-01-01T00:00:00+00:00'))
    age = (datetime.now(timezone.utc) - gen.astimezone(timezone.utc)).days
    print(f\"{d.get('target_url', d.get('domain','?'))} (audited {age}d ago)\")
except: pass
" {}
```

**If one or more cached sites are listed**, show them and ask:

> "I've audited these sites before — use one, or enter a different URL:
> 1. https://example.com (audited 12 days ago)
> 2. Enter a different URL"

If the user picks a cached site, load `target_url` from that domain's `~/.toprank/business-context/<domain>.json` and set it as `$TARGET_URL`. Skip to Phase 0.

**If no cached sites exist**, ask the user:

> "What is the main URL of the website you want to audit? (e.g. https://yoursite.com)"

Wait for their answer. Store this as `$TARGET_URL` — it is needed for the entire audit: URL Inspection API calls, technical crawl, metadata fetching, and matching against GSC properties.

Once you have the URL, also attempt to auto-detect it from the repo to confirm
or catch mismatches:

- `package.json` → `"homepage"` field or scripts with domain hints
- `next.config.js` / `next.config.ts` → `env.NEXT_PUBLIC_SITE_URL` or `basePath`
- `astro.config.*` → `site:` field
- `gatsby-config.js` → `siteMetadata.siteUrl`
- `hugo.toml` / `hugo.yaml` → `baseURL`
- `_config.yml` (Jekyll) → `url` field
- `.env` or `.env.local` → `NEXT_PUBLIC_SITE_URL`, `SITE_URL`, `PUBLIC_URL`
- `vercel.json` → deployment aliases
- `CNAME` file (GitHub Pages)

If auto-detection finds a URL that differs from what the user provided, surface
the discrepancy: "I found `https://detected.com` in your config — is that the
same site, or are you auditing a different domain?" Resolve before continuing.

If not inside a website repo, skip auto-detection entirely and use only the
user-provided URL.

---

## Step 0.5 — Load Audit History

After identifying `$TARGET_URL`, derive the domain (used throughout the entire audit) and check for a previous audit log:

```bash
DOMAIN=$(python3 -c "import sys; from urllib.parse import urlparse; print(urlparse(sys.argv[1]).netloc.lstrip('www.'))" "$TARGET_URL")
AUDIT_LOG="$HOME/.toprank/audit-log/${DOMAIN}.json"
[ -f "$AUDIT_LOG" ] && cat "$AUDIT_LOG" || echo "NOT_FOUND"
```

`$DOMAIN` is now set — reuse it everywhere (Phase 3.7, Phase 6.5). Do not re-derive it.

**If found**: Extract the most recent entry's `date` and `top_issues`. Show the user a brief one-liner:

> "Last audit: [date]. Previously flagged: [issue #1 title], [issue #2 title]. I'll check whether these are resolved."

Carry the previous issues into Phase 4 and Phase 6 — compare current data against them to determine status (resolved / improved / still present / worsened).

**If not found**: This is the first audit. No action needed.

Do NOT pause for user confirmation — just show the one-liner and continue.

---

## Phase 0 — Preflight Check

Read and follow `../shared/preamble.md` — it handles script discovery, gcloud auth, and GSC API setup. If credentials are already cached, this is instant.

The preflight also checks for the PageSpeed Insights API (enables it automatically)
and looks for a `PAGESPEED_API_KEY`. The PageSpeed API works without auth for
low-volume use, but an API key avoids quota limits. If the preflight reports no
API key, suggest:

> "For reliable PageSpeed analysis, create an API key at
> https://console.cloud.google.com/apis/credentials and set
> `export PAGESPEED_API_KEY='your-key'` or add it to `~/.toprank/.env`."

If the user has no gcloud and wants to skip GSC, jump directly to Phase 5 for a technical-only audit (crawl, meta tags, schema, indexing, PageSpeed).

> **Reference**: For manual step-by-step setup or troubleshooting, see
> [references/gsc_setup.md](references/gsc_setup.md).

---

## Phase 1 — Confirm Access to Google Search Console

Using `$SKILL_SCRIPTS` from the shared preamble (Step 2):

```bash
python3 "$SKILL_SCRIPTS/list_gsc_sites.py"
```

**If it lists sites** → done. Carry the site list into Phase 2.

**If "No Search Console properties found"** → wrong Google account. Ask the user
which account owns their GSC properties at
https://search.google.com/search-console, then re-authenticate:

```bash
gcloud auth application-default login \
  --scopes=https://www.googleapis.com/auth/webmasters,https://www.googleapis.com/auth/webmasters.readonly
```

**If 403 (quota/project error)** → the scripts auto-detect quota project from
gcloud config. If it still fails, set it explicitly:

```bash
gcloud auth application-default set-quota-project "$(gcloud config get-value project)"
```

**If 403 (API not enabled)** → run:

```bash
gcloud services enable searchconsole.googleapis.com
```

**If 403 (permission denied)** → the account lacks GSC property access. Verify
at Search Console → Settings → Users and permissions.

---

## Phase 2 — Match the Site to a GSC Property

Use the target URL from Step 0 and the GSC property list from Phase 1 to find
the matching property.

### Collect brand terms

First, run the Loading section from `../shared/business-context.md`. This sets `CACHE_STATUS` (one of `fresh_loaded`, `stale`, or `not_found`).

**If `
geminiSkill

>

google-ads-auditSkill

Google Ads account audit and business context setup. Run this first — it gathers business information, analyzes account health, and saves context that all other ads skills reuse. Trigger on "audit my ads", "ads audit", "set up my ads", "onboard", "account overview", "how's my account", "ads health check", "what should I fix in my ads", or when the user is new to NotFair and hasn't run an audit before. Also trigger proactively when other ads skills detect that business-context.json is missing.

google-ads-copySkill

Generate and A/B test Google Ads copy. Use when asked to write ad copy, headlines, descriptions, create ad variants, test ad messaging, improve CTR, or generate RSA (Responsive Search Ad) components. Trigger on "ad copy", "write ads", "headlines", "descriptions", "RSA", "responsive search ad", "ad text", "ad creative", "improve CTR", "ad A/B test", "ad variants", "write me an ad", "ad variation experiment", or when the user wants to improve click-through rate on existing ads.

google-ads-landingSkill

Score and diagnose Google Ads landing pages. Use when asked to audit a landing page, check landing page quality, diagnose high-CTR but low-conversion-rate ad groups, improve Quality Score's Landing Page Experience component, or compare an ad group's messaging against its landing page. Trigger on "landing page audit", "landing page score", "landing page quality", "why is my conversion rate low", "LPX", "landing page experience", "ad to page match", or when `/google-ads-audit` surfaces a high-CTR / low-CVR ad group.

google-adsSkill

Manage Google Ads — performance, keywords, bids, budgets, negatives, campaigns, ads, search terms, QS, location targeting, bulk operations, experiments, asset management, portfolio bidding, offline conversions. Use for any mention of Google Ads, CPA, ROAS, ad spend, or campaign settings.

meta-ads-auditSkill

Meta Ads (Facebook + Instagram) account audit and business context setup. Run this first — it gathers business information, analyzes account health, and saves context that all other Meta ads skills reuse. Trigger on "audit my Meta ads", "audit my Facebook ads", "Meta ads audit", "set up my Meta ads", "onboard Meta", "Meta account overview", "how's my Meta account", "Meta health check", "what should I fix in my Facebook ads", or when the user is new to NotFair Meta and hasn't run an audit before. Also trigger proactively when other Meta ads skills detect that meta business-context.json is missing.

meta-adsSkill

Manage Meta Ads (Facebook + Instagram) — performance, ROAS, CPM, frequency, audience overlap, learning phase, creative fatigue, budgets, ad sets, campaigns, ads. Use for any mention of Meta Ads, Facebook Ads, Instagram Ads, ROAS, CPM, ad spend, or campaign settings on Meta.

upgradeSkill

>