๐Ÿ›’ Product Matcher - Cross-Retailer Matching, No Shared SKU avatar

๐Ÿ›’ Product Matcher - Cross-Retailer Matching, No Shared SKU

Pricing

Pay per event

Go to Apify Store
๐Ÿ›’ Product Matcher - Cross-Retailer Matching, No Shared SKU

๐Ÿ›’ Product Matcher - Cross-Retailer Matching, No Shared SKU

๐Ÿ”— Match the SAME physical product across retailers/marketplaces, no shared SKU. โœ… Brand/model/pack/size extraction, unit canonicalisation, blocking. โš ๏ธ Different pack count or size never match, even on near-identical titles.

Pricing

Pay per event

Rating

0.0

(0)

Developer

mohamed alaya

mohamed alaya

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

Product Matcher

Work out which listings from different retailers or marketplaces are the same physical product when there is no shared SKU. There is exactly one product-matching actor in the entire Apify Store โ€” this is the second โ€” and it is a problem serious enough that Databricks and other data platforms publish whitepapers on it. This actor is pure computation: you supply two or more product lists, nothing is scraped.

What it actually does

1. Title normalisation. Retail titles are full of noise โ€” "Best Seller!", "Free Shipping", "2-Pack Deal", inconsistent punctuation and case. Marketing phrases are stripped, punctuation is unified, and the result is used for similarity scoring. Attribute extraction (below) still runs on the raw title first, so a pack count buried inside "2-Pack Deal" is recovered before the phrase is thrown away.

2. Structured attribute extraction. Brand, model/part number, pack count, size/capacity and colour are pulled from explicit fields when present, and parsed out of the title otherwise:

AttributeExample
Brandexplicit brand field, else the title's leading capitalised word
Model / part numberModel: XYZ, SKU ABC-123, or a bare alphanumeric token like WH-1000XM4
Pack size / count"6 Pack", "Pack of 12", "3 x 500ml"
Size / capacity"500ml", "1L", "16oz", "1kg", "12 inch" โ€” canonicalised to ml, g or cm so units compare correctly (1L = 1000ml, 16oz โ‰ˆ 473ml, 1kg = 1000g)
Colourmatched against a fixed colour-word list
GTIN/EAN/UPC/ASINexplicit identifier fields, digit/alnum normalised

3. Blocking. Comparisons are grouped by brand + normalised model (or brand alone, or GTIN), so N listings never costs O(nยฒ). Oversized blocks are skipped rather than allowed to reintroduce the blowup, and the run reports how many comparisons this avoided.

4. Scoring. A weighted blend of brand similarity, title trigram/token similarity, size agreement and pack-count agreement. An exact model/part-number match is near-decisive and floors the score high regardless of the rest.

5. Hard disqualifiers โ€” the actual accuracy lever. A different pack count, or a different canonical size, rejects the pair outright, before the weighted blend even runs. A 500ml bottle and a 1L bottle of the identical product are NOT the same listing, no matter how similar the titles read. This single rule is what separates real product matching from string-similarity theatre.

6. GTIN short-circuit. If both listings carry a GTIN/EAN/UPC/ASIN: agreement is an instant match, disagreement is an instant non-match โ€” no further scoring runs either way.

Input

Pass sources: an array of { name, records } and/or { name, datasetId }. Two sources is the normal case (matching store A against store B); three or more also works and produces transitive clusters (AB, BC โ‡’ one product) when outputMode is clusters.

{ "sources": [
{ "name": "storeA", "records": [{ "title": "Sony WH-1000XM4 Headphones, Black" }] },
{ "name": "storeB", "records": [{ "title": "Sony WH-1000XM4 Black Bluetooth Headphones" }] }
], "matchThreshold": 85, "reviewThreshold": 65 }

Thresholds are 0โ€“100 integers (Apify input schemas have no float type).

Output

match rows โ€” matched pairs with confidence (0-100), the winning band, and per-field evidence ยท review rows โ€” pairs between reviewThreshold and matchThreshold, reported rather than matched ยท unmatched rows โ€” listings from each source with no match, grouped by source ยท cluster rows (in clusters output mode) โ€” one row per distinct product with every matching listing from every source.

Honest limitations

  • Text and structured-attribute matching only โ€” there is no image comparison. Two visually identical products with completely different, unparseable titles will not be matched.
  • Model/part-number and colour extraction are regex heuristics, not a product taxonomy. Unusual title formats (non-English, no delimiters) will fall back to weaker title-similarity evidence.
  • GTIN/EAN/UPC/ASIN values are normalised but never checksum-validated โ€” garbage-in agreement still counts as agreement.
  • Bare "oz" is always treated as a fluid ounce for size canonicalisation (matching the common "16oz = 473ml" retail convention), not a weight ounce. Pass an explicit size field to avoid the ambiguity for weight-in-ounces products.
  • Blocking requires at least a brand, model, GTIN, or two shared leading title words. Two listings that share none of those are never compared, by design โ€” this is what keeps the run off O(nยฒ).
  • Capped at 200,000 records per run.