Intelligence / Spy : quelle variable débloque quoi
Une seule question : « je pose cette clé, qu'est-ce qui se remplit ? »
Une seule question : « je pose cette clé, qu'est-ce qui se remplit ? »
Le record canonique compte 150 champs répartis en 14 sections
(src/services/algorithms/intelligence/canonical/sections.ts) : chiffres
rendus par node scripts/intelligence-coverage.mjs, à relire là plutôt qu'à
recopier ici (cette page a affiché « 128 champs / 13 sections » bien après
que le record en compte davantage). Ce document
relie chaque variable aux champs qu'elle débloque, à son coût réel, et, c'est
le point le plus utile, à l'alternative gratuite quand il en existe une.
La source de vérité machine reste
src/services/env-audit.ts (rendue sur
/admin/platform/env-audit) et
src/services/provider-health.ts
(rendue par GET /api/admin/providers). Ce document explique le pourquoi ;
ces deux surfaces disent l'état courant. Si les deux divergent, ce sont
elles qui ont raison.
Convention de lecture : Socle = rien ne fonctionne sans ; Levier = une section entière s'allume ; Confort = un repli honnête existe déjà.
1. Le socle — sans ça, la DB ne se remplit pas du tout
| Variable | Ce qu'elle débloque | Sans elle |
|---|---|---|
DATABASE_URL | tout | rien ne démarre |
KV_REST_API_URL + KV_REST_API_TOKEN | cache, budget-breaker providers, runs publicitaires parkés | chaque scan repaie tout, aucun garde-fou de budget |
QSTASH_TOKEN (+ QSTASH_CURRENT_SIGNING_KEY, QSTASH_NEXT_SIGNING_KEY) | le débit de découverte | le firehose moissonne des milliers de domaines et en indexe 3 par tick (repli inline borné) — voir intelligence-runtime-checklist.md §1 |
KV_* est injecté par l'intégration Vercel « Upstash ». QStash est un
produit Upstash séparé : ses clés ne sont PAS injectées automatiquement.
C'est le piège numéro un.
2. La couche de rendu, le multiplicateur silencieux
| Variable | Ce qu'elle débloque | Coût |
|---|---|---|
FIRECRAWL_API_KEY | 9 sondes qui exigent du HTML rendu : social-handles, reviews-vendor, pixel-detector, app-detector, emails, popup-detector, analytics, reviews-aggregation, traffic-provider | ~1 crédit par rendu, 5 sur un hôte muré : le mode anti-bot (proxy: "auto", posé quand la sonde demande stealth) paie d'abord le fetch à 1 crédit et ne rejoue par le pool résidentiel qu'après détection d'un blocage |
Sans elle ces sondes lisent la coquille non-hydratée : pixels, apps, handles sociaux et avis reviennent vides sur un store qui les expose pourtant. C'est le mode de panne le plus trompeur du pipeline, parce qu'il ressemble à « ce store n'a rien ».
Le chaînage direct → brightdata → firecrawl → brightdata-browser vit dans
src/lib/fetch-providers/. Un
cache de 90 s (response-cache.ts)
fait qu'un scan ne paie qu'un seul rendu de la home, pas neuf.
| Variable | Ce qu'elle débloque | Coût |
|---|---|---|
BRIGHTDATA_UNLOCKER_TOKEN + BRIGHTDATA_UNLOCKER_ZONE ou BRIGHTDATA_PROXY_URL | déblocage anti-bot (IP résidentielle) devant Firecrawl | facturé par requête réussie |
BRIGHT_DATA_USERNAME + BRIGHT_DATA_PASSWORD | Scraping Browser tier-3, dernier recours | plafonné par INTELLIGENCE_TIER3_BUDGET_CENTS_PER_MONTH |
À ne poser que si le diagnostic dit traffic.scrape_challenged ou si des
sondes remontent looksLikeChallenge: true. Un 404 n'est pas un blocage (§6).
Le seul cas où ces clés sont la SEULE réponse : les abonnés FB / Instagram
Mesuré le 2026-08-22 sur valisedemo, pas supposé. Meta publie les deux
compteurs (757 followers Facebook, 3,3 K Instagram) sur la page « À
propos de l'annonceur » de sa Bibliothèque publicitaire : c'est
vraisemblablement là que l'outil concurrent les lit. Trois portes y mènent,
les trois sont fermées à un serveur sans cookies :
| Surface | Réponse | Conclusion |
|---|---|---|
| Page Bibliothèque publicitaire | 403, 481 octets, sans cookies de session | fermée à notre runtime |
Page Plugin (plugins/page.php) | 200, ~18 Ko — mais coquille : le texte visible se réduit à « Facebook », zéro chiffre | hydratée en JS, exige un rendu |
| Profils instagram.com / facebook.com | 403 "we do not support this site" | Firecrawl refuse ces domaines par POLITIQUE — ni les en-têtes ni le tier de proxy n'y changent quoi que ce soit |
Donc FIRECRAWL_API_KEY, quel que soit son crédit, ne débloquera jamais ces
deux champs. BRIGHT_DATA_USERNAME + BRIGHT_DATA_PASSWORD sont la seule
voie : le Scraping Browser n'a pas cette politique de domaine. Il ouvrira
d'abord le Page Plugin, le moins cher des trois (un widget de 18 Ko, pas
une page de profil, et aucun mur de connexion à franchir) : le code le
demande déjà en rendu, donc rien d'autre n'est à modifier.
Tant que ces clés ne sont pas posées, social.*_followers reste absent, et
le diagnostic le dit désormais franchement (social.counts_unrenderable)
plutôt que de laisser croire à un mur qu'un meilleur parseur franchirait.
3. Publicités — la variable qui change tout pour un store européen
| Variable | Ce qu'elle débloque | Coût |
|---|---|---|
META_AD_LIBRARY_TOKEN | ads.active_creatives, networks, primary_format, hook_clusters, networks_detail — plus la portée UE (reachBand) que le scraper ne porte pas | gratuit |
APIFY_TOKEN + APIFY_AD_LIBRARY_ACTOR_ID | les mêmes champs, couverture mondiale | payant, par run (navigateur, plusieurs minutes) |
APIFY_TIKTOK_ADS_ACTOR_ID | la ligne TikTok de ads.networks_detail | payant |
APIFY_GOOGLE_ADS_ACTOR_ID | la ligne Google — les créatives, pas la présence (voir ci-dessous) | payant |
APIFY_PINTEREST_ADS_ACTOR_ID | la ligne Pinterest | payant |
META_AD_LIBRARY_TOKEN est la meilleure ligne de ce document. Depuis le
Digital Services Act, Meta doit publier les publicités commerciales,
pas seulement politiques, pour toute annonce diffusée dans l'UE ou au
Royaume-Uni. L'API officielle ads_archive les rend donc accessibles
gratuitement, en un appel synchrone, avec la portée et le ciblage en prime.
Hors UE/UK le même appel ne renvoie que du politique : l'adaptateur
meta-graph.ts
restreint donc ad_reached_countries à l'UE/UK et s'abstient ailleurs
plutôt que de renvoyer un corpus qui n'a rien à voir.
L'enchaînement est : gratuit d'abord, payant seulement si le gratuit n'a
rien trouvé (ad-library/index.ts). Un store français comme
valisedemo.com est donc entièrement couvert sans dépenser un centime,
et Apify ne se déclenche que pour les marchés hors UE.
Bénéfice secondaire, et il est structurel : l'API officielle renvoie
ad_creative_link_captions, c'est-à-dire le domaine affiché par
l'annonceur. L'attribution passe donc d'une comparaison de noms
(« Valise Demo » ≈ n'importe quel annonceur employant ces mots, c'est ce
qui avait produit 2 800 créatives fantômes) à une comparaison d'hôtes.
Prouvable, pas plausible.
Comment l'obtenir : vérifier son identité sur facebook.com/ID → accepter
les conditions sur facebook.com/ads/library/api → générer un token
utilisateur longue durée. Compter 1 à 2 semaines de validation. Un token
applicatif ({app_id}|{app_secret}) est refusé par cet endpoint :
META_APP_ID / META_APP_SECRET ne peuvent pas s'y substituer.
Google Ads : la présence est gratuite, les créatives ne le sont pas
Le Google Ads Transparency Center n'expose aucune API publique. La
seule voie câblée vers ses créatives est un actor Apify payant
(APIFY_GOOGLE_ADS_ACTOR_ID). Aucune clé gratuite n'existe et aucun
scraper ne la remplace honnêtement.
Ce qui est gratuit et certain, en revanche : le tag de conversion
AW-… que la boutique porte elle-même. Personne n'installe le tag de
conversion d'un réseau sur lequel il n'achète pas. Il est déjà extrait
(stack.tracking_ids.google_ads) par le lecteur de conteneur GTM et le
détecteur de pixels, y compris derrière un Consent Mode, où la page
seule ne montre rien.
La bande « Réseaux » de l'onglet Ads rend donc deux niveaux de preuve qui ne se confondent jamais :
| Niveau | Ce qu'on affiche | Quand |
|---|---|---|
| Mesuré | le nombre de créatives actives | une bibliothèque publicitaire a répondu pour cet annonceur |
| Taggé | l'identifiant du tag + « créatives indisponibles » | seule la présence est établie |
Un réseau sans aucune preuve n'a pas de ligne du tout. Écrire « Google · 0 » affirmerait que la boutique n'achète pas sur Google, ce qui est exactement l'inverse de ce que le tag prouve.
4. Trafic — 6 champs, et une vérité désagréable
| Variable | Ce qu'elle débloque en plus du gratuit | Coût |
|---|---|---|
SIMILARWEB_API_KEY | visits_series (la courbe multi-mois) + des quotas et une fiabilité que le scrape n'a pas | abonnement API |
DATOS_API_KEY | idem | abonnement |
SEMRUSH_API_KEY | idem (+ sert aussi de repli SEO, §5) | abonnement |
Colonne libellée « en plus du gratuit » à dessein. monthly_visits,
top_country, top_source, paid_share, country_breakdown et
visits_change_pct arrivent sans aucune clé, par le scrape de la page
publique : un scan live de valisedemo a remonté 724 visites / FR 100 %
avec zéro variable posée. Les lister comme « débloqués par la clé » revient
à faire payer un champ déjà obtenu ; seule la série temporelle l'est
réellement.
Extension / hub lookup?rich=1. The Spy panel and the hub read the
same HubStore projection (projectVisitsSeries). A monthly KPI with
visits_series: null is not a missing extension wire: the free scrape
has fewer than two months, none of the three keys above is set, or the
panel has no coverage (traffic.no_coverage). Proof procedure:
2026-09-10-spy-ext-coherence.md.
Priorité de résolution : SimilarWeb → Datos → Semrush
(traffic-providers/types.ts). Sans aucune clé, la sonde retombe sur le
scrape gratuit de la page publique SimilarWeb.
La vérité désagréable. Aucune de ces clés ne produira de chiffre pour un
petit store. Les panels ne mesurent que ce qu'ils observent, et un storefront
sous leur plancher n'a pas de page publique : SimilarWeb répond 404, ce
qui n'est ni un blocage ni un bug de parser. Le diagnostic distingue
désormais ce cas (traffic.no_coverage) de traffic.scrape_challenged.
Recalibrage, ce que ce document a affirmé de trop
Une version antérieure de cette section concluait que le trafic de
valisedemo.com « n'existe nulle part » et qu'il ne fallait acheter aucune
clé. C'était une inférence, pas une observation. Le code de classification
est juste ; son application à ce store précis ne l'était pas : le statut HTTP
réellement renvoyé pour ce domaine n'a jamais été relevé.
Le fait rapporté par l'opérateur, l'outil de référence du marché affiche ce store complet, tranche dans l'autre sens. Deux lectures possibles, et il faut mesurer avant de choisir :
- Ils estiment le trafic à partir de signaux de première main (leur extension Chrome constitue un panel propriétaire), auquel cas la parité passe par notre propre estimation, pas par un abonnement.
- Une source couvre ce store et n'est pas câblée ici, auquel cas c'est une lacune d'implémentation.
Dans les deux cas la conclusion « la donnée n'existe pas » était fausse. La règle : quand un concurrent affiche une valeur pour un store, la donnée est atteignable ; la question est par quel chemin, jamais si.
Pistes gratuites déjà évaluées, avec leur limite connue :
| Source | Ce qu'elle donne | Limite |
|---|---|---|
| Cloudflare Radar Ranking | rang de domaine, gratuit avec un compte | top ~1 M |
| Tranco | liste de rangs, CSV gratuit | top ~1 M |
CrUX (GOOGLE_PAGESPEED_API_KEY, déjà posée pour les Web Vitals) | présence dans le dataset Chrome | signal de plancher, pas un nombre de visites |
Ces limites sont documentées par leurs éditeurs ; elles n'ont pas été
vérifiées contre valisedemo.com en particulier. À faire avant toute
décision d'achat, et avant de re-citer ce tableau comme un verdict.
5. SEO hors-page — 6 champs
| Variable | Ce qu'elle débloque | Coût |
|---|---|---|
AHREFS_API_KEY | seo.organic_keywords, organic_traffic, backlinks, referring_domains, domain_rating, top_ranking_keywords | le plus cher |
SEMRUSH_API_KEY | idem | intermédiaire |
DATAFORSEO_API_KEY | idem (base64 de login:password) | le moins cher, à la requête |
Priorité : Ahrefs → Semrush → DataForSEO (seo-providers/types.ts). Les
13 autres champs SEO (title, meta, h1, canonical, hreflang, schema,
word count, liens internes, ratio alt, blog, indexable, keywords cibles, top
pages) sont on-page : ils se remplissent gratuitement, sans aucune clé.
Recommandation : DataForSEO, facturé à l'appel. Sur ces six champs les
trois fournisseurs racontent la même histoire ; payer un abonnement Ahrefs
pour un domain_rating n'a pas de sens à ce stade.
Alternative gratuite partielle : OpenPageRank reconstruit un score
d'autorité 0-10 depuis le graphe ouvert de Common Crawl, en lot et sans frais.
Il couvre honnêtement domain_rating, pas les cinq autres champs. Non câblé
aujourd'hui : c'est un candidat d'implémentation, pas une variable à poser.
6. Stores similaires
| Variable | Ce qu'elle débloque | Coût |
|---|---|---|
UPSTASH_VECTOR_REST_URL + UPSTASH_VECTOR_REST_TOKEN | l'index d'embeddings — toute la recommandation « stores similaires » | tier gratuit Upstash suffisant au départ |
Sans ces deux clés, getIndex() renvoie null et chaque appel à
searchSimilar se termine par un tableau vide. Aucune erreur, aucun log
d'alerte : la fonctionnalité est simplement absente de l'interface. C'est le
meilleur rapport valeur/effort de tout ce document : deux clés, un tier
gratuit, une section entière.
À ne pas confondre avec la section
graph(§8), qui ne dépend d'aucune variable.
7. Confort — un repli honnête existe déjà
| Variable | Ce qu'elle débloque | Sans elle |
|---|---|---|
KLAVIYO_BENCHMARK_API_KEY | email.niche_benchmarks en direct | snapshot embarqué, mis à jour trimestriellement — parfaitement exploitable |
APIFY_SHOPIFY_DATASET_ID | backfill de ~500 k domaines | crt.sh + Common Crawl (gratuits) continuent de moissonner |
COMMON_CRAWL_INDEX | épingle un snapshot récent | un snapshot récent est codé en dur |
OPENCORPORATES_API_TOKEN | rattachement d'entité légale | champ absent |
CLICKHOUSE_URL | rien aujourd'hui : déclarée, sans effet. getTimeSeriesStore() retourne postgresStore dans les DEUX branches (intelligence/time-series/index.ts), le driver ClickHouse est un stub et le log annoncé n'est pas émis | partitions Postgres, exactement pareil |
INTELLIGENCE_VISION_BUDGET_CENTS_PER_STORE | plafond d'analyse visuelle des créatives | 100 c/store |
INTELLIGENCE_CREATIVE_LABELS | active les étiquettes IA des créatives (accroche, angle, étape du funnel, offre, urgence) ; exige aussi AI_GATEWAY_API_KEY | désactivé : aucune créative n'est étiquetée, les facettes restent vides |
INTELLIGENCE_CREATIVE_LABELS_BUDGET_CENTS_PER_DAY | plafond quotidien des appels d'étiquetage | 100 c/jour ; 0 arrête l'étiquetage |
INTELLIGENCE_ANON_SECRET | HMAC des handles anonymisés | à poser malgré tout : sans secret, un handle « anonyme » est un hash devinable sur l'espace des domaines Shopify |
JUDGE_ME_API_TOKEN | sur vos propres stores uniquement : photo_ratio, response_rate, verified_buyer_ratio, et l'échantillon de textes qui alimente le sentiment | le compte et la note se lisent sur le badge que Judge.me a rendu dans la page — voir ci-dessous |
Judge.me authentifie, et c'est la seule chose qui compte ici
L'endpoint judge.me/api/v1/widgets/preview_badge a été documenté dans ce
repo comme « public, sans auth ». C'est faux. Appelé sans jeton il répond,
pour n'importe quelle boutique :
{"error":"Failed to authenticate. Shop domain or Api Token is wrong"}
Le jeton en question est celui du marchand. Sur une surface d'intelligence
concurrentielle on ne l'a jamais : donc l'appel était un 4xx garanti sur chaque
store Judge.me rencontré, et son résultat vide se lisait en aval comme « cette
boutique n'a pas d'avis ». La sonde ne le tente plus sans jeton et nomme la
raison (widget_reason: "judge-me-api-token-missing").
Ce qui marche sans aucune clé, et qui est la seule source Judge.me pour un
concurrent : le compte et la note que le widget de Judge.me a lui-même
écrits dans la page (data-number-of-reviews, data-average-rating), lus au
rendu que FIRECRAWL_API_KEY produit déjà. Un store dont la page d'accueil ne
porte que des badges par produit, sans widget agrégé, n'expose donc pas de
headline, chez nous comme chez un concurrent.
La date de création ne coûte rien, et n'était pas lue
identity.domain_registered_at et identity.domain_registrar viennent du
registre lui-même, en RDAP (RFC 9082 / 9083) : HTTPS, JSON, aucune clé,
aucun contrat, aucun quota facturé. Ils n'apparaissent donc dans aucun
tableau ci-dessus, et c'est délibéré : il n'y a pas de variable à poser.
Cette page a longtemps laissé croire le contraire par omission : l'âge d'une
marque semblait dépendre d'archive.org seul, donc d'un signal qu'aucune clé
n'améliore. En réalité le registre répond gratuitement, et il répond mieux :
la première capture d'archive.org est une borne haute (une petite marque
est crawlée des mois après son ouverture), là où la création du domaine est
une borne basse datée à la seconde. Voir
intelligence-pipeline.md §5.2.
7 bis. Plafonds et bornes : les variables qui ne remplissent rien
Six variables déclarées dans src/env/server.ts
manquaient à ce document. Elles ne débloquent aucun champ : elles bornent le
pipeline, et c'est exactement ce qu'un opérateur vient régler ici.
| Variable | Ce qu'elle borne | Défaut |
|---|---|---|
INTELLIGENCE_SPY_FULL_SCANS_PER_MONTH | scans full de stores espionnés par mois | 120 (~4/jour) |
INTELLIGENCE_PROVIDER_BACKFILL_PER_DAY | scans ciblés (sondes trafic / pubs seules) qui remplissent les fiches déjà indexées quand une source est posée, lancés par refresh-warm ; exige KV (sans compteur partagé, rien ne tourne) ; 0 coupe le rattrapage | 40 |
INTELLIGENCE_CATALOG_MAX_PAGES | pages de catalogue lues par store | 25 |
INTELLIGENCE_TRAFFIC_HISTORY_MONTHS | profondeur d'historique de trafic demandée | 12 |
INTELLIGENCE_HISTORY_RETENTION_DAYS | rétention de l'historique d'intelligence | 180 |
INTELLIGENCE_LIVENESS_BATCH | taille de lot du balayage de liveness | 1000 |
INTELLIGENCE_SUPPRESSED_DOMAINS | domaines exclus du pipeline (liste séparée par des virgules) | vide |
Ces deux plafonds-là exigent Upstash.
INTELLIGENCE_SPY_FULL_SCANS_PER_MONTHetINTELLIGENCE_TIER3_BUDGET_CENTS_PER_MONTHcomptent dans un compteur Redis partagé. SansKV_REST_API_URL/KV_REST_API_TOKEN(ou leurs équivalentsUPSTASH_REDIS_REST_*), il n'y a pas de compteur partagé du tout :rateLimitretombe sur uneMapde portée module, donc par instance serverless, remise à zéro à chaque cold start.Depuis
intelligence/0351, les deux gardes refusent dans ce cas au lieu d'autoriser : le scanspy-fullrendguard_unavailable, le tier-3 aussi. Avant, ils dépensaient — le plafond mensuel de 120 scans devenait 120 scans par lambda, et les $50 de tier-3 devenaient $50 par lambda, sans une ligne de log. Poser ces variables sans Upstash ne borne donc plus rien du tout, et ne dépense plus rien non plus.
8. Ce qu'aucune variable ne débloque
Trois familles de champs ne dépendent d'aucune clé. Les chercher dans ce document, c'est chercher au mauvais endroit.
Le temps. prediction.* (9 champs), catalog.inventory_velocity,
best_seller_velocity, recent_diffs mesurent un mouvement. Ils exigent
au moins deux scans espacés ; au premier scan ils sont légitimement vides, et
les crons de rafraîchissement les remplissent tout seuls. Ils ne sont jamais
fabriqués à partir d'un seul point.
Le volume. La section graph (edges, same_owner_domains,
network_domains, clone_candidates, shared_identifiers, cluster_id)
relie un store aux autres via l'index inversé StoreSignalIndex
(identifiants de tracking partagés, comptes sociaux, empreinte thème+apps,
recouvrement de produits). Un graphe se construit à partir de voisins : tant
que peu de stores ont reçu un scan profond, il n'y a personne à relier et
related_count: 0 est la réponse correcte. related_count est d'ailleurs
toujours émis, même à 0 : c'est le marqueur « le graphe a tourné » qui
distingue « aucun réseau trouvé » de « jamais analysé ». La cure est le débit
de découverte, donc §1 (QSTASH_TOKEN), pas une nouvelle clé.
Le store lui-même. Un marchand qui masque inventory_quantity, ne tague
pas ses produits ou n'a pas d'app d'avis laisse ces champs vides chez tout le
monde, nous comme les concurrents. C'est une absence honnête, pas une panne.
9. Le cas valisedemo.com
Store français, jeune, catalogue restreint. Référence de parité : l'outil de référence du marché affiche ce store complet. Tant que ce n'est pas le cas ici, l'hypothèse par défaut est un défaut de notre côté, code ou quota, et non une donnée introuvable.
| Section | État | Levier |
|---|---|---|
| identity, catalog, stack, commerce, seo on-page | plein | déjà là (+ FIRECRAWL_API_KEY) |
| social, email | plein si le store expose des comptes sociaux | FIRECRAWL_API_KEY |
| reviews | app détectée (judge-me), aucun chiffre — pas de page Trustpilot, et la page d'accueil ne porte pas de widget agrégé Judge.me. Aucune clé n'y change quoi que ce soit (§7) | mesuré le 27/08/2026 |
| ads | gratuit pour un store UE | META_AD_LIBRARY_TOKEN |
| similar stores | vide | UPSTASH_VECTOR_REST_* |
| seo hors-page (6) | vide | DATAFORSEO_API_KEY |
| traffic (6) | vide — cause non tranchée, voir §4 | à mesurer, pas à acheter |
| prediction (9), velocity | se remplit tout seul | 2ᵉ scan |
| graph (6) | vide tant que le voisinage est vide | QSTASH_TOKEN (§1) |
Ordre d'action :
META_AD_LIBRARY_TOKEN— gratuit, débloque la section vitrine. Sans elle,ads_absencerestenot_observed/quarantinedetcreatives[]vide : l'extension garde Import Library en fallback (preuve :2026-09-10-spy-ext-coherence.md).UPSTASH_VECTOR_REST_URL+_TOKEN— tier gratuit, débloque les similaires.QSTASH_TOKEN— remplit la DB, donc à terme le graphe.DATAFORSEO_API_KEY— 6 champs SEO, facturé à l'appel.- Trafic : relever le statut HTTP réel avant toute décision (§4).
Deux blocages qui n'étaient ni des clés ni des crédits
Ils expliquent pourquoi des rescans répétés ne changeaient rien, et ils sont le rappel que ce document ne doit jamais être le premier suspect :
- Le verrou de fraîcheur. Une section était considérée « fraîche » dès
qu'un seul champ était rempli, ce qui faisait sauter la sonde à chaque
scan suivant : les autres champs de la section ne pouvaient donc plus jamais
se remplir. Cela touchait exactement les six sections concernées par
skipIfFresh: ads, reviews, seo, social, traffic, catalog. Corrigé : une section n'est sautée que complète et fraîche. - Le cooldown Apify de 6 h. Il est posé dès qu'un run démarre, même s'il
ne rend rien. Une rafale de rescans manuels retombe donc sur
ads.budget_skippedpendant six heures. C'est délibéré, c'est ce garde-fou qui a arrêté la dépense, mais il faut le lire dans lediagnosisau lieu de conclure que le store n'a pas de publicités.
10. Vérifier, sans deviner
GET /api/admin/providers # configured / breaker / live, par provider
GET /admin/platform/env-audit # variables manquantes + impact
POST /api/admin/intelligence/scan # diagnosis[] + coverage.absentFields[]
Le diagnosis du scan nomme la cause et la variable qui la corrige
(fix_env). Deux codes à savoir lire, parce qu'ils se ressemblent et
appellent des gestes opposés :
traffic.no_coverage— SimilarWeb n'a pas de page pour ce domaine (404). Ni une clé, ni un proxy, ni un correctif de parser ne changent ce qu'eux renvoient. Ce n'est pas pour autant un verdict sur la donnée elle-même : si un concurrent affiche une valeur pour ce store, elle est atteignable autrement (§4).traffic.scrape_challenged— un mur anti-bot s'est interposé. La donnée existe, l'accès manque :BRIGHTDATA_*ou une clé fournisseur.
coverage.absentFields liste nommément les champs vides par section : c'est
ce qu'il faut lire avant d'ouvrir ce document, pas après.