Catalog Matcher: Competitor Product Matching & Price Gaps avatar

Catalog Matcher: Competitor Product Matching & Price Gaps

Pricing

from $1.60 / 1,000 matched pairs

Go to Apify Store
Catalog Matcher: Competitor Product Matching & Price Gaps

Catalog Matcher: Competitor Product Matching & Price Gaps

Match your product catalogue against competitors' by barcode (GTIN/UPC/EAN), MPN, SKU, model number or title, with match method and confidence per pair, price gap %, and the products only one side sells. Reads Shopify, any-store and Amazon datasets or your own rows.

Pricing

from $1.60 / 1,000 matched pairs

Rating

0.0

(0)

Developer

CleanPull

CleanPull

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Features

Limited permissions

Share

This catalog matcher does product matching between your catalogue and one or more competitors': give it datasets from Shopify Store Scraper, Any Store Product Monitor or Amazon Product Scraper, your own rows, or Shopify stores by domain. It finds the same products on both sides, by barcode (GTIN, UPC, EAN), manufacturer part number, SKU, model number or title, and says how each pair was matched and how sure it is. Every pair comes with both prices and the price gap. It also lists what they sell that you don't, and what you sell that they don't, and a summary per competitor with overlap and a price index. Run it once, on a schedule or through the API.

How to match products with competitors

  1. Open Catalog Matcher on Apify and go to its input form.
  2. Give your catalogue in Your products (dataset) or Your products (rows), or your Shopify domain in Your store.
  3. Give the competitors in Competitor stores (Shopify), Competitor products (datasets) or Competitor products (rows), and pick which Gaps to return.
  4. Start the run. Open the Matches view to read each pair's Method, Confidence, Your price, Their price, Price gap % and Cheaper, the Gaps view for what only one side sells, and the Summary view for Overlap % (of yours) and Price index (theirs vs yours).
  5. To watch competitors, give it a Watchlist name, turn on Changes only (and set Undercut alert (%) to hear when they go cheaper), save it as a task and schedule it weekly.
Catalog matcher input: your products and competitor products for product matching, with title matching and gaps

What the catalog matcher gives you

  • "Which of my products does this competitor also sell, and at what price?" One row per matched pair: your price, theirs, the gap in %, and who is cheaper.
  • "What do they sell that I don't?" Gap rows for their products with no match among yours. By default only in brands you already carry (Gaps in your brands only): the ranges you could add first. Turn it off for every product they sell that you don't.
  • "Where am I the only seller?" Gap rows the other way: your products they don't carry.
  • "Am I cheaper or dearer overall?" The summary row per competitor gives the median price index (their price as % of yours), how many pairs are cheaper on each side, and the overlap.
  • "Tell me when that changes." Schedule it with a watchlist name and Changes only: you get only new matches, price moves, new gaps, and pairs or gaps that are gone.
  • "Tell me when a competitor sells something I sell for less." Give your store and theirs as Shopify domains (Competitor stores (Shopify)), an Undercut alert (%) and a watchlist name, and schedule it weekly. One run reads the stores, compares them and reports the products where they newly undercut you. No other task or webhook is needed.
  • "Feed it to a spreadsheet or an AI agent." Flat rows with the same field names for every source, and one dataset view per job.

Product matching method

Each competitor product goes down a ladder and stops at the first step that matches. matchMethod and confidence (0–1) say which step it was:

StepmatchMethodMatches onConfidence
1gtinThe same barcode (UPC, EAN-13, EAN-8, GTIN-14, written any way, check digit verified), on the product or any variant1 (0.9 for an Amazon product found by a barcode search whose page doesn't show the barcode)
2mpnThe same manufacturer part number (also found in the other side's SKU field), same brand0.95 (0.83 if one side has no brand)
3skuThe same SKU, or the style code a product's variant SKUs share (HZ8CL-02-XS, HZ8CL-02-SM → HZ8CL-02), same brand0.9 (0.78)
4modelThe same model number in the title or part number (WH-1000XM5), same brand, titles that agree0.8–0.95
5titleToken-set ratio of the titles ≥ 90, within the same brand, once brand, filler words and the variant's colour names are removedup to 0.9

Title matching rules

The title step is stricter than the ratio alone:

  • Gender must agree. Men's never pairs with women's, and a lone "W" or "M" counts.
  • Colours must agree, where both titles name one.
  • Numbers must agree (55L, 13, 105).
  • A word only one title has names another model, and blocks the match. "Arizona Suede LE" is not "Arizona Suede"; "Atom SL Hoody" is not "Atom Hoody". Words for the kind of product (jacket, shoes, backpack) and model years don't count.
  • Doubts lower the confidence by 0.1 each: a gender named on one side only, or a number on one side only.

In tests on 146 title pairs from real outdoor stores, checked by hand, 4 were wrong (2.7%), and none of the 124 with confidence 0.85 or more. All 4 had "gender on one side only" in matchedOn. Filter on confidence to choose your own trade-off.

Code match checks

Code matches have checks of their own:

  • Brands compare by whole word: "Bedrock" is "Bedrock Sandals", but "On" is not "Salomon".
  • Amounts must agree on a model-number match: 128 GB and 256 GB, a 2-pack and a 4-pack are other products.
  • Without a brand on one side, a part number or SKU match needs titles that don't disagree, and a SKU also needs similar titles.

Pairs are one to one, best confidence first. When a competitor lists the same product several times (each colour as its own product, or a second listing), the extras are shown on the pair as alsoMatched. They are not gaps and are not billed.

Product matching accuracy

  • Prices in different currencies are never compared. Such a pair has no price gap, and priceNote says why, for example "different currencies (USD and CAD): prices not compared". The summary counts these pairs. A currency missing on one side is compared as the same currency, and the note says so.
  • The matched variant's price. When a variant's barcode or SKU made the match, its own price is used, not the product's lowest.
  • A source read in part never makes false gaps. If a competitor's dataset fails part-way, that competitor is left out of the run (no rows, no charges, watchlist unchanged) and the run summary says why. If your own catalogue is read only in part, pairs are still returned but no gaps, and the watchlist is not moved.
  • A bare "$" is not assumed to be US dollars. The store's domain decides where it can ($ on a .ca store is CAD); otherwise the currency is unknown and the prices are not compared.
  • Duplicates count once. A product listed twice (same page, or the same barcodes) is matched once, never billed twice, and counted in the summary.
  • Shopify variant rows are merged. Shopify Store Scraper's flat one-row-per-variant output is put back together into products.
  • One dataset, several stores. A Shopify Store Scraper run over your store and three rivals is split by store: name yours in Your store, and each rival becomes its own comparison.
  • Placeholders are not codes. Barcodes with a wrong check digit or all zeros, store-internal numeric SKUs, and codes shared by many products are ignored.
  • Only what you pick is read. Datasets are chosen in the form, which gives this actor read access to those datasets only. It runs with limited permissions and fetches nothing from the web.

Catalog matcher input

FieldKeyWhat it does
Your products (dataset)yourDatasetIdA dataset of your products (Shopify Store Scraper, Any Store Product Monitor, Amazon Product Scraper or your own)
Your products (rows)yourItemsOr your products as rows; used together with the dataset if both are given
Your storeyourStoreYour store's domain: read in this run too with Competitor stores and no other catalogue of yours; otherwise it picks your products out of a competitor dataset
Competitor stores (Shopify)competitorStoresUp to 10 Shopify stores, each read in this run by Shopify Store Scraper and compared
Competitor products (datasets)competitorDatasetIdsOne or more competitor catalogues; each store in them is its own comparison
Competitor products (rows)competitorItemsOr competitor products as rows, with store (rows of one store are one catalogue)
Match by titletitleMatchingAfter the code steps, match the rest by title within the same brand (default on)
Title score thresholdminTitleScoreLowest token-set ratio for a title match (default 90)
Title match without a brandtitleWithoutBrandAlso match by title when one side gives no brand (score 95 or more, confidence at most 0.75; default off)
Lowest confidenceminConfidencePairs below this confidence are not matches (default 0.6)
GapsgapsGap rows both ways (default), they-sell, you-sell or none
Gaps in your brands onlygapsInYourBrandsOnlyOnly products they sell and you don't from brands you carry (default on)
Watchlist namemonitorNameRuns with the same name compare with each other
Changes onlychangesOnlyWith a watchlist name: return only rows that changed since the last run
Smallest price change (%)minPriceChangePercentIgnore price moves smaller than this (default 0)
Undercut alert (%)alertUndercutPercentMark pairs where they are at least this % cheaper; with a watchlist, report new undercuts (off by default)
Max products per cataloguemaxItemsPerCatalogueProducts read per catalogue (default 50,000)
Max cost per run (USD)maxRunCostUsdThe most one run may charge, for scheduled runs (with Competitor stores, the store reads included)
History storestateStoreNameThe key-value store that keeps each watchlist (default: its own store, cleanpull-catalog-matcher); pick one when you run with a scoped API token

Rows you give use these fields: title, brand, price, currency, url, gtin (or upc, ean, barcode), mpn, sku, store, and optionally variants (each with sku, gtin, price).

Example inputs

The form's example: three of your products against three of a rival's, as rows:

{
"yourItems": [
{
"title": "Atom Hoody — Men's",
"brand": "Arc'Teryx",
"price": 300,
"currency": "USD",
"url": "https://www.outdoorsports.com/products/arcteryx-atom_hoody-jackets-2025",
"store": "outdoorsports.com"
},
{
"title": "Black Hole Duffel 55L",
"brand": "Patagonia",
"price": 169,
"currency": "USD",
"url": "https://www.outdoorsports.com/products/patagonia-black-hole-duffel-55l-duffel-bag",
"store": "outdoorsports.com"
},
{
"title": "Cloudsoma — Women's",
"brand": "On",
"price": 180,
"currency": "USD",
"url": "https://www.outdoorsports.com/products/footwear-shoes-road_running_shoes-on_inc-womens-cloudsoma-2026",
"store": "outdoorsports.com"
}
],
"competitorItems": [
{
"title": "M Atom Hoody",
"brand": "Arcteryx",
"price": 300,
"currency": "USD",
"url": "https://www.alpenglowsports.com/products/m-atom-hoody",
"store": "alpenglowsports.com"
},
{
"title": "Black Hole Duffel 55L",
"brand": "Patagonia",
"price": 169,
"currency": "USD",
"url": "https://www.alpenglowsports.com/products/black-hole-duffel-55l-1",
"store": "alpenglowsports.com"
},
{
"title": "W Kyanite LT Hoody",
"brand": "Arcteryx",
"price": 150,
"currency": "USD",
"url": "https://www.alpenglowsports.com/products/w-kyanite-lt-hoody",
"store": "alpenglowsports.com"
}
]
}

A weekly undercut watch: your Shopify store against two rivals, read in the same run, reporting products they newly sell at least 5% below your price:

{
"yourStore": "mystore.com",
"competitorStores": ["rival-one.com", "rival-two.com"],
"alertUndercutPercent": 5,
"monitorName": "undercut-watch",
"changesOnly": true,
"maxRunCostUsd": 3
}

Your Shopify store against two rivals, from one Shopify Store Scraper run:

{ "competitorDatasetIds": ["<Shopify Store Scraper dataset id>"], "yourStore": "mystore.com" }

Your Any Store Product Monitor dataset against Amazon products found by the same barcodes, matches only:

{
"yourDatasetId": "<Any Store dataset id>",
"competitorDatasetIds": ["<Amazon Product Scraper dataset id>"],
"gaps": "none"
}

What a rival sells in brands you carry, checked weekly for changes:

{
"yourDatasetId": "<your catalogue>",
"competitorDatasetIds": ["<rival catalogue>"],
"gaps": "they-sell",
"gapsInYourBrandsOnly": true,
"monitorName": "rival-ranges",
"changesOnly": true,
"maxRunCostUsd": 1
}

Catalog matcher output

Catalog matcher output: Matches, Gaps and Summary views with match method, confidence, both prices, price gap and price index

Three kinds of rows (recordType), shown in the Matches, Gaps and Summary views.

Example rows

The rows the form's example (the first example input above) gives: two pairs, a gap each way and the summary. A matched pair:

{
"recordType": "match",
"catalogue": "alpenglowsports.com",
"matchMethod": "title",
"confidence": 0.9,
"matchedOn": "title 100",
"yourTitle": "Atom Hoody — Men's",
"yourBrand": "Arc'Teryx",
"yourPrice": 300,
"yourCurrency": "USD",
"yourUrl": "https://www.outdoorsports.com/products/arcteryx-atom_hoody-jackets-2025",
"theirTitle": "M Atom Hoody",
"theirBrand": "Arcteryx",
"theirPrice": 300,
"theirCurrency": "USD",
"theirUrl": "https://www.alpenglowsports.com/products/m-atom-hoody",
"priceGapPercent": 0,
"cheaper": "same",
"priceNote": null
}

priceGapPercent is their price against yours: −10 means they are 10% cheaper. cheaper is you, them or same. Also: yourSku, theirSku, theirGtin, yourInStock, theirInStock, and alsoMatched (their other listings of the same product).

A gap row, here a product they sell and you don't, in a brand you carry:

{
"recordType": "gap",
"catalogue": "alpenglowsports.com",
"direction": "they-sell",
"title": "W Kyanite LT Hoody",
"brand": "Arcteryx",
"price": 150,
"currency": "USD",
"url": "https://www.alpenglowsports.com/products/w-kyanite-lt-hoody",
"gtin": null,
"sku": null,
"inStock": null,
"youCarryBrand": true
}

The direction is they-sell (they sell it, you don't) or you-sell (here, the On Cloudsoma, which has no youCarryBrand).

The summary row for the competitor:

{
"recordType": "summary",
"catalogue": "alpenglowsports.com",
"yourProducts": 3,
"theirProducts": 3,
"matched": 2,
"overlapPercent": 66.7,
"theirOverlapPercent": 66.7,
"byMethod": { "gtin": 0, "mpn": 0, "sku": 0, "model": 0, "title": 2 },
"medianPriceIndex": 100,
"youAreCheaper": 0,
"theyAreCheaper": 0,
"samePrice": 2,
"currencyMismatches": 0,
"gapsTheySell": 1,
"gapsYouSell": 1,
"topGapBrands": [{ "brand": "Arcteryx", "products": 1 }]
}

Every summary row gives: yourProducts, theirProducts, matched, overlapPercent (of yours), theirOverlapPercent, byMethod, medianPriceIndex (their price as % of yours: 95 means they are 5% cheaper at the median), youAreCheaper, theyAreCheaper, samePrice, currencyMismatches, gapsTheySell, gapsYouSell, alsoMatched, duplicates, and topGapBrands (brands with the most products you don't sell).

Watchlist changes and run summary

With a watchlist name, every row has changes and firstSeen. The change types are:

  • new-match, your-price and their-price (with from and to; a price appearing or disappearing always counts);
  • new-gap;
  • match-lost and gap-closed, reported once when a pair or gap is missing from two runs in a row;
  • undercut (with gapPercent), with Undercut alert (%) set: a pair where they are now at least that much cheaper and were not on the last run, a new pair included. A pair whose price crossed the threshold through moves each smaller than Smallest price change (%) is reported too.

With Undercut alert (%) set, each pair also has undercut: true or false, and each summary gives undercuts and, with a watchlist, newUndercuts.

RUN_SUMMARY in the key-value store gives:

  • the outcome (COMPLETE, PARTIAL, EMPTY, FAILED);
  • the counts per competitor and method;
  • the charges;
  • every source that could not be read, with the reason;
  • with Competitor stores (Shopify), storeRuns (the Shopify Store Scraper run for each store) and storeReadsCostUsd;
  • droppedCatalogues (competitors left out because their source failed part-way, or because the store is your own: its pages are in your catalogue and Your store is not set) and gapsSkipped (why no gaps were made, when your catalogue was read only in part).

Pricing

EventFree and BronzeSilverGold and above
Matched pair (per 1,000)$2.00$1.80$1.60
Gap row (per 1,000)$0.10$0.09$0.08
Pair or gap checked, unchanged, Changes only (per 1,000)$0.05$0.045$0.04
Competitor catalogue compared (each, per run)$0.05$0.05$0.05

Each run also has a $0.00005 start fee. Summary rows are free. Duplicates, products you didn't ask gaps for and sources that could not be read are never charged; a competitor catalogue read only in part is left out and not charged at all. The comparison event is charged before a catalogue's rows, so a Max cost per run (USD) below $0.05 compares nothing.

Your 2,500 products against two rivals' 2,500 and 2,042 (93 pairs in common) come to, on the Free and Bronze plans:

  • $0.37 for the pairs and what they sell in brands you carry (93 pairs, 859 gap rows, 2 catalogues);
  • $0.86 with the default gaps both ways (also your 4,897 products they don't sell);
  • $1.22 with every gap both ways (Gaps in your brands only off: 9,344 gap rows).

A daily watchlist of the same with Changes only pays for its changes (a lost pair is billed as a pair, a closed gap as a gap), $0.05 per 1,000 unchanged pairs and gaps, and $0.05 per competitor (Free and Bronze).

A weekly undercut watch on Shopify stores

With Competitor stores (Shopify), each store (yours too, when this run reads it) is read by Shopify Store Scraper. Its run starts in your account and is billed at its own prices: $0.80 per 1,000 products on the Free and Bronze plans ($0.70 Silver, $0.60 Gold and above). This actor charges its usual events on top, nothing more. For 250-product stores, on the Free and Bronze plans, with Changes only after the first run:

RivalsStore reads (yours + theirs)ComparisonsUnchanged checks and ~10 changes eachA runA month (weekly)
1$0.40$0.05about $0.03$0.48about $2.10
2$0.60$0.10about $0.06$0.76about $3.30
3$0.80$0.15about $0.10$1.05about $4.50

The first run sets the baseline and returns every pair, at $2 per 1,000. With full overlap (all 250 products matched per rival) it is the dearest run: $0.95 for one rival, $1.70 for two and $2.45 for three. Later runs return only changes and cost the amounts in the table. If your catalogue is already in a dataset, give it as Your products (dataset) instead of Your store to skip one store read.

Set Max cost per run (USD) so it covers the first run: about $2 for one rival, $3 for two and $4 for three at 250 products each. A schedule keeps the same limit, and later runs charge only what they use. The limit covers the store reads too:

  1. The actor keeps back $0.15 per catalogue (its comparison and 50 rows) and $0.10 per rival (the least useful read).
  2. Your store is read first, with the rest as its limit, so it is read in full whenever the limit allows.
  3. The rivals then share what is left equally, each share being that read's own limit.

A store needs about $0.0008 per product. A rival whose share would be under $0.10, or under what your store's read cost, is not started (a rival read in part is never compared, so it would be paid for nothing). The last stores listed give way first, each with a reason giving the limit to set, and the run warns once.

Limits

  • It matches what the datasets hold. Shopify's public catalogue has no barcodes, so two Shopify Store Scraper datasets match by title. Run Any Store Product Monitor on the products to get their barcodes.
  • Title matching needs a brand on both sides by default. Products whose titles differ by more than the rules allow stay unmatched, as gaps.
  • Prices are compared as given: no currency conversion, no tax or shipping.
  • Up to 50,000 products a side run in the default 256 MB (the default limit). Give 1 GB and raise Max products per catalogue for up to 200,000 a side; a catalogue cut at the limit gives no gap rows.
  • Datasets are read only when you pick them in the form. The actor cannot see your other storages.
  • Competitor stores (Shopify) takes Shopify stores only. Some reads are reported in failures and left out (no rows, no charges, watchlist unchanged): a store that can't be read, a read that stopped at its share of the limit, and a store with more products than Max products per catalogue. A catalogue read in part would show its missing products as lost pairs. The other stores are still compared.
  • Your store must be read in full. If it can't be, nothing is compared, charged or alerted, and the reason gives the limit the read stopped at.
  • Nothing found: when nothing at all could be compared because a source does not exist or cannot be used (a dataset id that is not there or not shared, a store that is not a Shopify store, a limit too low to read your store), the run still succeeds, with one free recordType: "unreadable" row per source giving the reason; nothing is charged. When other catalogues were compared, the sources that could not be used are listed in RUN_SUMMARY (failures) instead. Near its time limit the run stops starting competitor catalogues and lists them the same way.

FAQ

How much does product matching cost per competitor per run?

On the Free and Bronze plans, each competitor catalogue compared costs $0.05 a run, each matched pair $0.002 and each gap row $0.0001; summary rows are free. The form's example (2 pairs, 2 gaps, 1 competitor) costs $0.0542. Your 2,500 products against two rivals come to $0.37 to $1.22 depending on the gaps you ask for. With Changes only, each run still bills $0.05 per competitor and $0.00005 per unchanged pair or gap; a changed or lost pair adds $0.002, a new or closed gap $0.0001. With Competitor stores (Shopify), each store read is a Shopify Store Scraper run billed at its own prices ($0.0008 per product on the Free and Bronze plans). Sources that cannot be read, duplicates and a competitor read only in part are never charged, and higher Apify plans pay less (see Pricing above).

How often should I run a competitor catalogue watch?

Weekly suits most stores, daily for fast-moving prices. The first run with a Watchlist name is the baseline; after it, new matches, price moves and new gaps come back on the run they appear, and a pair or gap counts as gone only after two runs in a row without it. Smallest price change (%) ignores small moves, and Undercut alert (%) reports only pairs that newly cross it.

What is the difference between the price gap and the price index?

priceGapPercent is one pair's price, theirs against yours: −10 means they are 10% cheaper. medianPriceIndex on the summary is their price as % of yours, the median over every pair priced in one currency: 95 means they are 5% cheaper at the median. overlapPercent is the share of your products they also sell; theirOverlapPercent the share of theirs you sell.

Why is a product not matched, or a price gap missing?

  • No brand on one side: title matching needs a brand on both sides unless Title match without a brand is on.
  • Titles that disagree: another gender, colour, number or model word blocks a title match; the product stays a gap.
  • Low confidence: pairs below Lowest confidence (0.6 by default) are not matches.
  • No barcodes: Shopify's public catalogue has none, so two Shopify catalogues match by title; Any Store Product Monitor reads barcodes from product pages.
  • Other currencies: a pair in two currencies has no priceGapPercent, and priceNote says why.
  • No gap rows: a catalogue cut at Max products per catalogue, or your catalogue read only in part (gapsSkipped in RUN_SUMMARY), gives no gaps; Gaps in your brands only leaves out brands you don't carry.

Which stores and datasets does it support?

Datasets from Shopify Store Scraper, Any Store Product Monitor and Amazon Product Scraper, any dataset with title, brand, price and (best) barcode, MPN or SKU fields, and your own rows. Competitor stores (Shopify) reads up to 10 Shopify stores in the same run; other platforms come in through a dataset.

Can I use the catalog matcher through the API?

Yes. Start runs through the Apify API or an API client, and read the dataset through its Matches, Gaps and Summary views, or the RUN_SUMMARY record with the outcome, the counts per competitor and method, the charges and every source that could not be read. Pass datasets by id in yourDatasetId and competitorDatasetIds.

Does it work with Google Sheets, Make, Zapier or Claude?

Yes. Apify's integrations send each run's results to Google Sheets, Make, Zapier, webhooks and other tools, and a schedule keeps them updated. From Claude, the MarketMage plugin compares your catalogue with a competitor's, the price gap on each product and what only one side sells, in a chat.

Is it allowed to match competitor catalogues?

The actor reads only the datasets and rows you give it, and with Competitor stores (Shopify), public Shopify catalogues through Shopify Store Scraper, as a signed-out visitor sees them: no login, no account and no customer data. How you use the data, and following the laws and terms that apply to you, is your responsibility. This is not legal advice.

Other CleanPull actors for monitoring:

Use it from Claude

The MarketMage plugin runs these actors from a Claude chat.

Found it useful? A rating on the Store helps others find it.

Changelog

  • Reliability (2026-10-24): runs that find nothing to compare (missing or unshared datasets, stores that are not Shopify stores, limits too low to read your store) end SUCCEEDED with a free unreadable row per source saying why, instead of FAILED; competitor catalogues not started before the time limit are listed, never TIMED-OUT. A source that breaks on every read, or a store blocked on every route, still fails the run. Competitor stores are capped at 10 in the input form. Prices and events unchanged.
  • Undercut watch (October 2026): Competitor stores (Shopify) reads Shopify stores in the same run, each through its own Shopify Store Scraper run within its share of the cost limit. Your store is read too when no other catalogue of yours is given. Undercut alert (%) marks pairs where a competitor is cheaper by at least a set percentage and, with a watchlist, reports new undercuts. Existing inputs work as before.
  • 0.1.8 (October 2026): a run limit that leaves room for the products found now delivers them (before, the run stopped once another catalogue comparison no longer fitted, even when pairs did). Your own store found in a competitor dataset is left out instead of being compared with itself.
  • 0.1 (October 2026): matching by barcode, part number, SKU and style code, model number, and title within the brand, with method and confidence. Price gaps without cross-currency comparison. Gaps both ways, per-competitor summaries and a watchlist mode. Shopify Store Scraper, Any Store Product Monitor and Amazon Product Scraper datasets, or your own rows.