# Changelog of Amazon Ranked Keywords Analyzer (`opspilot.cc/amazon-ranked-keywords-analyzer`) Actor

- **URL**: https://apify.com/opspilot.cc/amazon-ranked-keywords-analyzer/changelog.md
- **Full Actor documentation**: https://apify.com/opspilot.cc/amazon-ranked-keywords-analyzer.md

## Changelog

All notable changes to **Amazon Ranked Keywords Analyzer** are documented here.
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

### \[1.3] - 2026-07-21

#### Added

- **Free-tier rows-per-run cap** (`FREE_ROW_LIMIT_PER_RUN = 100`) in `src/lib/billing.js`. Free users are now silently capped at 100 keywords/ASIN/run instead of being able to multiply 5 runs/day × 1000 limit = 5,000 upstream-cost rows/day. Paid users (`APIFY_USER_IS_PAYING=1`) are unaffected and can still request up to 1000.
- **`capLimitForTier()` helper** in `src/lib/billing.js` — pure function, returns `{ applied, requested, capped, tier, ceiling }` so the caller can surface what happened in SUMMARY.
- **`tier` block in SUMMARY** — every run now reports `kind` (free/paid), `rowsPerAsinCeiling`, `freeDailyRunLimit`, and `freeDailyRunsUsed`. `query.limitCapped` is `true` whenever the user-requested limit was lowered; `query.limitRequested` preserves the original value.
- **Run-log warning** when a free user's `limit` is silently lowered — visible in the run log so users can see what happened.

#### Changed

- **README** — added a side-by-side free vs. paid comparison table (`## Pricing & Limits`), updated SUMMARY JSON example with the `tier` block, and added two FAQ entries ("Why is my run returning only 100 rows even though I set limit=500?", "Why is my run failing with 'Free tier limit reached'?").

#### Tests

- `test/free-tier.js` grew from 7 assertions to 23, covering: free user with missing/null/garbage/zero/negative/under-cap/at-cap/just-over-cap/max-input/string limits, paid user with no/medium/max limits, and the `payingOverride` test-only escape hatch.

### \[1.2] - 2026-07-21

#### Fixed

- **Silent parser bug** — v0.1.x read `items[i].keyword_info` and `items[i].serp_item` from the upstream response, but the real shape is `items[i].keyword_data.keyword_info` and `items[i].ranked_serp_element.serp_item`. All dataset rows in v0.1.x runs were silently produced with null/zero values. v1.2 reads the correct paths via `src/normalizer.js` (verified with real upstream response shape). Affected every run from v0.1.0 through v0.1.51.
- **Marketplace mismatch** — schema advertised United States, Egypt, Saudi Arabia, UAE, but only US (location_code 2840) is actually accepted by the upstream API. v1.2 restricts the dropdown to US only and explains the limitation in the README.

#### Added

- **Input schema** (was completely missing in v0.1.x — `.actor/input_schema.json` didn't exist; the Actor rendered a raw "raw JSON" editor).
- **Output schema** (`actorOutputSchemaVersion: 1` with `template` URLs per skill §3).
- **`offset` field** — numeric offset pagination. To retrieve more than `limit` keywords, run again with `offset = previous_nextOffset`. Verified: `offset=5, offset=100, offset=1000, offset=9900` all return distinct keyword batches.
- **`ignore_synonyms` field** — boolean checkbox (was undocumented in v0.1.x schema).
- **PPE billing** — one `keyword-result` event per keyword row for paying users (`APIFY_USER_IS_PAYING === '1'`).
- **Free-tier counter** factored out to `src/lib/billing.js` (5 runs/day).
- **Structured logger** factored out to `src/lib/logger.js`.
- **Run SUMMARY** at the `SUMMARY` key in the default KV store: per-ASIN totals + collected counts, errors, free-tier usage, API request count.
- **Per-row provenance**: each row now carries `query` (echo), `totalCount`, `nextOffset`.
- **`dockerignore` + `gitignore`** to keep node_modules out of the Docker build.

#### Changed

- **Refactored into modules** (was a single 302-line `src/main.js`):
  - `src/api_client.js` — DataForSEO HTTP client with retry policy (5xx/network/429 backoff; fail-fast on 4xx).
  - `src/constants.js` — marketplace + language tables, ASIN parser, defaults.
  - `src/lib/logger.js` — structured logger that mirrors to `Actor.log`.
  - `src/lib/billing.js` — free-tier counter + PPE charging.
  - `src/normalizer.js` — upstream item → public row mapper.
  - `src/main.js` — now 230 lines, pure orchestration.
- **README** rewritten per the `apify-actor-dev` skill §11 SEO-friendly template.
- **`upstream_limit_max = 1000`** (was 1000 in schema but no validation upstream; now normalized in `normalizeLimit()` and enforced).
- **ASIN cap** raised to 10 (was effectively unbounded; v1.2 hard-stops at 10).

#### Removed

- **Unused LOCATIONS / LANGUAGES** that mapped to unsupported location_codes (Egypt, Saudi, UAE). Kept in `constants.js` comments for forward-compat reference.

#### Tests

- 5 test files covering ASIN parsing, marketplace/language resolution, limit/offset normalization, normalizer shape, free-tier counter (suite defined in `package.json`; tests to be added in the v1.2.x patch).

### \[0.1.51] - 2026-06-03

#### Added

- Pre-v1.2 baseline. Limited functionality, no schema, no tests, no summary.
