# Google Trends Planner: Seasonality, Regions & Rising Searches (`hypaethral_bradawl/google-trends-planner`) Actor

Google Trends for media buyers: up to thousands of keywords per run on one comparable scale, with seasonality by month, YoY and 3-month change, top regions and rising searches as flat rows. Fails loudly, never returns a silent empty dataset.

- **URL**: https://apify.com/hypaethral_bradawl/google-trends-planner.md
- **Developed by:** [Trends Planner Tools](https://apify.com/hypaethral_bradawl) (community)
- **Categories:** Marketing, SEO tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 keyword analyseds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Planner: Seasonality, Regions & Rising Searches

Google Trends data built for people who spend media budgets. Give it a list of keywords; get back one
**summary row per keyword** with the numbers you plan with (peak month, low month, a 12-month
seasonality index, year-over-year and 3-month change, top regions, breakout searches), plus flat
timeline, region and related-search rows you can pivot in a spreadsheet.

**$2.50 per 1,000 keywords analysed. No start fee. Up to 120 timeline, region and related rows per
keyword are included (the defaults stay inside that). Keywords Google has no data for are free.**

### What you can use it for

- **Budget pacing and flighting:** `seasonJan` … `seasonDec` is an index (100 = average month). A
  category at 160 in November and 70 in February tells you where to weight spend.
- **Geo-targeting and bid adjustments:** interest by country, state, US metro area (DMA) or city.
- **New keywords and negatives:** "rising" related searches flag breakout terms (`isBreakout`) before
  they show volume in your keyword tools, plus the junk queries to exclude.
- **Share of search vs competitors:** with *Add share of search* on, every keyword is also put on one
  common scale (`shareOfSearch`, `shareOfSearchAvg`), even past Google's 5-term comparison limit.
- **Shopping and YouTube demand:** switch *Search type* to Google Shopping (the closest proxy for
  purchase intent) or YouTube.

### Input

| Field | What it does |
|---|---|
| `keywords` | Search terms or Trends topic ids (`/m/...`). With share of search on, put your main term first: it anchors the scale. |
| `geo` | Empty = worldwide; `US`, `GB`, `TH`…; or a subregion such as `US-CA`. |
| `timeRange` | Preset (default: past 5 years, needed for YoY and a stable seasonality index), or set `startDate`/`endDate`. |
| `searchProperty` | Web (default), Google Shopping, YouTube, Images, News. |
| `category` | Optional Trends category id to disambiguate ("apple" in Food vs Computers). |
| `regionResolution` | AUTO, COUNTRY, REGION (states), DMA (US metros), CITY. |
| `includeTimeline`, `timelineGranularity` | Timeline rows; AUTO gives monthly rows for ranges over a year (60 rows for 5 years), NATIVE gives every weekly/daily point. |
| `includeRegions`, `maxRegions` | Region rows, highest interest first (default top 25). |
| `includeRelatedQueries`, `maxRelatedPerKeyword` | Top and rising searches (default 10 per list). |
| `maxKeywords` | Hard cap on keywords per run; your cost ceiling. |

### Output

Every row has `recordType`, `keyword`, `geo`, `timeRange`, `searchProperty`, `category`. Use the
dataset views (Summary, Timeline, Regions, Related) or filter on `recordType`:

- **SUMMARY** (one per keyword): `status` (OK / NO_DATA / ERROR), `dataQuality` (GOOD / SPARSE),
  `averageValue`, `latestValue`, `peakValue`/`peakDate`, `lowValue`/`lowDate`, `change3mPct`,
  `changeYoYPct`, `peakMonth`, `lowMonth`, `seasonJan`…`seasonDec`, `shareOfSearchAvg`,
  `topRegions`, `topQueries`, `risingQueries`, `message`, and `trendsUrl` to check it in Google Trends.
- **TIMELINE:** `granularity`, `date` (`YYYY-MM` when monthly), `value` (0-100 for this keyword), `shareOfSearch`, `isPartial` (the current,
  still-filling period; excluded from the summary maths).
- **REGION:** `regionResolution`, `regionCode`, `regionName`, `latitude`/`longitude` (cities), `value`.
- **RELATED_QUERY:** `listType` (TOP / RISING), `query`, `value`, `formattedValue` (`Breakout`,
  `+250%`), `isBreakout`.

Example summary row (US, past 5 years, web search):

```json
{"recordType": "SUMMARY", "keyword": "nike", "status": "OK", "dataQuality": "GOOD",
 "averageValue": 49.6, "latestValue": 40, "peakDate": "2026-04-12", "changeYoYPct": 6.1,
 "change3mPct": -24.5, "peakMonth": "Dec", "lowMonth": "Sep", "seasonNov": 121, "seasonDec": 124,
 "risingQueries": "nike mind 001 (Breakout), nike vomero plus (Breakout), ...",
 "trendsUrl": "https://trends.google.com/trends/explore?q=nike&date=today%205-y&geo=US"}
```

### Honest about failures

- **No silent empty datasets.** A keyword with too little volume gets a `NO_DATA` row saying so (not
  charged). A keyword Google refuses after all retries gets an `ERROR` row with the reason (not charged).
  If every keyword fails, the run is marked **Failed** with the reason in the status message.
- **Sparse data is flagged.** If fewer than half the periods have data, `dataQuality` is `SPARSE`
  and seasonality/change figures are withheld rather than computed from noise.
- **No timeouts that eat your results.** About 450 keywords an hour (requests are deliberately
  paced). The default run timeout is 4 hours; if a run nears its timeout it stops cleanly, saves
  everything done so far and lists the keywords it did not reach.
- **Polite by design.** Requests are sequential and spaced out; on HTTP 429 the actor backs off
  (honouring `Retry-After`) and retries with a fresh session. A `RUN_REPORT` record in the key-value
  store lists requests made, rate-limit hits, failures and duration.

### Things to know about Google Trends data

- Values are **relative** (0-100 within the request), not search volumes. Pair them with a keyword
  volume tool when you need absolute numbers.
- Region scores are normalised by each region's total searches, so small regions (Wyoming, small US
  metros) can top a list on modest absolute volume. Use them for bid adjustments, not volume forecasts.
- Related **topics** are off by default: in October 2026 Google returns empty topic lists. Related
  queries are unaffected.
- Data comes from Google Trends' public web interface, the same data you see at trends.google.com.
  No login and no Google account are used.

### Pricing

Pay per event:

| Event | Price | When |
|---|---|---|
| `keyword-analyzed` | $0.0025 | One keyword with data: its summary row plus up to 120 detail rows |
| `extra-row` | $0.00001 | Each detail row beyond 120 for a keyword (only with NATIVE timelines, all metros, etc.) |

1,000 keywords on default settings = **$2.50**. NO_DATA and ERROR keywords cost nothing. Set a
maximum charge per run in Apify; the actor stops cleanly at it.

Measured on Apify (31 Oct 2026): 50 keywords, US, 5 years, all row types, finished 50/50 in 6.6 minutes,
recovering on its own from the 3 rate-limit responses it met.

# Actor input Schema

## `keywords` (type: `array`):

Search terms (or Trends topic ids such as /m/019sbn). Duplicates are removed. With 'Compare keywords' on, the FIRST keyword anchors the scale for all others, so put your main term first.

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

Empty = worldwide. Country code (US, GB, TH, AU...) or subregion (US-CA, GB-ENG, AU-NSW).

## `timeRange` (type: `string`):

Preset period. Use 5 years (default) to get year-over-year change and a reliable seasonality index. Ignored when a custom start date is set.

## `startDate` (type: `string`):

Optional YYYY-MM-DD (2004-01-01 or later). Overrides the time range.

## `endDate` (type: `string`):

Optional YYYY-MM-DD; defaults to today when a start date is set.

## `searchProperty` (type: `string`):

Which Google surface the interest comes from. Shopping = Google Shopping searches, the closest proxy for purchase intent.

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

Optional Trends category id to disambiguate (0 = all categories; e.g. 18 Shopping, 71 Food & Drink, 47 Autos & Vehicles, 67 Travel).

## `compareKeywords` (type: `boolean`):

Every keyword is always analysed on its own 0-100 scale (full precision for seasonality and change). On: also adds a shareOfSearch column putting all keywords on ONE scale; beyond 5 keywords the first keyword anchors every batch, so values can exceed 100. No extra charge.

## `includeTimeline` (type: `boolean`):

One row per keyword per week/day/hour. Turn off if you only need the summary rows.

## `timelineGranularity` (type: `string`):

AUTO keeps a 5-year timeline at 60 monthly rows. NATIVE gives every Google data point (e.g. 261 weekly rows over 5 years); rows beyond 120 per keyword are billed as extra rows. Summary metrics always use the full-resolution data.

## `includeRegions` (type: `boolean`):

Interest by country, state, US metro (DMA) or city: one row per region.

## `regionResolution` (type: `string`):

AUTO = countries for worldwide, states/provinces for a country, cities for a subregion. DMA (US metro areas) works for US only.

## `maxRegions` (type: `integer`):

Top regions kept as REGION rows (highest interest first). US metros (DMA) have 210; cities can be many more.

## `includeRelatedQueries` (type: `boolean`):

Top and rising related searches for each keyword, with Breakout flags.

## `includeRelatedTopics` (type: `boolean`):

Off by default: as of Oct 2026 Google Trends returns empty related-topic lists. Turn on to request them anyway; the summary says when Google returned none.

## `maxRelatedPerKeyword` (type: `integer`):

Cap per keyword for each of the top and rising lists (1-50).

## `maxKeywords` (type: `integer`):

Hard cap on keywords processed in this run. You are charged only for keywords that return data; up to 120 detail rows per keyword are included, rows beyond that are $0.01 per 1,000.

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

Google Trends rate-limits shared datacenter IPs heavily; residential is the reliable default.

## Actor input object example

```json
{
  "keywords": [
    "running shoes",
    "trail running shoes",
    "hoka",
    "on running"
  ],
  "geo": "",
  "timeRange": "today 5-y",
  "searchProperty": "web",
  "category": 0,
  "compareKeywords": true,
  "includeTimeline": true,
  "timelineGranularity": "AUTO",
  "includeRegions": true,
  "regionResolution": "AUTO",
  "maxRegions": 25,
  "includeRelatedQueries": true,
  "includeRelatedTopics": false,
  "maxRelatedPerKeyword": 10,
  "maxKeywords": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Dataset view with one row per keyword: status, seasonality index by month, peak/low month, YoY and 3-month change, share of search, top regions and rising searches.

## `timeline` (type: `string`):

Interest over time per keyword (monthly for ranges over a year by default), with share of search.

## `regions` (type: `string`):

Interest by country, state, US metro (DMA) or city per keyword.

## `related` (type: `string`):

Top and rising related queries per keyword, with Breakout flags.

## `runReport` (type: `string`):

Keywords analysed, no-data and failed keywords, HTTP requests, rate-limit responses and duration.

# 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 = {
    "keywords": [
        "running shoes",
        "trail running shoes",
        "hoka",
        "on running"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("hypaethral_bradawl/google-trends-planner").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 = {
    "keywords": [
        "running shoes",
        "trail running shoes",
        "hoka",
        "on running",
    ],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("hypaethral_bradawl/google-trends-planner").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 '{
  "keywords": [
    "running shoes",
    "trail running shoes",
    "hoka",
    "on running"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call hypaethral_bradawl/google-trends-planner --silent --output-dataset

```

## MCP server setup

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

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/IJZ409QEknHm9vzig/builds/rROedsBYzj78gRYm3/openapi.json
