Search online stores and their traffic
search_shopsSearch ONLINE STORES — the same catalogue as the website's /shops page (not every domain: general sites such as google.com or youtube.com are not in it). Each row carries traffic, commerce and advertising intelligence for one store domain. Shops advertising now in a country ("shops with fresh/active ads in Mexico"): country= + has_ads=true (only shops with ACTIVE ads now; add min_ads=N for a floor) + sort_by=ads — do NOT use search_ads for this; there is no separate freshness-window filter. visits is a MONTHLY estimate for traffic_as_of (not live traffic); fetched_at is ingestion time. Judge every estimate using traffic_quality, traffic_confidence, traffic_is_small, traffic_is_data_from_ga, traffic_data_status and history. traffic_paid_share is display + paid-search + paid-social share; trust it only when traffic_sources_available=true. visits_growth_pct is latest-vs-previous month PERCENT; min_growth and sort_by=growth only return growth_qualified rows (current cohort, contiguous 3-month window, previous month >=10k, non-small estimate, confidence >=0.60). category is an estimated SITE category and may be missing/wrong; ai_category is Spytrend's AD category and is preferred for ad-market discovery. created_from/to filter domain_created: best available registration date of the REGISTRABLE ROOT, not product/subdomain launch or Spytrend first-seen. The ClickHouse row does not retain whether that date came from the preferred registry lookup or the legacy fallback. traffic_start_max compares the current estimate with the MAXIMUM of both preceding complete months and excludes stale/low-quality windows; combine with traffic_end_min. ads_monthly counts ads first observed by Spytrend (first_parsed_date), and each point has is_complete=false for the open current month. fb_signal is correlation_only, not causal attribution; honest statuses are correlated_growth, ad_growth_ahead, ad_growth_flat_traffic, ad_growth_declining_traffic, traffic_growth_without_fb_growth, stable_or_mixed and insufficient_signal. sort_by=relevance REQUIRES ai_category and is rejected otherwise. Sorts: visits/revenue/growth/ads/rank/backlinks/ai_traffic/products/fb_score/per_ad/relevance; sort_by=ads orders by the number of ACTIVE ads now (active_ads), not by total_ads — never describe it as 'sorted by total number of ads'; sort_by=revenue and min_revenue use website_value — the estimated VALUE of the site in USD, NOT revenue, and outliers with tiny traffic are possible. country/country_exclude match the shop's MAIN visitor country (top_country). An empty page carries a note explaining why. product_count is the number of products shown on the website shop card (the larger of the crawler counter and the real catalog size products_total). a separate legacy snapshot is kept alongside; never substitute its similarly named traffic fields for the primary visits/traffic_as_of contract. Returns total, has_more and offset; total is the exact number of matching stores and has_more is true whenever total > offset+rows. FREE SAMPLE: without a Shops subscription the catalogue returns a short preview (a few rows) whatever the limit and deeper offsets come back empty — the result then carries a note "Free sample: N of TOTAL…" and params.normalized limit (requested→delivered); say it is a sample of TOTAL stores, never that only N exist. Use get_shop for the full source payload. Saving shops is free. FREE PLAN COUNTS: when the plan's archive window narrows a request, pagination.total_status is "restricted" and meta.plan_window_cutoff names the boundary — the count then describes the window actually searched, NOT the one requested, so a zero means "nothing in the archive window" and never "nothing exists". QUOTA: 1 MCP credit per DELIVERED result from your plan balance (free starter: 500 MCP credits lifetime; paid plans: 40,000/month; short pages auto-refund — you pay only for results you receive). Default page is 20 results = 20 MCP credits; pass limit (1–200) to size it. get_usage is free. Autonomous agents must be linked to a spytrend account to access data — an unlinked agent gets an actionable connect-your-account refusal (create agent credentials at spytrend.com/settings?tab=ai, or a human claims it by client_id), NOT a server error. Calls are rate-limited per authenticated user (deployment defaults: 60/minute and 1000/hour); a rate-limit refusal is an MCP tool error with structured error.code=rate_limit_exceeded, scope, window and retry_after_seconds. CONCURRENCY: heavy analytical calls (get_trends, search_ads, search_creatives) are admitted ONE AT A TIME per account — fanning out 5-10 of them in parallel does not go faster, it returns admission refusals for all but one. Issue heavy calls sequentially; light lookups (get_ad, get_advertiser, get_usage) are not gated. PRICING: price × number of filters set (min 1), on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | substring search on the normalized domain; URLs are normalized to their host | |
| limit | No | max results (default 20, at most 200; each delivered result costs 1 MCP credit). Without a Shops subscription the catalogue answers a free sample of a few rows whatever the limit: params.normalized then reports limit as requested→delivered, note says the page is a free sample and has_more stays true while total exceeds offset+rows. | |
| saved | No | saved scope selector. Use saved=all to restrict results to shops saved in ANY favourites folder. | |
| offset | No | pagination offset (0-based) | |
| pixels | No | comma-separated pixel identifiers to filter by | |
| country | No | ISO-2 country code (any case; unknown codes are rejected) — keep only shops whose MAIN visitor country (top_country) is this country, NOT every shop with some traffic there. For small sites top_country can come from the site's country ranking instead of visitor shares, so a small shop whose visitors mostly come from another country may be listed under the wrong one | |
| has_ads | No | true = only shops with ACTIVE ads now (the site's 'Has active ads' chip) | |
| min_ads | No | minimum number of ads | |
| socials | No | comma-separated social-media handle filters | |
| sort_by | No | order by: visits (default), revenue (= website_value, the estimated site VALUE in USD, not revenue), growth, ads (= number of ACTIVE ads now, active_ads — not total_ads), rank, backlinks, ai_traffic, products, fb_score, per_ad or relevance; relevance REQUIRES ai_category and is rejected without it | |
| category | No | estimated site-category filter; may be missing or misclassified, so prefer ai_category for ad-market discovery | |
| platform | No | commerce platform the site runs on: Shopify, WooCommerce, WordPress, Wix, Squarespace, Magento, PrestaShop or BigCommerce | |
| fb_status | No | observed ads/traffic relationship: correlated_growth, ad_growth_ahead, ad_growth_flat_traffic, ad_growth_declining_traffic, traffic_growth_without_fb_growth, stable_or_mixed or insufficient_signal; correlation only | |
| folder_id | No | restrict results to shops saved in this favourites folder UUID. Mirrors the /shops folder view. | |
| created_to | No | registrable-root registration date on/before YYYY-MM-DD; NOT product/subdomain launch; per-row RDAP/WHOIS-vs-legacy provenance is unavailable | |
| max_bounce | No | maximum bounce rate in PERCENT (0-100) — max_bounce=30 keeps only sticky sites, the reason this control exists. The server converts it to the fraction the column stores. | |
| max_growth | No | upper end of the traffic-growth range (percent). The /shops panel has BOTH ends; pair it with min_growth for a band such as 10..50. | |
| max_per_ad | No | maximum visits-per-ad efficiency | |
| max_visits | No | maximum monthly visits | |
| min_bounce | No | minimum bounce rate in PERCENT (0-100), matching the visible /shops bounce slider — min_bounce=70 keeps only high-bounce sites. The server converts it to the fraction the column stores. | |
| min_growth | No | minimum latest-vs-previous monthly visits growth PERCENT; only current-cohort growth_qualified rows pass (contiguous 3 months, previous >=10k, non-small, confidence >=0.60) | |
| min_per_ad | No | minimum visits-per-ad efficiency (traffic / active ads) | |
| min_visits | No | minimum monthly visits | |
| sort_order | No | sort direction: asc or desc (default desc) | |
| ai_category | No | AI category slug the shop's ads belong to (e.g. ecommerce_and_retail) | |
| min_revenue | No | minimum site value estimate in USD (website_value — the estimated VALUE of the site, not monthly revenue; the row field is website_value) | |
| shopify_app | No | Shopify app slug filter (shops using this app) | |
| created_from | No | registrable-root registration date on/after YYYY-MM-DD; NOT product/subdomain launch or Spytrend first-seen; per-row RDAP/WHOIS-vs-legacy provenance is unavailable | |
| has_products | No | true = only shops with a product catalog in our database | |
| min_products | No | minimum number of catalogued products | |
| shopify_plan | No | Shopify plan name filter (e.g. Basic, Shopify, Advanced) | |
| min_backlinks | No | minimum total backlinks | |
| shopify_theme | No | Shopify theme slug filter | |
| has_ai_traffic | No | true = only shops receiving AI-referred traffic (ai_traffic_share > 0) | |
| has_trustpilot | No | true = only shops with Trustpilot reviews | |
| country_exclude | No | ISO-2 country code (any case) — drop shops whose MAIN visitor country (top_country) is this country | |
| traffic_end_min | No | latest monthly estimate at traffic_as_of is at least this value; combine with traffic_start_max | |
| traffic_start_max | No | maximum allowed baseline traffic, where baseline=max(two complete months before traffic_as_of); stale, low-quality, incomplete and non-contiguous windows are excluded; combine with traffic_end_min | |
| min_trustpilot_rating | No | minimum Trustpilot rating (0-5) | |
| exclude_infrastructure | No | drop rows that are transit rather than an offer — link shorteners / link-in-bio, app stores and marketplaces, social networks and messengers, ad servers. Every row also carries surface_role (destination | redirect | store | social | adserver; absent for an ordinary merchant site) so you can filter yourself instead. NOTE: rows are dropped after the page is fetched, so an excluded page can return fewer than limit rows — page on has_more/offset, not on row count. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| data | No | ||
| meta | No | ||
| note | No | ||
| error | No | Present only when isError is true: machine-readable failure. The human explanation stays in content. | |
| total | No | ||
| offset | No | ||
| params | No | Request parameter echo: applied = parameters that shaped this result; normalized = parameters rewritten before applying (alias, type coercion, resolved id); ignored = parameters that were accepted but NOT applied, with the reason. | |
| has_more | No | ||
| addon_hints | No | Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about. |