# Changelog of Google Trends Scraper and Data API (`danthedataman/google-trends-data-api`) Actor

- **URL**: https://apify.com/danthedataman/google-trends-data-api/changelog.md
- **Full Actor documentation**: https://apify.com/danthedataman/google-trends-data-api.md

## Changelog

### 0.9 — 2026-09-10

- Adds optional `includeKeywordInsights` (default off). When the add-on is on,
  keyword mode writes one derived insight per keyword to the `KEYWORD_INSIGHTS`
  key-value record (never the dataset) from that keyword's emitted rows. The
  `keyword-insight` charge applies once per written insight when that event is
  listed in the Actor's pricing; opting in before then returns the record
  without an add-on charge. Fewer than four emitted interest-over-time points
  whose `hasData` is not false skip the charge. Partial coverage still bills
  once when the event is listed. A charging failure is recorded on `ERRORS` as
  `keywordInsightCharge`; a write failure after a successful charge is recorded
  as `keywordInsightWrite`. Neither drops already-pushed result rows nor fails
  the run. Trending mode ignores the flag.
- Keyword insight `coverage` is `partial` with `max_items` among
  `coverageReasons` when `maxItems` dropped any of that keyword's rows in the
  batch, even if four or more points remain.
- A non-boolean `includeKeywordInsights` writes SUMMARY with
  `invalid_include_keyword_insights` before the run fails, matching the other
  validated exits.
- The add-on write follows `charged_count` on the charge result: a positive
  count writes the insight; zero with `event_charge_limit_reached` skips the
  write and records `keywordInsightSkipped` on `ERRORS`. Zero without that
  flag records `keywordInsightUnknown` as "charged\_count was 0 and
  event\_charge\_limit\_reached was not reported". The last billed unit is
  written even when `event_charge_limit_reached` is true. When
  `charged_count` is unavailable, the write falls back to the limit flag
  and a skip is recorded as `keywordInsightUnknown` with
  "charged\_count was unavailable on the charge result".
- When the add-on is on, a non-TrendsError exception during a batch's explore,
  widget fetch or dataset push is counted as a failure, recorded on `ERRORS` with
  the batch keywords and a repr, and marked failed on SUMMARY
  (`unexpected_error`); the run continues so `ERRORS` and SUMMARY are
  written. Off: the exception still escapes.
- When the add-on is on, an unexpected exception while computing a keyword
  insight is recorded on `ERRORS` as `keywordInsightError` with the keyword,
  a repr, and `charged` true when Actor.charge had returned for that
  keyword and the run had not decided against writing; later keywords still charge and
  write, and `ERRORS` and SUMMARY are written. The block runs only when the
  add-on is on, so the off path is unchanged.
- When the add-on is on, each add-on failure (charge, write, skipped, unknown,
  error) and an unexpected batch error writes `ERRORS` immediately; the helper
  logs and swallows its own failure. The final `ERRORS` write at the end of
  the run still runs. Off: unchanged.

### Unreleased

- Added SUMMARY processing coverage and widget errors in the key-value store, with output links and exact-key collections. These records add no result/custom-event charge.
- Corrected startup pricing and storage-cost wording. Existing rows, charging configuration, request order, stop behavior and failure thresholds are unchanged.

### 0.7 — 2026-07-26

- **Removed a billing hazard introduced in 0.6.** A schema `default` on
  `keywords` meant an API or MCP caller who omitted the field silently got a
  \~150-row bill for a term they never asked for. Apify's daily QA test uses the
  *prefill*, not the default, so the default bought no reliability. Omitting
  search terms now fails immediately without result-row charges, with a clear message.
  The automatic memory-scaled Actor Start charge still applies.
- Missing or invalid input ends with a status message instead of a Python
  traceback in the run log.
- Corrected the README: Web search is the empty string, not `"web"` — the
  documented value would have been rejected by input validation.
- `geo` now documents its Trending-now behaviour (country-level, defaults to US).

### 0.6 — 2026-07-26

- Superseded by 0.7; see above.

### 0.5 — 2026-07-26

- Trending-now failures now end with a clear status message instead of a Python
  traceback (any country whose board Google does not publish, and every genuine
  rate-limiting episode, took the old path).
- `valueScale` is now on every dataset type, not just interest by region.
- Several `startUrls` now pool their keywords and take geo/date/category from the
  first URL that specifies them, instead of silently merging into one hybrid
  query. Non-Trends URLs are reported rather than dropped, and terms are trimmed.
- Documented `maxRunSeconds`; surfaced `comparisonGroup` and the trend timestamps
  in the default Output view.
- Replaced the competitor comparison table with a plain capability list.

### 0.4 — 2026-07-26

- **Fixed (important): comparison mode returned self-normalised regional values.**
  `compareKeywords: true` fetched each term's own region widget, so every term
  peaked at 100 and the values were not comparable despite the docs promising a
  shared scale. It now reads the shared widget and every row states its
  `valueScale` (`comparison_share_percent` vs `index_0_100`).
- **Failed requests are no longer written to the dataset**, so you are never
  billed a result row for our error. Details go to the run's `ERRORS` record.
- **An empty result is no longer a failed run.** Filters that match nothing now
  finish cleanly with guidance instead of a Python traceback.
- `dataTypes: []` no longer silently scraped (and billed) all three datasets;
  `maxItems: 0` and `rotateAfterRequests: 0` now mean what they say.
- `date` is now sortable ISO-8601 UTC; Google's display label moved to
  `dateLabel` (it omitted the year on short ranges).
- Custom date ranges are actually selectable — the closed dropdown blocked the
  documented `2024-01-01 2024-12-31` form.
- Added a run time budget, a `comparisonGroup` marker for >5 compared terms, and
  many more fields in the default Output view.

### 0.3 — 2026-07-26

- **Paste a Google Trends URL** (`startUrls`) and its q / geo / date / cat are
  parsed straight into the run.
- **Labelled category pickers** for both modes, instead of raw numeric IDs.
- **Trending categories** are now a multi-select, and **trend status** is a
  three-way all / active / ended filter.
- Sub-region geo codes in Trending now mode are normalised to their country with
  a warning: Google's trending board is country-level only.

### 0.2 — 2026-07-26

- **New: Trending Now mode.** Pick a country and get the live trending board with
  estimated search volumes, growth percentages, active/ended status, category IDs
  and breakdown queries. No keywords needed.
- Windows of 4 / 24 / 48 hours or 7 days; optional category filter and
  active-only filter.
- Google retired the legacy `dailytrends` endpoint (now 404); this reads the
  current Trending Now board directly.

### 0.1 — 2026-07-26

Initial release.

- Interest over time, interest by region, and related & rising queries.
- Independent (0–100 per term, unlimited keywords) and comparison (shared scale, up to 5 terms) modes.
- Resilient transport: warmed sessions, exponential backoff with jitter, and automatic proxy/session rotation on rate limits.
- Partial failures are logged and skipped instead of aborting the run.
- Country, sub-region, category, search property, language and custom date range support.
