Discover and checkpoint the source list
Use Sitemap to find candidate URLs, or a scoped crawl when you need linked content. Review the domain and path scope before queuing pages. Give each item an application ID that stays stable if its title or price changes. Save a manifest like this assources.json, replacing the example URL with a reviewed product page:
sources.json
Choose the extraction path
The Products discovery endpoint returns at most 12 products; it is not a full-catalog export. For a catalog, discover and queue the pages you intend to cover. Product variants, stock, and image-to-variant associations can be missing and need independent validation.
The worker below uses custom Extract with
factCheck: true, a nullable schema, and a single-page scope. See the extraction guide for requests in every SDK. Run this Python application with CONTEXT_DEV_API_KEY set on the server.
Store records separately from attempts
Keep three kinds of state: the source queue, the latest accepted record, and historical observations. The SQLite worker commits each source independently, so a failure on one page cannot delete another page’s data.catalog.py
Run the worker
next_attempt_at; do not repeatedly restart after an authentication or account-limit error. Review exhausted retries and invalid records explicitly.
Preserve uncertainty and provenance
urls_analyzed is the set of pages used by an extraction request, not automatic field-level evidence. If a displayed field needs an exact citation, retain and verify a supporting excerpt from the relevant page. Do not manufacture a per-field source by attaching the first analyzed URL to every value.
A null price means the extraction could not establish it. Keep historical observations if you want to display a separately labeled last-known price. Never replace an unknown price with zero, or compare prices before checking currency, unit, and selected variant.
The worker uses maxAgeMs: 0 for an intentional fresh extraction. For routine ingestion, choose a cache policy that fits your refresh schedule. The stored observation time is when your worker received the data; inspect cache metadata if source freshness is material.
Expand and reconcile coverage
For larger raw-content jobs, use Batch and persist the batch ID, per-item IDs, result cursor, and failures. Read all result pages usinghas_more and next_cursor; a completed job can still contain failed items. Resume from checkpoints and process each result idempotently.
Before calling a dataset complete, compare discovered, queued, accepted, empty, failed, and reviewed items. A successful extraction or a crawl that reached its time or page limit does not establish full-site coverage. Remove a record only after a deliberate deletion check; a failed page is not evidence that the product disappeared.
Try a second run with a changed price, a nullable field, and one failing source. Verify that IDs remain unique, observations retain source URLs and times, and the failed source’s last accepted record remains available with a stale-state label.
Product extraction
Use the product-specific contract when it fits your records.
Competitor comparisons
Compare compatible facts and preserve unknown values.