Search Trend Data for Demand Forecasting: What It Can Show
Search trend data shows when interest in a topic rises and falls, which makes it a useful leading signal for demand forecasting. It does not show how many searches happened. Google Trends returns an index from 0 to 100 that is rescaled for every request, so you can model shape, seasonality and timing, but not units sold or absolute volume.
What does a Google Trends value actually measure?
A Trends value measures relative popularity: the share of searches for a term in a given place and period, scaled to a 0 to 100 range. Google describes the process itself: "Each data point is divided by the total searches of the geography and time range it represents to compare relative popularity" (Google Trends Help, FAQ about Google Trends data, accessed October 2026). The result is then scaled "on a range of 0 to 100 based on a topic's proportion to all searches on all topics."
Two consequences follow. First, a value of 40 means "40% of this window's peak share", not 40 searches or 40% of anything absolute. Second, if overall search activity grows, a term's index can stay flat while its raw volume rises, because the denominator moved too.
What does the API return?
The Google Trends interest endpoint returns a series with a timestamp, a human-readable date range and the index value, plus a summary block with the average, maximum and minimum. This is a real recorded response for tesla in the US over one year, trimmed:
curl "https://api.perceptlayer.com/v1/google-trends/interest?q=tesla&geo=US&time_range=1y" \
-H "X-API-Key: $API_KEY"
{
"search_parameters": {
"keyword": "tesla",
"geo": "US",
"time_range": "today+12-m",
…
},
"timeline_data": [
{ "timestamp": 1760832000, "date": "Oct 19 – 25, 2025", "value": 40 },
{ "timestamp": 1761436800, "date": "Oct 26 – Nov 1, 2025", "value": 39 },
…
],
"interest_over_time": {
"average": 49.13,
"max_value": 100,
"min_value": 39,
…
}
}
Read it as: in the week of Oct 19 to 25, 2025, interest was 40% of the strongest week in that 12-month window. The max_value here is 100, which is the top of the scale. It tells you nothing about how large that peak was in searches.
The request takes q, plus optional geo, time_range (1h to 5y or all), hl and search_type (web, images, news, youtube or shopping). Authentication is covered in the docs.
Why does the window change the numbers?
The window changes the numbers because the peak is recalculated for every request. Google says each data point is divided by the totals for the geography and time range it represents. It doesn't spell out what happens when you change the window, but a different window can contain a different maximum, so the same week can plausibly be 40 in one response and a different number in another, with no change in the underlying searches.
Here is the arithmetic, using made-up numbers to show the mechanism. Suppose a week has a true search share of 0.002% and the peak week in a 1-year window has 0.005%. That week indexes at 0.002 / 0.005 × 100 = 40. Now request 5 years, where an earlier peak had a share of 0.010%. The same week indexes at 0.002 / 0.010 × 100 = 20. Nothing changed except the denominator.
For a forecasting pipeline, this means you should never append values from separate requests to one table as if they shared a scale. Pull one long window and store it whole, or rescale overlapping windows against each other.
How do you stitch two windows onto one scale?
You stitch windows by finding timestamps present in both responses and computing the ratio between them. If the overlap is a few points with non-zero values, the median ratio is a stable scale factor. This only works when both responses use the same granularity. The recorded 1y response is weekly, but We haven't recorded a 5y response, so the script checks for shared timestamps instead of assuming they line up.
import os
import statistics
import requests
BASE = "https://api.perceptlayer.com/v1/google-trends/interest"
HEADERS = {"X-API-Key": os.environ["API_KEY"]}
def series(q, geo, time_range):
r = requests.get(
BASE,
params={"q": q, "geo": geo, "time_range": time_range},
headers=HEADERS,
timeout=30,
)
r.raise_for_status()
return {p["timestamp"]: p["value"] for p in r.json()["timeline_data"]}
recent = series("tesla", "US", "1y")
long_run = series("tesla", "US", "5y")
overlap = [t for t in recent if t in long_run and recent[t] > 0 and long_run[t] > 0]
if not overlap:
raise SystemExit("No shared timestamps; the windows use different granularity")
factor = statistics.median(long_run[t] / recent[t] for t in overlap)
print(f"{len(overlap)} shared points, long-window values are x{factor:.2f} of the recent ones")
This costs 2 credits (2 calls × 1 credit). Failed calls cost nothing, and the retry rules for lost replies are in Retry Web API Calls Without Paying Twice.
Rounding is the limit here. Values are integers, so a term that sits at 1 or 2 has too little resolution for a reliable ratio. Prefer overlap points with values above 10.
What can the index show a forecasting model?
The index can show seasonality, trend breaks and lead time. Those are shape properties, and shape survives rescaling. A product whose search interest climbs six weeks before your sales history does is a candidate for a lagged regressor, and the lag is something you can measure with a cross-correlation against your own data.
What it cannot show is level. You can't turn 40 into units, and you can't compare two terms from separate requests, because each response has its own peak of 100. The catalogue doesn't document requesting several terms in one call, so check in the playground whether q accepts more than one before you build comparisons on it. Check the endpoint page and run a call in the playground to see how the response is shaped before you build on it.
Useful companions in the same API:
| Endpoint | What it adds | Credits |
|---|---|---|
/v1/google-trends/interest |
Index over time for a term | 1 |
/v1/google-trends/interest-by-region |
Relative interest across regions | 1 |
/v1/google-trends/related |
Related queries for broadening a thin term | 1 |
/v1/google-trends/trending-now |
What is surging now in a geo |
1 |
What are the honest limits?
The limits are sampling, privacy thresholds and rounding. Google says that "only a sample of Google searches are used in Google Trends" and argues that this is sufficient at its scale (Google Trends Help, accessed October 2026). It also says Trends "only shows data for popular terms, so search terms with low volume appear as '0.'"
In practice that gives you a short list of cautions:
- Zeros are not zero demand. A 0 means below Google's threshold for that place and period.
- Narrow geographies are noisy. Smaller
geoareas have fewer searches behind each point. - Search is not purchase. Interest can come from curiosity, news or a product launch with no buying behind it.
- Terms are ambiguous. A brand name can pick up searches that have nothing to do with your product.
- The data is as found. Perceptlayer returns what the source shows at the time of the call, so store the call date next to every series.
If your category is small, trend data may be too thin to help. In that case your own sales, site search and ad data will do better.
How do you run this as a forecasting input?
You run it as a scheduled pull that stores raw series with the request parameters and the call date, then builds features from them. Keep the raw response, because the rescaling means you can't reconstruct it later from derived values.
A simple plan: pull each keyword weekly with time_range=1y, which the recorded response returns as weekly points, store every pull so your own history grows past one year, and compute features such as a 4-week moving average and, once a year of pulls has built up, a year-over-year ratio. Test whether adding them lowers error on a holdout period against a baseline that uses only your sales history. If it doesn't, drop the signal.
Cost is easy to budget. 50 keywords × 1 call a week × 4 weeks = 200 credits a month, inside the 1,000 free credits you get every month after verifying an email address; see pricing for what credits cost beyond that. Caching repeat requests is covered in Cache API Responses in Python, and the first call to run is in the Google Trends API in Python guide. To start, get a free API key and run an interest call in the playground on the Google Trends API page.
APIs in this post
Frequently asked questions
Can Google Trends data predict sales?
It can improve a forecast when search interest leads purchases and you test the lag against your own history. It cannot predict sales alone, because the values are a relative index with no units. Treat it as an extra input beside sales data and keep it only if it lowers holdout error.
Are Google Trends values search volumes?
No. Google says each data point is divided by the total searches of its geography and time range, then scaled from 0 to 100 against the topic's proportion of all searches (Google Trends Help, accessed October 2026). The value 100 marks the peak of that window, not a fixed number of searches.
Why do my values change between requests?
The scale is recalculated for each request, so a different time_range, geo or set of terms can put the maximum somewhere else and shift every other value. Store whole series from one request, or rescale overlapping windows with a ratio on shared timestamps, as in the Python example above.
How much does it cost to pull trend data?
Each interest call costs 1 credit, and failed calls cost nothing and return X-Credits-Used: 0. Every account gets 1,000 free credits a month after email verification. After that, credits come in prepaid packs starting at 10,000 credits (the Starter pack), so 10,000 calls × 1 credit = 10,000 credits. See pricing for what credits cost and credits in the docs.
What does a value of 0 mean?
Google states that terms with low volume appear as 0, because Trends only shows data for popular terms (Google Trends Help, accessed October 2026). A 0 therefore means below the reporting threshold, not no searches. For niche products, query a broader term or use the related endpoint to find one.