Omar EldeebHow to monitor MAP: list every seller of your products from Google Shopping and retailer pages, flag advertised prices below MAP, and keep timestamped evidence.
MAP monitoring means listing every seller that advertises your products, comparing each advertised price with your minimum advertised price, and logging every price below it with the seller, the time and a link. Collect sellers per product from Google Shopping's seller list and from retailer pages, filter out used and refurbished offers, and run it daily so you have dated evidence, not screenshots from memory.
This guide does that with the Google Shopping "Sellers" mode and retailer URLs of E-commerce Product Scraper Pro, using real seller data for the Sony WH-1000XM5 collected on 2026-10-18 and 2026-10-20. It isn't legal advice.
A minimum advertised price (MAP) policy is a brand's rule about the lowest price its resellers may advertise for a product. This guide uses the US context. The US Federal Trade Commission's guide on manufacturer-imposed requirements describes the typical form from a dealer's point of view, where a dealer "can't participate if I advertise a price that is below the supplier's minimum advertised price", and says "the law allows a manufacturer considerable leeway in setting the terms for advertising that it helps to pay for". The same page notes the FTC challenged MAP policies of five large music distributors that it found unreasonable in reach. Policies differ, so what counts as "advertised" and what happens after a violation comes from your own policy, and its legal side is a question for your lawyer.
For monitoring, three practical points follow:
Google Shopping groups offers from many stores under one product, and the actor's Sellers mode reads that list: merchant, price, old price, stock, condition, delivery, returns and the offer link, one entry per store. It's the fastest way to see sellers you didn't know about, including stores this actor can't scrape directly (Best Buy, eBay, Lowe's and Newegg pages are unsupported, but they appear in Google's seller lists, which is a different page).
The input from a run on 2026-10-18:
{
"searchEngineKeyword": "Sony WH-1000XM5",
"scrapeModeSearchEngine": "Sellers",
"countryCode": "us",
"maxSearchEngineProducts": 4,
"maxSearchEngineSellersPerProduct": 5,
"maxSearchEngineResults": 20
}
searchEngineKeyword takes up to 50 lines, one search each. Use your exact model name, or the model number, so Google groups the right product.
One output row, trimmed (the offer links are long google.com/goto redirects to each store's offer):
{
"recordType": "search-result",
"keyword": "Sony WH-1000XM5",
"title": "Sony WH-1000XM5 Noise-Canceling Wireless Headphones",
"priceInsight": "Typically $199–$300",
"lowestOfferPrice": 228,
"sellerCount": 4,
"sellers": [
{ "merchantName": "Store A", "price": 228, "originalPrice": 398, "inStock": true, "condition": null, "bestPrice": true, "url": "https://www.google.com/goto?url=…" },
{ "merchantName": "Sony", "price": 228, "originalPrice": 400, "inStock": true, "condition": null },
{ "merchantName": "Store B", "price": 299, "inStock": null, "condition": null },
{ "merchantName": "Target", "price": 398.99, "inStock": true, "condition": null }
],
"scrapedAt": "2026-10-18T09:14:51.617Z"
}
The other three products in that run included a Target "refurbished" offer at $189.99 and an Electronic Express offer tagged used: seller badges such as "Refurbished" and "Used" are split out of the merchant name into condition.
Google's list is a summary. To confirm on the retailer's own page, or to cover marketplace sellers Google doesn't show, scrape the product pages and searches directly on supported sites (Amazon, Walmart, Target, Shopify and WooCommerce stores, and the rest of the README matrix):
{
"detailsUrls": [{ "url": "https://www.amazon.com/dp/B09XS7JWHH" }],
"listingUrls": [{ "url": "https://www.walmart.com/search?q=sony+wh-1000xm5" }],
"maxItemsPerStartUrl": 3,
"maxProductResults": 4
}
Run on 2026-10-20, it returned the Amazon listing at $199.99 and three Walmart marketplace listings with their seller field: "Video & Audio Center" at $288, "Electronic Express" at $298 (pink), and a "Restored" unit from "Secondipity" at $147.26. Product rows have no condition field, so for direct pages filter by title words such as "Restored", "Renewed" or "Refurbished", and by the URL (Walmart's restored listing carried conditionGroupCode=2).
This reads a Sellers-mode run, skips used/refurbished offers and exempt merchants, flags prices below MAP, and appends every flag to a CSV evidence log:
"""Flag sellers advertising below your MAP in a Google Shopping "Sellers" run. pip install apify-client"""
import csv
import os
import sys
from apify_client import ApifyClient
MAP_USD = {"Sony WH-1000XM5": 250.00} # made-up MAP for the example; use your policy's figures
EXEMPT = {"Sony"} # merchants you don't police (e.g. the brand's own store)
run = ApifyClient(os.environ["APIFY_TOKEN"]).run(os.environ["RUN_ID"])
rows = run.dataset().list_items(clean=True).items
violations = []
for row in rows:
if row.get("recordType") != "search-result":
continue
map_price = MAP_USD.get(row["keyword"])
for s in row.get("sellers") or []:
if s.get("condition"): # "refurbished", "used": skip unless your policy covers them
continue
if s["merchantName"] in EXEMPT or s.get("currency") != "USD" or s.get("price") is None:
continue
if map_price and s["price"] < map_price:
violations.append({
"checked_at": row["scrapedAt"], "keyword": row["keyword"], "listing": row["title"],
"merchant": s["merchantName"], "advertised": s["price"], "map": map_price,
"gap_pct": round(100 * (s["price"] - map_price) / map_price, 1),
"was_price": s.get("originalPrice"), "offer_link": s["url"], "google_page": row["url"],
"run_id": os.environ["RUN_ID"],
})
w = csv.DictWriter(sys.stdout, fieldnames=["checked_at", "merchant", "advertised", "map", "gap_pct", "listing"],
extrasaction="ignore")
w.writeheader()
w.writerows(violations)
if violations: # append the full rows to your evidence log
new_file = not os.path.exists("map_evidence.csv")
with open("map_evidence.csv", "a", newline="", encoding="utf-8") as f:
log = csv.DictWriter(f, fieldnames=list(violations[0]))
if new_file:
log.writeheader()
log.writerows(violations)
Output for the 2026-10-18 run (RUN_ID=FiUR4s8DgTfDEE02e):
checked_at,merchant,advertised,map,gap_pct,listing
2026-10-18T09:14:51.617Z,Store A,228,250.0,-8.8,Sony WH-1000XM5 Noise-Canceling Wireless Headphones
The $250 MAP is made up for this example, and the merchant names are replaced with "Store A" and "Store B". Sony's actual policy, if it has one for this model, isn't public, and nothing here says any retailer broke one. With that test number, the script flagged one offer and correctly skipped: Sony's own store (exempt), Target's and Electronic Express's refurbished/used offers (condition), and the offers at or above $250.
map_evidence.csv keeps the full record for each flag: checked_at, keyword, listing, merchant, advertised, map, gap_pct, was_price, offer_link, google_page and run_id. That's the core of what a MAP enforcement email needs. For a stronger record:
Save the Sellers input as a task and add an Apify schedule, for example 0 9 * * * (09:00 daily in the schedule's timezone).
The actor is pay per event. In the README's pricing table, a Google Shopping request costs $0.0045 on FREE and $0.0035 on GOLD (billed per successful request; failed ones aren't billed), a seller row $0.0024 and $0.0008, and the run start $0.005. The 2026-10-18 run billed 4 search-engine requests and 9 seller rows:
In Sellers mode each product costs one extra Google request, so cost grows with maxSearchEngineProducts × keywords, plus one seller row per store listed. Use maxSearchEngineSellersPerProduct to cap the long tail. Apify's free plan gives $5 of usage a month with no credit card; the actor has no in-actor free trial.
MAP pressure peaks when everyone discounts. Some brands also suspend or relax MAP for a set window, a "MAP holiday". For example, board-game publisher Iello suspended its MAP for Black Friday weekend in 2017, letting retailers "advertise games at prices below 20% off MSRP" (ICv2). If your policy has such a window, put its dates and temporary floor into the check instead of flagging authorised promotions. For the busiest window, add a second schedule to the same task such as 0 */3 20-30 11 *, every three hours from 20 to 30 November 2026 (88 runs in America/New_York; at the run size above, 88 × $0.0446 = $3.92 on FREE or 88 × $0.0262 = $2.31 on GOLD per keyword). Black Friday is Friday 27 November and Cyber Monday 30 November 2026. The holiday sales calendar has every event's window, and comparing Black Friday prices across stores uses the same Google Shopping data from the shopper's side.
title before you send anything.Related: competitor price monitoring, price drop alerts in Slack, and the e-commerce price tracker query builder.
Disclosure: I built the actor and this site. The flagging and evidence logic works with seller data from any source.
Sources: FTC: Manufacturer-imposed requirements, ICv2: Iello suspends MAP policy (2017), E-commerce Product Scraper Pro README (Sellers mode, pricing, supported sites, limitations), Apify docs: Schedules, and actor runs on 2026-10-18 and 2026-10-20.