The Mine Works
Browse on Apify
Automate SEO Research and Content Strategy with Claude and Google Trends Pro
← All posts
tutorial September 15, 2025 · 10 min read

Automate SEO Research and Content Strategy with Claude and Google Trends Pro

Use Apify's Google Trends Pro actor with Claude to build an autonomous content calendar generator, keyword opportunity finder

Try the scraper

The actor referenced in this article is live on Apify. Pay only for results delivered.

Open on Apify →

Google Trends data tells you what people are searching for right now, and how that interest has shifted over time. Claude can interpret that data and turn it into strategy. Combining the two gives you a content research assistant that runs automatically — surfacing keyword opportunities, predicting seasonal demand, and generating a content calendar aligned with actual search behavior.

TL;DR: Five automation patterns combining Google Trends Pro with Claude: keyword opportunity scoring (rising trend + Claude strategy = ranked content backlog), seasonal calendar generation (monthly interest patterns → 12-month editorial plan), breakout alert detection (spike > 1.4x baseline triggers Claude interpretation), geographic market expansion analysis, and competitive intelligence briefs. Full weekly pipeline costs under $0.75.

This guide walks through five real automation patterns, each solving a specific problem that content teams and SEO practitioners face every week.

The Core Setup

pip install apify-client anthropic pandas python-dotenv
from apify_client import ApifyClient
import anthropic
import os
import json

apify = ApifyClient(os.environ["APIFY_TOKEN"])
claude = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

def fetch_trends(keywords: list[str], timeframe: str = "today 12-m", geo: str = "US") -> list[dict]:
    run = apify.actor("themineworks/google-trends-pro").call(run_input={
        "keywords": keywords,
        "timeframe": timeframe,
        "geo": geo,
        "includeRelatedQueries": True,
        "includeInterestByRegion": True,
    })
    return list(apify.dataset(run["defaultDatasetId"]).iterate_items())

Pattern 1: Keyword Opportunity Finder

Your content team has a backlog of potential topics. This pipeline scores each one against actual search trend data and Claude’s strategic judgment, returning a ranked list with rationale.

def score_keyword_opportunities(candidate_keywords: list[str], your_niche: str) -> list[dict]:
    """Rank keywords by opportunity score using trends data + Claude analysis."""
    
    # Fetch in batches of 5 (Google Trends limit per comparison)
    all_trend_data = []
    for i in range(0, len(candidate_keywords), 5):
        batch = candidate_keywords[i:i+5]
        data = fetch_trends(batch, timeframe="today 5-y")
        all_trend_data.extend(data)
    
    # Build data summary for Claude
    keyword_summaries = []
    for item in all_trend_data:
        iot = item.get("interest_over_time", [])
        if not iot:
            continue
        
        values = [p["value"] for p in iot]
        avg = sum(values) / len(values)
        recent_avg = sum(values[-12:]) / 12  # Last 12 weeks
        historical_avg = sum(values[:12]) / 12  # First 12 weeks
        trend_direction = "rising" if recent_avg > historical_avg * 1.1 else ("falling" if recent_avg < historical_avg * 0.9 else "stable")
        
        rising_queries = [q["query"] for q in item.get("relatedQueries", {}).get("rising", [])[:5]]
        
        keyword_summaries.append({
            "keyword": item["keyword"],
            "avg_interest": round(avg, 1),
            "trend_direction": trend_direction,
            "recent_vs_historical": round(recent_avg / max(historical_avg, 1), 2),
            "rising_related_queries": rising_queries,
        })
    
    # Ask Claude to score and rank
    response = claude.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=2000,
        messages=[{
            "role": "user",
            "content": f"""You are an SEO strategist for a {your_niche} website. Analyze these keyword trends and score each for content opportunity.

KEYWORD DATA:
{json.dumps(keyword_summaries, indent=2)}

For each keyword, provide a JSON array with:
- keyword: string
- opportunity_score: 1-10
- reasoning: 2-sentence explanation
- recommended_content_angle: specific article title or content approach
- urgency: "evergreen" | "seasonal" | "trending_now"

Score higher for: rising trends, high average interest, strong rising related queries.
Score lower for: falling trends, very low interest, too competitive.

Return only a JSON array."""
        }]
    )
    
    scored = json.loads(response.content[0].text)
    scored.sort(key=lambda x: x["opportunity_score"], reverse=True)
    return scored

# Example
candidates = [
    "apify actors", "web scraping python", "reddit data api",
    "google trends api", "job posting scraper", "threads scraper",
    "rag crawler", "data pipeline automation",
]

opportunities = score_keyword_opportunities(candidates, "web scraping and data APIs")
for item in opportunities:
    print(f"{item['opportunity_score']}/10 — {item['keyword']}: {item['recommended_content_angle']}")

Pattern 2: Seasonal Content Calendar Generator

Every niche has seasonal demand patterns. This pipeline detects your peak months from historical trends and generates a 12-month editorial calendar timed to those peaks.

def generate_seasonal_calendar(core_keywords: list[str], your_industry: str) -> str:
    """Generate a 12-month content calendar based on seasonal trend patterns."""
    
    data = fetch_trends(core_keywords, timeframe="today 5-y")
    
    # Compute monthly averages across all years
    monthly_patterns = {}
    for item in data:
        keyword = item["keyword"]
        monthly_agg = {}
        
        for point in item.get("interest_over_time", []):
            month = point["date"][5:7]  # "YYYY-MM-DD" -> "MM"
            if month not in monthly_agg:
                monthly_agg[month] = []
            monthly_agg[month].append(point["value"])
        
        monthly_patterns[keyword] = {
            month: round(sum(vals) / len(vals), 1)
            for month, vals in monthly_agg.items()
        }
    
    response = claude.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=3000,
        messages=[{
            "role": "user",
            "content": f"""You are a content strategist for a {your_industry} company.

MONTHLY SEARCH INTEREST BY KEYWORD (averaged over 5 years, 0-100 scale):
{json.dumps(monthly_patterns, indent=2)}

Create a 12-month content calendar. For each month:
1. Identify the highest-interest keywords for that month
2. Recommend 2-3 specific article titles
3. Explain the seasonal reason driving interest
4. Suggest the primary promotion channel (SEO long-tail, paid search, social)

Format as a clear month-by-month plan. Be specific with article titles — they should be actionable, searchable headlines that a writer could pick up immediately.

Start with the month that has the highest overall opportunity."""
        }]
    )
    
    return response.content[0].text

The most time-sensitive use of Trends data is catching a topic before it peaks. This script checks daily and fires an alert when a keyword’s 7-day interest jumps significantly.

from datetime import datetime

def detect_breakout_keywords(watchlist: list[str], spike_threshold: float = 1.5) -> list[dict]:
    """Detect keywords with unusual recent interest spikes."""
    
    data = fetch_trends(watchlist, timeframe="today 3-m")
    alerts = []
    
    for item in data:
        iot = item.get("interest_over_time", [])
        if len(iot) < 8:
            continue
        
        recent_values = [p["value"] for p in iot[-4:]]   # Last 4 weeks
        baseline_values = [p["value"] for p in iot[-16:-4]]  # Prior 12 weeks
        
        recent_avg = sum(recent_values) / len(recent_values)
        baseline_avg = sum(baseline_values) / len(baseline_values) if baseline_values else 1
        
        if baseline_avg > 0 and recent_avg / baseline_avg >= spike_threshold:
            ratio = recent_avg / baseline_avg
            
            # Ask Claude what the spike likely means
            rising_queries = [q["query"] for q in item.get("relatedQueries", {}).get("rising", [])[:5]]
            
            response = claude.messages.create(
                model="claude-haiku-4-5-20251001",  # Use Haiku for fast, cheap single-item analysis
                max_tokens=200,
                messages=[{
                    "role": "user",
                    "content": f"""Keyword "{item['keyword']}" has spiked {ratio:.1f}x above its 12-week baseline.
Rising related queries: {rising_queries}

In 2 sentences: What is likely driving this spike? What content opportunity does this create?"""
                }]
            )
            
            alerts.append({
                "keyword": item["keyword"],
                "spike_ratio": round(ratio, 2),
                "recent_interest": round(recent_avg, 1),
                "baseline_interest": round(baseline_avg, 1),
                "rising_related_queries": rising_queries,
                "claude_interpretation": response.content[0].text,
                "detected_at": datetime.now().isoformat(),
            })
    
    return sorted(alerts, key=lambda x: x["spike_ratio"], reverse=True)

# Run daily via cron
watchlist = ["web scraping", "apify", "reddit api", "rag pipeline", "job scraper"]
alerts = detect_breakout_keywords(watchlist, spike_threshold=1.4)

for alert in alerts:
    print(f"SPIKE: {alert['keyword']} is {alert['spike_ratio']}x above baseline")
    print(f"  {alert['claude_interpretation']}")
    print(f"  Rising queries: {alert['rising_related_queries']}")

Pattern 4: Geographic Market Expansion Analysis

Before entering a new market, understand where search demand is concentrated. This pattern identifies which countries and regions have the highest interest in your category — and asks Claude to rank expansion opportunities.

def analyze_expansion_markets(product_keywords: list[str], current_markets: list[str]) -> str:
    """Identify the best new markets to enter based on search demand."""
    
    # Fetch worldwide interest by region
    run = apify.actor("themineworks/google-trends-pro").call(run_input={
        "keywords": product_keywords[:3],  # Compare up to 3
        "timeframe": "today 12-m",
        "geo": "",  # Worldwide
        "includeInterestByRegion": True,
    })
    
    data = list(apify.dataset(run["defaultDatasetId"]).iterate_items())
    
    # Aggregate by country
    country_scores = {}
    for item in data:
        for region in item.get("interest_by_region", []):
            country = region["geoName"]
            value = region["value"]
            if country not in country_scores:
                country_scores[country] = []
            country_scores[country].append(value)
    
    avg_by_country = {c: sum(v)/len(v) for c, v in country_scores.items() if sum(v)/len(v) > 10}
    top_countries = sorted(avg_by_country.items(), key=lambda x: x[1], reverse=True)[:20]
    
    response = claude.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1500,
        messages=[{
            "role": "user",
            "content": f"""You are a market expansion strategist.

Keywords analyzed: {product_keywords}
Already in these markets: {current_markets}

Top countries by search interest (0-100 scale):
{json.dumps(dict(top_countries), indent=2)}

Identify the top 5 expansion markets NOT already in the current list. For each:
1. Country and interest score
2. Why this market is attractive
3. What localization or positioning adjustment would be needed
4. Estimated effort to penetrate (low/medium/high)

Be specific. Consider English proficiency, tech adoption, developer density, and ability to pay."""
        }]
    )
    
    return response.content[0].text

Pattern 5: Automated Competitive Intelligence Brief

Track how search interest in your category’s key players evolves week over week, and get Claude to write the narrative.

def competitive_intelligence_brief(competitors: list[str], category: str) -> str:
    """Weekly competitive landscape brief based on brand search trends."""
    
    # Get 2-year trends for all competitors
    data = fetch_trends(competitors, timeframe="today 2-y")
    
    # Extract trajectory for each competitor
    competitor_data = {}
    for item in data:
        iot = item.get("interest_over_time", [])
        if not iot:
            continue
        
        values = [p["value"] for p in iot]
        competitor_data[item["keyword"]] = {
            "current_interest": values[-1] if values else 0,
            "6_month_avg": round(sum(values[-26:]) / min(26, len(values)), 1),
            "12_month_ago": values[-52] if len(values) >= 52 else values[0],
            "2_year_trend": "rising" if values[-1] > values[0] * 1.1 else ("falling" if values[-1] < values[0] * 0.9 else "flat"),
        }
    
    response = claude.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1500,
        messages=[{
            "role": "user",
            "content": f"""Write a competitive intelligence brief for the {category} market.

COMPETITOR SEARCH INTEREST DATA:
{json.dumps(competitor_data, indent=2)}

Write a 400-word analyst brief covering:
1. Who is gaining momentum and why
2. Who is losing ground
3. What the combined data suggests about the market direction
4. Which competitor's positioning appears to be working based on trend data
5. One strategic recommendation for how to differentiate

Write as a professional analyst briefing a leadership team. Be direct and specific."""
        }]
    )
    
    return response.content[0].text

Scheduling the Pipeline

Run these automations on a schedule using cron or a simple script:

import schedule
import time

def weekly_seo_run():
    print("Running weekly SEO intelligence...")
    
    opportunities = score_keyword_opportunities([...], "your niche")
    calendar = generate_seasonal_calendar([...], "your industry")
    brief = competitive_intelligence_brief([...], "your category")
    
    # Save or email results
    with open("weekly_seo_report.md", "w") as f:
        f.write("# Weekly SEO Intelligence Report\n\n")
        f.write("## Keyword Opportunities\n\n")
        for opp in opportunities[:10]:
            f.write(f"**{opp['keyword']}** ({opp['opportunity_score']}/10): {opp['recommended_content_angle']}\n\n")
        f.write("## Content Calendar\n\n")
        f.write(calendar)
        f.write("\n\n## Competitive Brief\n\n")
        f.write(brief)

def daily_alert_run():
    alerts = detect_breakout_keywords([...], spike_threshold=1.4)
    if alerts:
        print(f"ALERT: {len(alerts)} keyword spikes detected")
        for alert in alerts:
            print(f"  {alert['keyword']}: {alert['spike_ratio']}x spike")

schedule.every().monday.at("08:00").do(weekly_seo_run)
schedule.every().day.at("09:00").do(daily_alert_run)

while True:
    schedule.run_pending()
    time.sleep(60)

Total Cost

A full weekly run across 20 keywords costs roughly:

  • Google Trends Pro (Apify): ~$0.20 (200 trend data points at PPE rates)
  • Claude Sonnet API: ~$0.40 (4-5 analysis calls, ~500 tokens each)
  • Total: under $0.75/week for automated SEO intelligence

For a team that would otherwise spend 2 hours every week on manual keyword research, that is a worthwhile trade.

Frequently Asked Questions

How do you score keyword content opportunities using Google Trends data and Claude together?

Fetch 5-year weekly trend data for each candidate keyword. Compute: average interest (demand level), recent vs. historical ratio (trajectory), and rising related queries (adjacent opportunity). Pass this structured data to Claude with your niche context and ask for an opportunity score (1-10) with a recommended content angle and urgency classification. Claude’s value is synthesizing the strategic angle — “this rising trend correlates with X developer behavior, here is the specific article title that would capture it” — not just ranking by raw trend numbers.

How do you generate a seasonal editorial calendar from Google Trends data?

Extract 5 years of weekly data for your 5-10 core keywords. Compute the average Trends value for each calendar month across all years to get a seasonal demand profile. Apply linear trend correction to separate seasonal from growth components. Pass the monthly profiles to Claude with your industry context and ask for a 12-month content calendar with specific article titles timed 6-8 weeks before each demand peak. Claude’s output turns raw seasonality data into an immediately actionable content plan.

What threshold should you use to detect a meaningful Google Trends spike?

A spike ratio of 1.4x above the 12-week baseline is a reliable threshold — it filters out normal weekly variance (typically ±15%) while catching genuine interest acceleration. Calculate: recent_4_week_avg / prior_12_week_avg ≥ 1.4. For keywords with high baseline volatility, increase the threshold to 1.6x. The spike detection is most valuable for watchlist monitoring of emerging topics — catching a breakout before it appears in keyword difficulty tools gives you a 4-8 week head start on content creation.

How do you use Google Trends to identify which new markets to enter?

Run a worldwide Interest by Region query for your 3 core category keywords. Average the regional interest scores across all keywords. Filter out markets you already operate in. Sort by interest score and overlay feasibility criteria: English proficiency (reduces localization cost), tech adoption index, and ability-to-pay proxies. Ask Claude to rank the top 10 by expansion opportunity considering these factors. This turns a list of Trends scores into a prioritized market entry roadmap in minutes.

What is the total cost of running a weekly automated SEO intelligence pipeline?

A full weekly pipeline across 20 keywords — keyword opportunity scoring, seasonal calendar generation, breakout alert detection, and competitive intelligence brief — costs approximately $0.20-0.35 in Apify Google Trends Pro credits (200-350 data points at PPE rates) and $0.30-0.50 in Claude API fees (4-6 analysis calls at Sonnet pricing). Total: under $0.75/week. For a content team that would otherwise spend 2 hours on manual keyword research, the ROI is immediate at any hourly rate.

Related Actor

Try the scraper referenced in this article — live on Apify, pay only for results.

Open google-trends-pro on Apify →