# How products work without live search **Live shop:** https://balkanplate.com/shop **Example recipe cart:** https://balkanplate.com/shop?recipe=krompir-paprikas **Cockpit paste-ASIN:** https://balkanplate.com/admin → *Više* → Curated Amazon products **User product picks:** shop gap → help icon → open Amazon + paste `/dp/` ## Standing rule (development) **Live search comes later.** Until then we do **everything possible and legal without it**: - No ASINSpotlight / PA-API browse or search on shop pages (`/api/search` stays **503**). - Curated ASINs in `web/data/amazon.json`, cache seed, Add-all cart URLs. - User-assisted picks (paste `/dp/` or ASIN) with auto-approve + admin queue. - **Similar product** control stays active after a pick; live thumbnail/link = latest approved ASIN; older ones stay in `alts` (capped). - Free Amazon CDN thumbnails from ASIN (`images-na…/images/P/{ASIN}…`) — no product API. - Soft-match pantry by ingredient `query` when a recipe row has no ASIN yet. We do **not** scrape Amazon pages, hidden iframes, or harvest cross-origin DOM (CORS + Associates ToS). --- ## The awkward moment (find → paste) — especially on phones We cannot read Amazon from our page. The helper must bring the link back: 1. Tap **Suggest product** on a gap ingredient. 2. Tap **Open on Amazon** (search opens with the ingredient query + our tag). 3. Pick a product in the Amazon app / browser. 4. **Share → Copy link** (or copy from the address bar / Share sheet). 5. Return to BalkanPlate, **paste** into the field, Save. Accepted paste shapes: bare `ASIN`, `/dp/ASIN`, `/gp/product/ASIN`, or a long Amazon URL that contains an ASIN. Messy share text is OK if an ASIN is inside it. Lost or search-only `/s?k=` links are rejected as products. --- ## Why invisible windows / hidden iframes cannot fill gaps Opening Amazon in a hidden iframe, popup, or “invisible link” **cannot** harvest title, price, or ASIN into our app: 1. **Cross-origin (CORS)** — a page on `balkanplate.com` cannot read the DOM or network body of `amazon.com`. 2. **Bot detection** — automated headless scrapes get blocked or challenged. 3. **Amazon Associates / site ToS** — automated scraping of Amazon product pages is not an allowed substitute for a product API. So: **no invisible-window harvester.** Gaps are filled by curated ASINs (paste or cache reuse) **or user-assisted picks** (user opens Amazon, pastes `/dp/` back). --- ## How affiliate shops worked before paid search APIs | Approach | What it does | Do we use it? | |---|---|---| | **Manual curated ASIN lists** in JSON | Real `/dp/ASIN` links + multi-ASIN `gp/aws/cart/add.html` | **Yes** — primary path | | **User product picks** | Helper opens Amazon search (affiliate tagged), pastes `/dp/` → pantry | **Yes** — `POST /api/product-picks` | | **Amazon CDN image from ASIN** | Thumbnail without Product API | **Yes** — fill gaps when image missing | | **Amazon search deep-links** `/s?k=…&tag=` | Sends shoppers to Amazon search (no API bill) | Helpers only (picker); shop still has no search bar | | **Cached API payloads** (`instance/amazon-cache/**`) | Reuse ASINs/titles/images from earlier API runs offline | **Yes** — seeded pantry + recipes | | **Cart add URLs** from known ASINs | `https://www.amazon.com/gp/aws/cart/add.html?ASIN.1=…&ASIN.2=…&tag=…` | **Yes** — Add-all | | **Paste ASIN / `/dp/` URL** in cockpit | Admin saves into `web/data/amazon.json` | **Yes** — local only, zero API credits | --- ## What BalkanPlate does now 1. **Offline seed** from `instance/amazon-cache` into `web/data/amazon.json` (pantry + recipe ingredients). 2. **Recipe shop curated mode** returns products that already have `asin` → builds `amazon_cart_url`. 3. **Cockpit editor** (`POST /api/curated/products`) — paste ASIN or Amazon product URL; optional attach to a recipe id. 4. **User picks** (`POST /api/product-picks`) — public, rate-limited; default **auto-approve** writes the same pantry JSON. Queue: `instance/product-picks.json`. Cockpit can later approve/reject when auto-approve is off. 5. **CDN thumbnails** when an ASIN has no stored image. 6. **Search stays disabled** — no shop search UI, no live ASINSpotlight search calls. Ingredients always show a suggest control (bag icon). If Amazon is already linked, the button means **Similar product** — live image stays the newest approval; prior ASINs accumulate under `alts`. --- ## Cost note: ~1000 Amazon lookups (one-time fill) Scope for early catalog: **≤100 recipes × ~10 ingredients ≈ 1000** search/product results. Unique pantry queries are usually **far below 1000** (milk, flour, eggs soft-match across dishes). Live shop search stays off; this is for an occasional batch or a free-trial seed only. | Provider | Model | Cost for ~1000 Amazon results | Catch | |---|---|---|---| | **Oxylabs** (Amazon scraper) | Micro: **~$0.50 / 1K** Amazon results (no JS) | **~$0.50** usage | Free trial up to **2K** results; then Micro floor **$49/mo** | | **Bright Data** (Amazon Scraper API) | PAYG **$1.50 / 1K** records | **~$1.50** | Free tier **5K/mo** — one fill fits without paying | | **ScraperAPI** | Amazon = **5 credits**/req | 1000 × 5 = **5000 credits** (~$2.45 effective on Hobby) | Free ≈ **200** Amazon req; Hobby **$49**/100K credits is overkill for one batch | **Oxylabs:** Amazon without JS ≈ $0.50/1K on Micro; trial (~2K results) can cover one full fill once; paid floor is $49/mo afterward. **Bright Data:** PAYG ~$1.50 for 1000; new account **5K free/month** is enough for this batch at $0. **ScraperAPI:** Amazon is 5 credits per request (not 1:1). Free 1K credits ≈ 200 Amazon pages. `render` / `premium` bumps credits (often 15–25/req). Hobby pays subscription floor, not pure usage. **Verdict for BalkanPlate (small, one-shot):** 1. Cheapest: Bright Data free 5K **or** Oxylabs trial 2K. 2. Do **not** buy a $49/mo plan only to fill once. 3. Prefer **manual + user paste** ([Cockpit](https://balkanplate.com/admin) / shop help) — soft-match reuses pantry ASINs across recipes. Public list prices (VAT / geotarget / retries may change totals). Charged for success (Oxylabs / Bright Data) or credits (ScraperAPI). Sources: [Oxylabs](https://oxylabs.io/products/scraper-api/web/pricings), [Bright Data Amazon](https://brightdata.com/products/web-scraper/amazon), [ScraperAPI credits](https://docs.scraperapi.com/getting-started/quick-start/credits-and-requests-costs). --- ## Operator checklist 1. Open Amazon in your normal browser, copy a product link (`/dp/XXXXXXXXXX`). 2. Cockpit → Više → paste URL → optional recipe id (`krompir-paprikas`) → **Sačuvaj ASIN**. 3. Or let shoppers fill gaps: `/shop?recipe=…` → help icon → paste. 4. Open `/shop?recipe=…` → **Add all** should open `gp/aws/cart/add.html` with `ASIN.1`, `ASIN.2`, … --- ## Related - **7-day content + link plan:** https://balkanplate.com/docs/wordcamp/7-DAY-AMAZON-FUNNEL.md - **Recipe of the week:** `instance/featured-recipe.json` · `GET /api/featured` · surfaced on `/`, `/shop`, `/start`