# Google Trends Bulk Compare – 1,000 Keywords on One Scale (`tgelu/google-trends-stitcher`) Actor

Compare up to 1,000 keywords in Google Trends on ONE 0–100 scale. Anchor-term stitching beats the 5-term limit; outputs stitched interest over time, peak, growth, low-confidence flags and optional volume estimates.

- **URL**: https://apify.com/tgelu/google-trends-stitcher.md
- **Developed by:** [Gelu Timoficiuc](https://apify.com/tgelu) (community)
- **Categories:** SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Trends Bulk Compare – 1,000 Keywords on One Scale

Google Trends compares only **5 keywords at a time**, and every batch is scaled 0–100 on its own, so numbers from different batches can't be compared. This Actor breaks that limit: it runs as many 5-term batches as needed, links them through shared **anchor terms**, and rescales everything onto **one common scale** (the biggest term peaks at 100).

**Use it for:** keyword research across hundreds of terms · product / brand demand comparison · content planning · market sizing · seasonality and growth screening.

### What you get per keyword

| Field | Meaning |
|---|---|
| `mean`, `peak`, `peakDate` | Average and highest interest on the shared scale |
| `growthPct` | Last quarter of the period vs first quarter |
| `timeline[]` | Every point: `raw` (Google's own batch value) and `value` (stitched) |
| `lowConfidence` | `true` when Google's raw value was < 10 (rounding noise) |
| `estimatedMonthlyVolume` | Optional: give one term's monthly search volume and every term is estimated proportionally |
| `bestBatchId`, `scaleFactor` | Audit trail of the math |

Views: **Overview** (one row per term) and **Debug**. Output mode `perTermDate` gives one row per term per date (pivot-ready CSV).

### Real sample (run on 2 Nov 2026: 12 coffee/tea terms, US, past 12 months, 6 batches)

| term | mean | peak | growth % | low confidence |
|---|---|---|---|---|
| coffee | 75.60 | 100 | -0.1 | no |
| tea | 35.55 | 45.0 | -12.3 | no |
| espresso | 9.42 | 14.50 | -17.8 | no |
| cold brew | 2.02 | 3.52 | +39.6 | no |
| dandelion coffee | 0.016 | 0.043 | -31.9 | yes |

"Dandelion coffee" is ~4,800× smaller than "coffee" and is still placed on the same scale. One Google batch can't show that, because it rounds the small term to 0.

```json
{"term":"espresso","geo":"US","timeframe":"today 12-m","mean":9.4151,"peak":14.4974,"peakDate":"2026-04-12","growthPct":-17.8,"lowConfidence":false,"bestBatchId":"A2","scaleFactor":0.144974,"timeline":[{"date":"2025-11-02","raw":51,"value":7.3937}]}
```

### How the stitching works

1. **Pass 1:** the anchor term plus 4 new terms per batch.
2. **Pass 2 (automatic, when needed):** terms are sorted by size and re-queried in overlapping "ladder" batches, so tiny terms are measured next to similar-sized terms instead of next to a giant.
3. **Scaling:** batches become a graph that shares terms. The strongest links (a maximum spanning tree) carry the scale factor `mean_A / mean_B`. Each term is taken from the batch where Google measured it most precisely.

### Input

`terms` (list), `anchor` (optional; default is the first term), `geo` (e.g. `US`, `DE`, empty = worldwide), `timeframe` (`today 12-m`, `today 5-y`, `2024-01-01 2024-12-31`…), `category`, `property` (web, YouTube, news, images, shopping), `bridgeMode`, calibration fields and proxy.

### Tips & limits

- Terms far below the others (raw peak 0 even next to the smallest linkable term) come back as `belowResolution: true` with `mean: null`, never as 0. Add 1–3 terms of intermediate popularity to bridge them.
- Tested on 12, 50, 100 and 216 terms (US/GB/WORLD/DE; 1-m to 5-y): all terms linked; ratios match Google's own 5-term comparisons within 0–10%.
- Values are relative interest, not search counts. Use the calibration option for estimated volumes.
- Google may throttle large jobs. The Actor retries with new sessions; a residential proxy is recommended above ~100 terms.
- Terms flagged `lowConfidence` are directionally right but noisy.

### Pricing

Pay per stitched keyword: **$1.50 per 1,000** on Starter, $1.25 on Scale, **$1.00 on Business and Enterprise** ($2.00 on the Free plan), plus $0.01 per run. Platform usage and residential proxy are included. A 12-keyword run costs about $0.03, and keywords without data are never charged.

Not affiliated with Google. Uses publicly visible Google Trends data. You are responsible for complying with Google's terms in your use case.

# Actor input Schema

## `terms` (type: `array`):

Up to 1,000 search terms. Duplicates are removed.

## `anchor` (type: `string`):

A mid-popularity term that is added to every batch. Default: the first keyword. Pick something neither tiny nor huge relative to your list.

## `geo` (type: `string`):

Trends geo code, e.g. US, DE, GB, US-CA. Empty = worldwide.

## `timeframe` (type: `string`):

Time range of the Trends query.

## `category` (type: `integer`):

Google Trends category id (0 = all categories).

## `property` (type: `string`):

Which Google property to measure (web, YouTube, Shopping, News, Images).

## `bridgeMode` (type: `string`):

Extra size-sorted batches that link very big and very small terms through neighbours of similar size.

## `calibrationTerm` (type: `string`):

A term from your list whose monthly search volume you know (e.g. from Google Ads Keyword Planner).

## `calibrationMonthlyVolume` (type: `integer`):

Known monthly searches of the calibration term. Enables an estimatedMonthlyVolume column (an estimate, proportional to Trends interest).

## `outputMode` (type: `string`):

Nested timeline per keyword, or one flat row per keyword per date.

## `requestDelayMs` (type: `integer`):

Pause between Google Trends requests. Higher = fewer rate limits.

## `concurrency` (type: `integer`):

How many comparison batches to fetch at once, each on its own proxy session (1-5). Higher is faster; 3 was reliable in tests.

## `proxyConfiguration` (type: `object`):

Residential proxy strongly recommended on Apify; Google Trends rate-limits datacenter IPs.

## Actor input object example

```json
{
  "terms": [
    "coffee",
    "tea",
    "matcha",
    "espresso",
    "cold brew"
  ],
  "geo": "",
  "timeframe": "today 12-m",
  "category": 0,
  "property": "",
  "bridgeMode": "auto",
  "outputMode": "perTerm",
  "requestDelayMs": 1500,
  "concurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All result rows in the default dataset (switch views in the Output tab).

## `summary` (type: `string`):

Run statistics (JSON).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "terms": [
        "coffee",
        "tea",
        "matcha",
        "espresso",
        "cold brew"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tgelu/google-trends-stitcher").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "terms": [
        "coffee",
        "tea",
        "matcha",
        "espresso",
        "cold brew",
    ],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("tgelu/google-trends-stitcher").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "terms": [
    "coffee",
    "tea",
    "matcha",
    "espresso",
    "cold brew"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call tgelu/google-trends-stitcher --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tgelu/google-trends-stitcher"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/zdRHdqHS8SnYHl8Ly/builds/LWoDVBPcITrUTtHPx/openapi.json
