An ecommerce product research pipeline starts with a live board, maps the SKU to a category keyword, then scores that keyword on Amazon, Google Shopping, and Google Search from one endpoint. On the 2026-08-10 pull, TikTok Shop Hot Products ranked a 140 microneedle derma roller SKU at #1 (as_of_ts 2026-08-10T00:01:32Z). The category term derma roller on Amazon sat at score 58.3 with volume 328,707 on 2026-07-31 (+5.81% over 30D, -15.51% over 3M, -19.59% over 12M). Google Shopping sat at 19.0 on 2026-08-08 (+35.71% over 7D, -62.0% over 3M). Google Search sat at 48.0 on 2026-08-08 (-4.0% over 7D, -36.84% over 12M). The same Bearer POST contract powers boards, growth, and time series.
Pipeline shape
Keep the job in three stages. Stage 1 pulls a board with get_top_trends. Stage 2 normalizes a SKU title into a short category keyword. Stage 3 runs get_growth once per source and writes a scorecard. Optional stage 4 stores get_time_series points for charts. The Python Trends API client pattern is enough for cron.
import json
import os
import requests
API_URL = "https://api.trendsapi.ai/api"
API_KEY = os.environ["TRENDSAPI_API_KEY"]
def trends_api(payload):
res = requests.post(
API_URL,
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json=payload,
timeout=60,
)
res.raise_for_status()
envelope = res.json()
# body is a JSON string; parse it a second time
return json.loads(envelope["body"])
Free tier is 100 successful requests per month. Starter 5,000. Pro 25,000. Business 100,000. Only HTTP 200 counts.
Stage 1: pull a live shop board
get_top_trends needs a type and no keyword. For social commerce, use TikTok Shop Hot Products. For marketplace context, use Amazon Best Sellers Top Rated.
tiktok_shop = trends_api({
"mode": "get_top_trends",
"type": "TikTok Shop Hot Products",
"limit": 15,
})
amazon_board = trends_api({
"mode": "get_top_trends",
"type": "Amazon Best Sellers Top Rated",
"limit": 10,
})
On 2026-08-10, TikTok Shop limit 15 returned the derma roller listing at rank 1, a sports top at rank 2, and GeeYea nude ankle strap block heel sandals at rank 3. Amazon Best Sellers Top Rated (as_of_ts 2026-08-10T04:01:35Z) led with Amazon Basics 20-pack AA batteries at rank 1, AAA batteries at rank 2, and Crocs Classic Clog at rank 3. Board titles are long SKU strings. The pipeline should map them to short keywords before growth calls.
Stage 2: map SKU title to keyword
Boards do not return a clean keyword field. Strip brand fluff, pack counts, and gift copy. For the #1 TikTok Shop SKU on 2026-08-10, derma roller is the research term. Rank 4 on that board pointed at facial hydrocolloid acne patches, so acne patches is the second candidate. Rank 15 pointed at a Wavytalk thermal brush, so thermal brush is a third. Keep the original rank and as_of_ts beside the normalized keyword so later audits can replay the board.
Stage 3: multi-source growth scorecard
Call sources one at a time. Comma-separated multi-source growth can time out. Prefer 30D, 3M, 6M, and 12M on Amazon. Keep daily presets for Google Shopping and Google Search.
SOURCES = ["amazon", "google shopping", "google search", "youtube"]
PERIODS = {
"amazon": ["30D", "3M", "6M", "12M"],
"google shopping": ["7D", "14D", "30D", "3M", "12M"],
"google search": ["7D", "14D", "30D", "3M", "12M"],
"youtube": ["7D", "30D", "3M", "12M"],
}
def score_keyword(keyword):
rows = []
for source in SOURCES:
body = trends_api({
"mode": "get_growth",
"source": source,
"keyword": keyword,
"percent_growth": PERIODS[source],
})
for result in body.get("results", []):
rows.append({"source": source, **result})
return rows
Live scorecard: derma roller (2026-08-10)
| Source | Recent date | Score | Volume | 30D | 3M | 12M |
|---|---|---|---|---|---|---|
| amazon | 2026-07-31 | 58.3 | 328,707 | +5.81% | -15.51% | -19.59% |
| google shopping | 2026-08-08 | 19.0 | n/a | -9.52% | -62.0% | -72.06% |
| google search | 2026-08-08 | 48.0 | n/a | -7.69% | -32.39% | -36.84% |
| youtube | 2026-08-08 | 40.0 | n/a | -2.44% | -4.76% | -36.51% |
Amazon 7D and 14D returned collapsed_range because recent and baseline resolved to the same monthly point. Google Shopping 7D was +35.71% (19.0 vs 14.0 on 2026-08-01) and 14D was +46.15% (19.0 vs 13.0 on 2026-07-25). A TikTok keyword series for derma roller returned no_data on 2026-08-10 even though TikTok Shop ranked a derma roller SKU #1. Keep the board rank and skip inventing a TikTok time series.
Amazon monthly history for derma roller shows a peak score of 100.0 with volume 564,148 on 2025-02-28, then 91.3 / 515,213 on 2026-01-31, 55.1 / 310,621 on 2026-06-30, and 58.3 / 328,707 on 2026-07-31. The short rebound over 30D sits inside a longer 12M decline.
Pipeline checks on nearby TikTok Shop terms
| Keyword | Source | Recent date | Score | Volume | Notable growth |
|---|---|---|---|---|---|
| acne patches | amazon | 2026-07-31 | 47.9 | 190,441 | +5.97% 30D, -10.13% 12M |
| acne patches | google shopping | 2026-08-08 | 5.0 | n/a | +66.67% 7D (3.0 on 2026-08-01), -89.13% 3M |
| thermal brush | amazon | 2026-07-31 | 38.6 | 380,899 | -1.78% 30D, -10.23% 12M |
| thermal brush | google search | 2026-08-08 | 33.0 | n/a | +6.45% 7D, -49.23% 3M, +6.45% 12M |
For acne patches on Google Shopping, the 14D baseline was 0.0 on 2026-07-25 and the recent score was 5.0 on 2026-08-08. Report the two scores instead of the inflated percent when baseline is zero. That rule belongs in the scorecard writer.
Stage 4: store time series when charts matter
Use get_time_series when a dashboard needs every dated point. Amazon for derma roller returned 49 monthly points from 2022-07-31 (score 38.8, volume 218,659) through 2026-07-31. Persist date, value, and volume when present. The Amazon trends source docs describe the volume field; Shopping and Search usually return scores only.
series = trends_api({
"mode": "get_time_series",
"source": "amazon",
"keyword": "derma roller",
})
# series is a list of {date, value, volume, keyword, datatype}
Cron wiring
Run the board pull once per day. Map the top N SKUs to keywords. Score each keyword across the four sources above. Write CSV or Parquet with data_date, board rank, keyword, source, period, score, volume, growth, and error code. A failed preset such as Amazon collapsed_range or TikTok no_data is a stored finding, not a reason to drop the keyword. For a worked Python walkthrough on the derma roller case, see Derma roller multi-source product signals. For Node.js fetch wiring, see the Node.js Trends API page.
Decision rules that keep the pipeline honest
- Board rank is not demand proof. Pair it with Amazon volume and Shopping score before buying inventory.
- Short Amazon windows can collapse. Prefer monthly presets and keep the error.
- Zero baselines break percent growth. Store raw scores when baseline value is 0.0.
- Social shop boards and social keyword series disagree. TikTok Shop #1 for derma roller coexisted with TikTok
no_datafor the plain keyword on 2026-08-10. - Compare siblings. Acne patches Amazon volume 190,441 and thermal brush Amazon volume 380,899 show different absolute demand than derma roller at 328,707 even when all three appear on the same shop board day.
That is the full loop: board, keyword map, multi-source growth, optional series, cron output. One API key, one endpoint, JSON in and out.