Référence complète du CLI
Voici la référence complète du CLI d'Ads Uploader. Pour une introduction et un guide d'installation, consulte Configuration du CLI.
Commandes
Authentification
| Commande | Ce qu'elle fait |
|---|---|
ads login | S'authentifie via le navigateur (ouvre ton navigateur par défaut) |
ads logout | Efface les identifiants enregistrés |
ads whoami | Affiche l'e-mail connecté, le compte publicitaire par défaut et l'URL de l'API |
ads config | Indique si tu es connecté, ton e-mail, le compte publicitaire par défaut, l'URL de l'API et le dossier de configuration (~/.config/adsuploader/) |
ads --version | Affiche la version installée du CLI |
Un jeton de connexion dure 30 jours. Ensuite, relance ads login.
Navigation
| Commande | Ce qu'elle fait |
|---|---|
ads accounts | Liste tous les comptes publicitaires connectés à ton compte Meta |
ads accounts:refresh | Récupère tout de suite la liste des comptes publicitaires auprès de Meta, par exemple après avoir obtenu l'accès à un nouveau compte publicitaire |
ads account <id> | Définit un compte publicitaire par défaut pour les prochaines commandes |
ads pages | Liste les Pages Facebook avec lesquelles tu peux faire de la publicité, avec tout compte Instagram lié, à utiliser avec les substitutions de profil |
ads targeting:search "Austin" --type city | Trouve les clés de ville pour le ciblage des ensembles d'annonces |
ads targeting:search "90210" --type zip | Trouve les clés de code postal pour le ciblage des ensembles d'annonces |
ads targeting:search "advertising" --type detailed | Trouve les ID et les types de ciblage détaillé |
ads campaigns | Liste les campagnes actives |
ads campaigns --status all | Inclut aussi les campagnes inactives |
ads campaigns --search "text" | Filtre les campagnes par nom |
ads campaign <id> | Affiche les ensembles d'annonces d'une campagne |
ads adsets --campaign <id> | Liste les ensembles d'annonces d'une campagne (accepte --search, --status) |
ads adset <id> | Affiche les annonces d'un ensemble d'annonces |
ads ad <id> | Affiche tous les détails d'une annonce, y compris les paramètres du créatif |
ads presets | Liste tes préréglages d'API enregistrés |
ads presets <id> | Affiche les détails d'un préréglage précis |
ads presets:save --from-ad <adId> --name "Preset Name" | Enregistre une annonce existante comme préréglage d'API. Ajoute --share pour le partager avec ton équipe (offres équipe). |
ads text-presets | Liste tes préréglages de texte enregistrés |
ads text-presets <id> | Affiche les détails d'un préréglage de texte précis |
ads uploads | Liste les lots d'import récents (20 par défaut, modifiable avec --limit <n>) |
ads uploads <batchId> | Affiche les détails d'un lot (fichiers, variantes, hashes) |
Saved Builds
Les builds enregistrés sont les mêmes que ceux que tu vois dans la fenêtre Saved Builds de l'uploader web. Consulte Saved Builds pour comprendre leur fonctionnement.
| Commande | Ce qu'elle fait |
|---|---|
ads builds | Liste tes builds enregistrés (filtre avec --account <id>) |
ads builds <buildId> | Affiche un build enregistré, avec son numéro de révision actuel |
ads builds:create --spec spec.json --name "Summer Sale" | Enregistre une spec comme nouveau build. builds:save est un alias. Accepte aussi --notes, --account et --web-state <file>. |
ads builds:update <buildId> --spec-patch patch.json --expected-revision <n> | Modifie une partie de la spec d'un build avec un JSON merge patch. --expected-revision est obligatoire et t'empêche d'écraser une modification plus récente faite par quelqu'un d'autre. |
ads builds:update <buildId> --name "New name" | Renomme un build. --notes, --spec <file> (remplace toute la spec) et --web-state <file> fonctionnent aussi. |
ads builds:fork <buildId> | Copie un build dans un nouveau brouillon, sans modifier l'original |
ads builds:delete <buildId> | Supprime un build enregistré |
Passe - à la place d'un nom de fichier pour lire le JSON depuis stdin. Pour lancer un build, utilise ads create --build <buildId> (ou create:preview).
Import de médias
| Commande | Ce qu'elle fait |
|---|---|
ads upload <inputs...> | Importe des chemins locaux et des URL HTTPS publiques dans ton compte publicitaire |
ads upload ./directory/ | Importe un dossier entier |
ads upload:drive <folderUrl> | Importe un dossier Google Drive public en tâche de fond (accepte --account, --json et --api-timeout) |
ads upload --retry-failed [batchId] | Relance les fichiers en échec de ton dernier lot d'import en échec, ou du lot que tu indiques. Ne passe pas de fichiers avec ce flag. |
Les arguments HTTPS, y compris les liens publics vers des fichiers Google Drive, sont détectés automatiquement. Tu peux mélanger chemins locaux et URL : les fichiers locaux sont importés d'abord, puis le serveur importe les URL dans le même lot, pour que le regroupement fonctionne sur toutes les entrées. Les dossiers Drive publics doivent être partagés en Anyone with the link (Viewer) (tous les utilisateurs disposant du lien, en lecture).
Les fichiers locaux sont préparés en parallèle, et les échecs réseau passagers sont relancés automatiquement avec un délai croissant. Les imports d'URL et de dossiers Drive utilisent des pipelines de fichiers parallèles limités, dans une tâche de fond, pendant que le CLI affiche un compteur terminés/total et chaque fichier en cours. Tu as rarement besoin de toucher à ces flags, mais ils sont disponibles :
| Flag d'import | Description |
|---|---|
--concurrency <n> | Nombre de fichiers préparés en parallèle, de 1 à 6 (par défaut : 4). Les grosses vidéos sont automatiquement ralenties pour rester dans les limites de mémoire. |
--upload-timeout <ms> | Délai d'expiration de l'import par fichier (par défaut : 120000) |
--api-timeout <ms> | Délai d'expiration des requêtes API en millisecondes (par défaut : 60000). Aussi disponible sur upload:drive. Tu peux le définir pour toutes les commandes avec la variable d'environnement ADS_API_TIMEOUT_MS. |
Règles d'import :
- Chaque fichier peut peser jusqu'à 4 Go.
- Images :
.jpg,.jpeg,.png,.gif,.bmp,.webp. Vidéos :.mp4,.mov,.avi,.mkv,.webm,.m4v. - Les liens doivent utiliser
https://. Tout le reste est traité comme un chemin local. - Une image nommée comme sa vidéo avec
_thumbnailen plus (par exemplepromo_thumbnail.jpgpourpromo.mp4) est attachée à cette vidéo comme miniature personnalisée, au lieu d'être importée comme un média séparé. - Appuyer sur Ctrl-C pendant l'import d'un lien ou d'un dossier Drive demande au serveur d'arrêter l'import. Les fichiers déjà terminés restent dans le lot.
Création d'annonces
| Commande | Ce qu'elle fait |
|---|---|
ads create spec.json | Crée des annonces à partir d'un fichier de spec |
ads create:preview spec.json | Simulation qui montre ce qui serait créé |
ads create:test [spec.json] | Test Mode réservé aux admins, avec des résultats de validation seule côté Meta ; ne crée aucune annonce Meta |
ads create:interactive | Assistant guidé (accepte tous les flags de création) |
Duplication par Post ID
| Commande | Ce qu'elle fait |
|---|---|
ads duplicator:post-id [specFile] | Duplique des annonces existantes sélectionnées par Post ID de Page, en conservant leurs références de publication |
ads duplicator:post-id:preview [specFile] | Prévisualise une duplication par Post ID et sa correspondance source vers destination |
Gestion des tâches
| Commande | Ce qu'elle fait |
|---|---|
ads jobs <jobId> | Vérifie le statut d'une tâche |
ads jobs <jobId> --follow | Affiche la progression en direct |
ads jobs cancel <jobId> | Annule une tâche en cours |
Flags de création
Ces flags s'appliquent à ads create, ads create:preview et ads create:interactive (ainsi qu'à ads create:test, réservé aux admins). Tu peux les utiliser à la place d'un fichier de spec, ou en plus.
| Flag | Description |
|---|---|
--account <id> | Remplace le compte publicitaire par défaut |
--build <buildId> | Utilise un build enregistré comme spec. Ne le combine pas avec un fichier de spec. |
--preset <id> | Utilise un préréglage d'API enregistré (alternative au fichier de spec) |
--text-preset <id> | Charge un préréglage de texte enregistré |
--copy-from <adId> | Copie les paramètres d'une annonce existante |
--upload <batchId> | Indique l'ID du lot d'import |
--status <PAUSED|ACTIVE> | Définit le statut des annonces (par défaut : ACTIVE) |
--pause-at <level> | Niveau de mise en pause : ad (par défaut), adSet ou campaign |
--daily-budget <amount> | Remplace le budget quotidien par ensemble d'annonces (en unités de devise, par ex. 50 pour 50 $) |
--bid-amount <amount> | Remplace le plafond d'enchère ou de coût par ensemble d'annonces (en unités de devise) |
--minimum-roas <ratio> | Remplace l'objectif de ROAS minimum par ensemble d'annonces (par ex. 1.5) |
--campaign-daily-budget <amount> | Définit un budget quotidien de campagne CBO en unités de devise entières. Exclusif avec le budget global ; omets les deux pour hériter du budget de la campagne source. |
--campaign-lifetime-budget <amount> | Définit un budget global de campagne CBO en unités de devise entières. Exclusif avec le budget quotidien ; omets les deux pour hériter du budget de la campagne source. |
--adset-min-spend <amount> | Définit la dépense minimum de l'ensemble d'annonces en CBO, en unités de devise entières ; 0 supprime la limite héritée de l'ensemble d'annonces source. |
--adset-max-spend <amount> | Définit la dépense maximum de l'ensemble d'annonces en CBO, en unités de devise entières ; 0 supprime la limite héritée de l'ensemble d'annonces source. |
--adset-min-spend-pct <5-100> | Définit la dépense minimum de l'ensemble d'annonces en pourcentage du budget de campagne, par paliers de 5 %. Fonctionne aussi avec une campagne CBO existante ; exclusif avec --adset-min-spend. |
--adset-max-spend-pct <5-100> | Définit la dépense maximum de l'ensemble d'annonces en pourcentage du budget de campagne, par paliers de 5 %. Fonctionne aussi avec une campagne CBO existante ; exclusif avec --adset-max-spend. |
--location <ISO> | Cible un pays par son code ISO à deux lettres. Répète le flag pour plusieurs pays. |
--age-min <n> | Âge minimum, de 13 à 65 |
--age-max <n> | Âge maximum, de 13 à 65 (65 signifie 65 ans et plus) |
--gender <gender> | all, men ou women. all supprime une restriction de genre héritée de l'ensemble d'annonces source. |
--ai-disclosure | Déclare toi-même un contenu créatif généré par IA (transparence Meta sur les contenus IA). Désactivé par défaut. Consulte Déclaration IA pour le champ de spec. |
--page <id> | Utilise cette Page Facebook au lieu de celle du modèle (voir Options de profil) |
--instagram <id> | Utilise ce compte Instagram au lieu de celui du modèle |
--use-page-identity | Utilise la Page Facebook comme identité Instagram ; ne peut pas être combiné avec --instagram |
--threads <id> | Utilise ce profil Threads au lieu de celui du modèle |
--text-file <path> | Charge la configuration du texte depuis un fichier JSON |
--expanded | Affiche en entier les titres, textes principaux et descriptions dans les aperçus |
Flags de duplication par Post ID
Ces flags s'appliquent à ads duplicator:post-id et ads duplicator:post-id:preview. Tu peux les utiliser à la place d'un fichier de spec de duplication par Post ID, ou en plus. C'est le mode de duplication par Post ID ; d'autres modes de duplication pourront être ajoutés plus tard.
| Flag | Description |
|---|---|
--account <id> | Remplace le compte publicitaire par défaut |
--post <postId> | Trouve les annonces source par Post ID de Page. Plusieurs correspondances exigent une sélection explicite avec --ad. |
--ad <adId> | Sélectionne un ID d'annonce source exact. Répète-le pour plusieurs annonces ; ne le combine pas avec --post. |
--campaign <id> | Utilise une campagne de destination existante |
--adset <id> | Utilise un ensemble d'annonces de destination existant, ou s'en sert comme modèle pour un nouvel ensemble d'annonces |
--new-adset [name] | Crée un seul nouvel ensemble d'annonces pour toutes les annonces source. Le nom par défaut est {AdName}. |
--new-adset-per-ad [name] | Crée un nouvel ensemble d'annonces par annonce source. Le nom par défaut est {AdName}. |
--ad-name <pattern> | Définit le modèle de nom des annonces dupliquées. Par défaut, c'est {AdName}. |
--paused | Crée les annonces dupliquées en pause |
--use-creative-id | Réutilise les ID de créatif d'origine au lieu de créer des créatifs qui référencent la publication |
--acknowledge-warnings | Poursuit une exécution réelle après que tu as examiné les avertissements sur les créatifs dans l'aperçu (acknowledgeWarnings: true en JSON) |
--json | Renvoie du JSON brut pour les scripts |
Fichier de spec de duplication par Post ID
Cette spec v1 sélectionne une annonce source exacte, clone un ensemble d'annonces et crée des annonces en pause :
{
"adIds": ["120200000000000001"],
"campaignId": "120200000000000000",
"adSetId": "120200000000000002",
"newAdSet": { "name": "Winners {AdName}" },
"adNamePattern": "{AdName} - {Index}",
"paused": true,
"useCreativeId": false
}
Utilise soit postIds pour la recherche, soit adIds dans l'ordre voulu pour une sélection exacte, jamais les deux. L'aperçu renvoie sourceCandidates avec les ID d'annonce, de campagne et d'ensemble d'annonces. Quand les correspondances sont ambiguës, requiresSourceSelection vaut true et resolvedRequest vaut null : choisis les ID d'annonce et relance l'aperçu. Avec une sélection exacte, resolvedRequest contient des ID d'annonce et aucun Post ID. Un campaignId existant est obligatoire ; les nouvelles campagnes ne sont pas prises en charge.
Choisis un mode de destination pour l'ensemble d'annonces :
| Destination | Champs de la spec |
|---|---|
| Ensemble d'annonces existant | "adSetId": "120200000000000002" |
| Un nouvel ensemble d'annonces | "newAdSet": { "name": "Winners {AdName}" } et, en option, adSetId comme modèle |
| Un nouvel ensemble d'annonces par annonce | "newAdSetPerAd": { "name": "Winners {Index} {AdName}" } et, en option, adSetId comme modèle |
Pour les exécutions réelles avec des avertissements sur les créatifs, examine l'aperçu et passe --acknowledge-warnings (acknowledgeWarnings: true en JSON/MCP) pour continuer. Un useCreativeId: true explicite remplit aussi cette condition. L'aperçu n'exige pas de confirmation.
La campagne de destination, l'ensemble d'annonces sélectionné et les annonces source doivent appartenir au même compte publicitaire. Un ensemble d'annonces sélectionné doit appartenir à campaignId, y compris quand il sert de modèle pour un nouvel ensemble. Choisis soit newAdSet, soit newAdSetPerAd ; combiner les deux est refusé. Une seule source avec newAdSetPerAd crée un seul clone partagé et garde {Index} à 1.
L'aperçu et le Test Mode web lisent la vraie configuration de chaque annonce source et de chaque modèle sélectionné, sans créer d'objets Meta. Les sources suivantes peuvent donc révéler des données manquantes et des avertissements sur les créatifs ; le ciblage est validé sur chaque modèle utilisé pour créer un nouvel ensemble d'annonces. Les nouveaux ensembles d'annonces simulés utilisent les paramètres de budget et d'enchère de la campagne de destination quand ils sont disponibles. Les annonces sont actives par défaut ; paused ne concerne que les annonces, et les nouveaux ensembles d'annonces restent actifs.
{AdName} insère le nom de l'annonce source. {Index} insère son rang (à partir de 1) dans les noms des annonces dupliquées et dans les noms des ensembles d'annonces créés par annonce. Quand un nouvel ensemble d'annonces contient plusieurs annonces source, {AdName} dans le nom de cet ensemble devient Multiple Ads.
Comment la recherche par publication choisit les annonces : une recherche par Post ID parcourt jusqu'à environ 2 000 annonces récentes du compte. Elle ne choisit jamais la correspondance la plus récente à ta place. Quand plusieurs annonces correspondent, le CLI et le MCP s'arrêtent et te demandent de choisir, et ils s'arrêtent aussi sur les avertissements que tu n'as pas confirmés. Une exécution réelle duplique toujours des ID d'annonce exacts, donc soumets le resolvedRequest de l'aperçu. Pour relancer une sélection déjà examinée, enregistre et réutilise resolvedRequest (le MCP a aussi besoin de accountId) au lieu de refaire la recherche par publication seule. Les ID d'annonce restent fixes, mais les paramètres Meta actuels sont relus et revérifiés au lancement.
Les nouveaux ensembles d'annonces héritent du ciblage, du budget, du calendrier et des paramètres d'enchère de l'--adset ou de l'adSetId sélectionné, avec le même nettoyage et le même ajustement au budget de destination que le Duplicator web. Sans modèle sélectionné, un nouvel ensemble partagé utilise l'ensemble de la première annonce source ; le mode par annonce utilise l'ensemble propre à chaque annonce source.
Les annonces source en Dynamic Creative réutilisent leur ID de créatif et ne peuvent pas conserver l'engagement synchronisé. Le CLI affiche le même avertissement que le Duplicator web.
Les exécutions réelles de duplication par Post ID affichent la progression par ensemble d'annonces et par annonce, y compris les messages d'erreur de Meta, et se terminent par Duplicated X of Y.
Flags de navigation
Ces flags sont disponibles sur campaigns, adsets, adset et campaign :
| Flag | Description |
|---|---|
--status <status> | active (par défaut) ou all |
--inactive | Raccourci pour --status all (sur campaigns) |
--search <text> | Filtre par nom (sur campaigns, adsets) |
Recherche de ciblage
Le ciblage par ville, par code postal et le ciblage détaillé utilisent des identifiants Meta plutôt que des noms. Fais la recherche via Ads Uploader pour obtenir des valeurs que tu peux coller dans une spec :
ads targeting:search "Austin" --type city
ads targeting:search "90210" --type zip
ads targeting:search "advertising" --type detailed
| Flag | Description |
|---|---|
--type <type> | Obligatoire. city renvoie des valeurs targeting.cities[].key ; zip renvoie des valeurs targeting.zips[].key ; detailed renvoie des entrées pour targeting.detailedTargetingGroups. |
--account <id> | Remplace le compte publicitaire par défaut configuré |
--limit <n> | Renvoie de 1 à 25 correspondances (8 par défaut) |
--json | Renvoie des résultats structurés prêts à coller |
Les résultats de ciblage détaillé incluent id, name, type, une fourchette de taille d'audience et le chemin de catégorie. Le type identifie la catégorie de ciblage détaillé, par exemple interests, behaviors, work_employers ou work_positions. Recherche toujours ces identifiants ; ne les devine jamais.
Flags de détail
Ces flags sont disponibles sur ad :
| Flag | Description |
|---|---|
--expanded | Affiche en entier les titres, textes principaux et descriptions |
Flags communs
| Flag | Description |
|---|---|
--account <id> | Remplace le compte publicitaire par défaut pour n'importe quelle commande |
--json | Renvoie du JSON brut (disponible sur la plupart des commandes, pensé pour les scripts) |
Variables d'environnement et mises à jour
| Variable | Ce qu'elle fait |
|---|---|
ADS_API_TIMEOUT_MS | Délai d'expiration des requêtes API en millisecondes pour toutes les commandes (par défaut 60000) |
ADS_API_URL | L'adresse d'Ads Uploader avec laquelle le CLI communique. Laisse-la vide pour un usage normal. |
Le CLI vérifie une fois par jour s'il existe une nouvelle version et affiche un message quand c'est le cas. Mets à jour avec npm update -g @adsuploader/cli.
Format du fichier de spec
Le fichier de spec JSON contrôle tous les aspects de la création d'annonces. Fournis une source de modèle (adPresetId ou copyFromAd) et soit uploadId, soit des mediaItems capturés avec un mediaHash Facebook pour chaque image et un mediaId pour chaque vidéo. Les vidéos standard, carrousel, flexibles et de placement ont aussi besoin de thumbnailHash ; les vidéos Multi Media utilisent leur URL publique de miniature capturée.
Pour les vidéos, mediaItems[].mediaId doit être l'ID numérique de la vidéo Facebook : utilise le videoId de la réponse d'import, pas son id interne. videoId est accepté comme alias, et les linkedAssets[] suivent la même règle. Les ID d'import internes sont résolus à l'enregistrement uniquement s'ils appartiennent à l'utilisateur authentifié et au compte sélectionné. Sans ID numérique ni lien vers un lot, une vidéo non résolue rend le build impossible à lancer. Consulte l'élément vidéo de placement de référence.
Spec minimale
{
"adPresetId": "your_preset_id",
"uploadId": "batch_abc123"
}
Exemple complet
{
"adPresetId": "preset_id_here",
"uploadId": "batch_abc123",
"adSet": {
"name": "My New Ad Set",
"dailyBudget": 50
},
"adNamePattern": "{filename}",
"texts": {
"perAd": {
"hero.jpg": {
"headlines": ["Main Headline"],
"bodies": ["Ad copy here."],
"descriptions": ["Short description"],
"cta": "SHOP_NOW",
"link": "https://example.com/landing"
}
}
},
"creativeEnhancements": "none",
"options": {
"status": "PAUSED",
"pauseAt": "adSet"
}
}
Source du modèle
Tu as besoin de l'un de ces champs pour indiquer au CLI quelle configuration d'annonce utiliser comme base.
| Champ | Description |
|---|---|
adPresetId | Un ID de préréglage d'API enregistré. Fixe la configuration de la campagne, de l'ensemble d'annonces et de l'annonce. |
copyFromAd | Un ID d'annonce Facebook dont copier les paramètres. |
Avec copyFromAd, fournis le lot d'import, ou lance un build web enregistré dont les images capturées ont un mediaHash et les vidéos un mediaId. Tu peux aussi définir la campagne et l'ensemble d'annonces si tu veux :
{
"copyFromAd": "120233848667930472",
"uploadId": "batch_abc123",
"campaign": { "id": "120233848666410472" },
"adSet": { "id": "120233848666620472" }
}
Pour trouver le bon ID d'annonce, descends dans ton compte : ads campaigns, puis ads campaign <id>, puis ads adset <id>, puis ads ad <id>.
Options de profil
Par défaut, les nouvelles annonces héritent de la Page Facebook, du compte Instagram et du profil Threads de l'annonce modèle ou du préréglage. C'est le même réglage Profile Options que dans le panneau Defaults de l'application web. Remplace n'importe lequel avec un bloc profile (ou avec les flags --page / --instagram / --use-page-identity / --threads, qui ont priorité sur le fichier de spec) :
{
"copyFromAd": "120233848667930472",
"uploadId": "batch_abc123",
"profile": {
"pageId": "123456789012345",
"instagramId": "17841400000000000",
"threadsId": "987654321098765"
}
}
Lance ads pages pour lister les ID de Page que tu peux utiliser, avec le compte Instagram lié à chaque Page.
Si tu remplaces uniquement la Page, Ads Uploader utilise automatiquement son compte Instagram lié. Si aucun compte Instagram n'est lié, il utilise la Page Facebook comme identité Instagram. Threads est quand même réinitialisé, car il peut appartenir à l'ancienne Page ; définis-le explicitement si besoin.
Pour choisir explicitement la Page comme identité, utilise --use-page-identity ou mets "useFacebookPage": true dans profile. Ne le combine pas avec --instagram ou instagramId. Tu peux aussi changer uniquement le profil Instagram ou Threads sans toucher à la Page, en ne définissant que ces champs.
Pour les lancements sur plusieurs campagnes, attribue les identités séparément avec profile.campaigns. Associe chaque substitution à l'id de la campagne correspondante (recommandé) ou à un nom de campagne sans ambiguïté :
{
"campaign": {
"mode": "duplicate",
"campaigns": [
{ "id": "prospecting", "name": "Prospecting" },
{ "id": "retargeting", "name": "Retargeting" }
]
},
"profile": {
"campaigns": {
"prospecting": { "pageId": "page_1", "instagramId": "ig_1", "threadsId": null },
"retargeting": { "pageId": "page_2", "useFacebookPage": true, "threadsId": "threads_2" }
}
}
}
profile.campaigns ne fonctionne que si campaign.mode vaut "duplicate" ou "split" avec au moins deux entrées dans campaign.campaigns. Chaque clé doit correspondre à l'une de ces campagnes ; les clés sans correspondance ou ambiguës sont refusées avant le lancement.
Structure de campagne
Par défaut, les annonces vont dans la campagne de l'annonce modèle. Tu peux créer une nouvelle campagne en fournissant campaign.name.
Pour les modes multi-campagnes, utilise campaign.mode avec un tableau campaigns :
{
"campaign": {
"mode": "duplicate",
"campaigns": [
{ "name": "Campaign A" },
{ "name": "Campaign B" }
]
}
}
| Mode | Comportement |
|---|---|
"single" | Par défaut. Une seule campagne. |
"duplicate" | Tous les médias sont dupliqués dans chaque campagne. |
"split" | Les médias sont répartis équitablement entre les campagnes. |
Modes d'ensemble d'annonces
Par défaut, les annonces vont dans l'ensemble d'annonces existant de l'annonce modèle. Les modes suivants te permettent de contrôler la répartition des annonces entre les ensembles d'annonces.
Créer un nouvel ensemble d'annonces :
{ "adSet": { "name": "My Ad Set" } }
Utiliser un ensemble d'annonces existant par ID :
{ "adSet": { "id": "120233848666620472" } }
Un ensemble d'annonces par fichier importé :
{ "adSet": { "mode": "perUpload" } }
Regroupement automatique en ensembles d'annonces de taille fixe :
{ "adSet": { "mode": "autoGroup", "adsPerAdSet": 5 } }
Groupes personnalisés, avec un contrôle total sur la destination de chaque fichier :
{
"adSet": {
"groups": [
{ "name": "Images - April 10", "media": ["hero.jpg", "banner.jpg"] },
{ "name": "Videos - April 10", "media": ["promo.mp4"] }
]
}
}
Modèle de nom des ensembles d'annonces pour les modes à plusieurs ensembles :
{ "adSet": { "mode": "perUpload", "namePattern": "Ad Set {index:01}" } }
Le regroupement par variante place les annonces qui partagent un identifiant de variation dans le même ensemble d'annonces :
{ "adSet": { "mode": "autoGroup", "groupVariations": true, "variationIdentifier": "-" } }
Remplacement du budget et du contrôle des enchères
Remplace le budget quotidien et/ou le montant d'enchère sur les nouveaux ensembles d'annonces. Les valeurs sont en unités de la devise de ton compte (par ex. 50 pour 50 $ ou 50 euros).
dailyBudget et bidAmount utilisent les unités de devise du compte. minimumRoas est un ratio : 1.5 signifie un objectif de ROAS de 1,5x.
- Campagnes ABO (le budget est au niveau de l'ensemble d'annonces) : combine
dailyBudgetavecbidAmountpour les stratégies de plafond d'enchère ou de coût, ou avecminimumRoaspourLOWEST_COST_WITH_MIN_ROAS. - Campagnes CBO (le budget est au niveau de la campagne) : ne définis pas
dailyBudgetsur l'ensemble d'annonces. Définiscampaign.dailyBudgetoucampaign.lifetimeBudget(exclusifs l'un de l'autre) pour remplacer le budget de la campagne source, ou omets les deux pour en hériter. Les limites de dépense minimum et maximum de l'ensemble d'annonces peuvent être des montants en unités entières ou 5 à 100 % du budget de campagne, par paliers de 5 % ; les limites en pourcentage fonctionnent aussi avec une campagne CBO existante. DéfinisbidAmountouminimumRoassur l'ensemble d'annonces quand sa stratégie source utilise ce contrôle.
bidAmount et minimumRoas sont exclusifs l'un de l'autre, car ils appartiennent à des stratégies d'enchère différentes.
{ "adSet": { "dailyBudget": 50 } }
{ "adSet": { "bidAmount": 5 } }
{ "adSet": { "minimumRoas": 1.5 } }
{ "adSet": { "dailyBudget": 50, "bidAmount": 5 } }
Pour les limites de dépense CBO dans une spec, définis ces champs sur adSet :
| Champ | Ce qu'il définit |
|---|---|
minSpend | Dépense minimum de l'ensemble d'annonces en unités de devise entières. 0 supprime la limite copiée depuis l'ensemble d'annonces source. |
maxSpend | Dépense maximum de l'ensemble d'annonces en unités de devise entières. 0 supprime la limite copiée depuis l'ensemble d'annonces source. |
minSpendPercentage | Dépense minimum de l'ensemble d'annonces en pourcentage du budget de campagne (de 5 à 100, par paliers de 5) |
maxSpendPercentage | Dépense maximum de l'ensemble d'annonces en pourcentage du budget de campagne (de 5 à 100, par paliers de 5) |
{
"campaign": { "dailyBudget": 200 },
"adSet": { "minSpend": 20, "maxSpendPercentage": 50 }
}
Aussi disponibles en flags du CLI : --daily-budget 50, --bid-amount 5, --minimum-roas 1.5, --campaign-daily-budget 100, --campaign-lifetime-budget 1000, --adset-min-spend 20, --adset-max-spend 80, --adset-min-spend-pct 20 et --adset-max-spend-pct 80.
Ciblage des ensembles d'annonces
Le ciblage s'applique aux nouveaux ensembles d'annonces. Omets le bloc targeting de premier niveau pour hériter de l'audience de l'ensemble d'annonces source sans changement. Tous les modes peuvent utiliser adSet.targetingPerAdSet, dont les clés fonctionnent comme texts.perAdset : nom final de l'ensemble d'annonces, ID de l'ensemble d'annonces, ou campaign::key pour éviter les collisions. Le mode personnalisé accepte aussi adSet.groups[].targeting. L'ordre de priorité est targetingPerAdSet, puis groups[].targeting, puis la valeur par défaut du build, puis l'audience source. Le ciblage par ensemble d'annonces n'existe que dans la spec, car les flags du CLI ne peuvent pas viser un ensemble d'annonces prévu en particulier.
Avec plusieurs campagnes, la copie d'un ensemble d'annonces dans chaque campagne est ciblée séparément ; utilise "Campaign name::Ad set name" comme clé pour viser une copie précise.
{
"targeting": {
"countries": ["US"],
"cities": [
{
"key": "2525495",
"name": "Austin",
"region": "Texas",
"countryCode": "US",
"radius": 25,
"distance_unit": "mile"
}
],
"zips": [
{
"key": "US:90210",
"name": "90210",
"region": "California",
"countryCode": "US"
}
],
"selectionVersion": 4,
"ageSelected": true,
"ageMin": 21,
"ageMax": 55,
"genderSelected": true,
"genders": "women",
"detailedTargetingSelected": true,
"detailedTargetingGroups": [[
{
"id": "112002898811624",
"name": "Advertising agency",
"type": "work_employers"
}
]]
}
}
{
"targeting": { "countries": ["US"], "ageMin": 21, "ageMax": 55 },
"adSet": {
"mode": "perUpload",
"namePattern": "Ad Set {index:01}",
"targetingPerAdSet": {
"Ad Set 02": { "countries": ["CA"], "genders": "women" },
"Ad Set 01": { "countries": ["GB"] }
}
}
}
En mode personnalisé, groups[].targeting reste valide et garde la substitution à côté de son groupe de médias :
{
"adSet": {
"mode": "custom",
"groups": [{
"name": "Canada Women",
"media": ["canada.jpg"],
"targeting": { "countries": ["CA"], "genders": "women" }
}]
}
}
Règles de ciblage :
- L'âge et le genre sont à activer explicitement. Définis
ageSelected: trueougenderSelected: true, sinon les valeurs d'âge ou de genre sont ignorées. - Le ciblage détaillé remplace, il ne fusionne pas.
detailedTargetingGroupsdevient l'audience détaillée complète, donc tout ce que tu omets est supprimé. - Le rayon autour d'une ville reste entre 10 et 50 miles, ou entre 17 et 80 kilomètres. Une valeur hors de cette plage est ramenée à la limite la plus proche, et un rayon absent utilise le minimum.
Utilise ads targeting:search pour trouver la key d'une ville (type city), la key d'un code postal comme US:90210 (type zip), ainsi que l'id, le name et le type de chaque sélection détaillée (type detailed). Omets les pays, villes et codes postaux pour hériter des lieux de la source. Pays, villes et codes postaux se cumulent comme des alternatives : ajouter Austin ou un code postal à countries: ["US"] cible donc toujours tous les États-Unis ; omets les pays pour ne cibler que la ville ou le code postal. Les codes postaux n'ont pas de rayon.
Configuration du texte
Le texte commun applique le même texte à toutes les annonces :
{
"texts": {
"common": {
"headlines": ["Headline 1", "Headline 2"],
"bodies": ["Primary text"],
"descriptions": ["Description"]
},
"strategy": "flexible"
}
}
Le texte par annonce te permet de définir un texte unique pour chaque fichier :
{
"texts": {
"perAd": {
"hero.jpg": {
"headlines": ["Hero Headline"],
"bodies": ["Hero copy"],
"descriptions": ["Hero desc"],
"cta": "LEARN_MORE",
"link": "https://example.com/hero",
"urlTags": "utm_content=hero"
},
"banner.jpg": {
"headlines": ["Banner Headline"],
"bodies": ["Banner copy"]
}
}
}
}
Les clés par annonce sont des noms de fichier (pas des chemins complets). Chaque entrée accepte : headlines, bodies, descriptions, cta, link, displayUrl, urlTags. Les champs que tu ne précises pas sont hérités de l'annonce modèle.
Le texte par ensemble d'annonces applique un bloc de texte à toutes les annonces d'un ensemble d'annonces de destination. Utilise un simple nom ou ID d'ensemble d'annonces quand il est unique, ou une entrée campaign::key quand le même nom d'ensemble d'annonces apparaît dans plusieurs campagnes :
{
"texts": {
"perAdset": {
"Prospecting::prospecting_set": {
"headlines": ["Prospecting headline"],
"bodies": ["Prospecting copy"],
"descriptions": ["Prospecting description"],
"cta": "SHOP_NOW",
"link": "https://example.com/prospecting",
"displayUrl": "example.com/prospecting",
"urlTags": "utm_campaign=prospecting",
"aiDisclosure": false
}
}
}
}
Chaque clé de texts.perAdset doit correspondre à un ensemble d'annonces prévu. Les clés sans correspondance sont refusées au lieu de retomber sur le texte commun.
Les préréglages de texte te permettent de charger une configuration de texte enregistrée :
{ "textPresetId": "preset_id_here" }
Tu ne peux pas combiner textPresetId avec texts.
AI Disclosure
Déclare toi-même que le créatif d'une annonce a été créé ou fortement modifié avec l'IA (auto-déclaration Meta des contenus IA). C'est désactivé par défaut et ce n'est jamais activé à ta place.
{ "aiDisclosure": true }
Le champ aiDisclosure de premier niveau (ou le flag --ai-disclosure) s'applique à toutes les annonces du lancement. Tu peux aussi mettre aiDisclosure à true ou false sur une entrée de texts.perAd ou texts.perAdset ; cette valeur par entrée l'emporte toujours, y compris un false explicite.
Les options de stratégie contrôlent la gestion de plusieurs variations de texte :
"flexible"(par défaut) laisse Meta optimiser entre tes variations de texte. Plusieurs titres et textes principaux deviennent des options que Facebook combine."separate"crée une annonce distincte pour chaque combinaison de texte.
CTA et liens
Un CTA de premier niveau s'applique à toutes les annonces. Les CTA par annonce dans texts.perAd et les CTA par ensemble d'annonces dans texts.perAdset le remplacent.
{
"cta": {
"type": "SHOP_NOW",
"link": "https://example.com",
"displayUrl": "example.com"
},
"urlTags": "utm_source=facebook&utm_medium=paid"
}
Types de CTA standard : LEARN_MORE, SHOP_NOW, SIGN_UP, SUBSCRIBE, GET_OFFER, GET_QUOTE, CONTACT_US, GET_IN_TOUCH, BOOK_TRAVEL (affiché comme Book Now), ORDER_NOW, BUY_NOW, APPLY_NOW, DOWNLOAD, SEE_DETAILS, WATCH_MORE, LISTEN_NOW, PLAY_GAME, DONATE_NOW, OPEN_LINK
Utilise la valeur Meta (comme SHOP_NOW), pas le libellé du bouton.
Les CTA propres à un objectif sont hérités de l'annonce modèle et ne doivent pas être définis à la main. Les définir sur le mauvais type de campagne provoque une erreur de l'API Facebook.
| CTA | Objectif de campagne requis |
|---|---|
MESSAGE_PAGE | Destination Messenger |
WHATSAPP_MESSAGE | Destination WhatsApp |
INSTAGRAM_MESSAGE | Destination message privé Instagram |
CALL_NOW | Campagne d'appel |
Test A/B d'URL (Split Destination)
Fournis de 2 à 5 URL de destination dans texts.urlVariants : chaque ensemble d'annonces généré est dupliqué une fois par URL, pour que Meta optimise chaque combinaison annonce et page de destination de façon indépendante.
{
"texts": {
"common": { "headlines": ["Hero"], "bodies": ["Copy"] },
"urlVariants": [
{ "link": "https://example.com/homepage", "label": "homepage" },
{ "link": "https://example.com/quiz", "label": "quiz-v2" }
]
}
}
labelest facultatif. S'il est omis, le dernier segment du chemin de l'URL est utilisé (/quiz-v2devientquiz-v2), avec le nom de domaine en repli pour les URL racine.- En mode à un seul ensemble d'annonces, le libellé de chaque variante devient le nom complet de l'ensemble d'annonces.
- En modes
perUploadetautoGroup,-{label}est ajouté à la fin du nom de chaque ensemble d'annonces dupliqué (par exempleAd Set 01-quiz-v2), ou le libellé remplace un jeton{destination}si tu en inclus un. - Le jeton
{date}dans un libellé devient la date du jour (par exemple,launch-{date}devientlaunch-2026-04-27). - Chaque URL de destination doit être unique. Des URL identiques (ou des variantes du même URL avec ou sans slash final, ou avec une casse différente) sont fusionnées en une seule entrée, donc vérifie que tu as au moins 2 destinations distinctes.
- Le budget de ton ensemble d'annonces est multiplié par le nombre de variantes, puisque chaque doublon est un ensemble d'annonces à part entière.
- Incompatible avec les annonces source à destination spéciale (formulaire de lead, Messenger, WhatsApp, message privé Instagram, appel). Le CLI refuse cette combinaison avec une erreur claire, car ces formats n'utilisent pas
cta.link. - Les substitutions de
linkpar annonce danstexts.perAdperdent face à l'URL de la variante quand les deux sont définis.
Creative Enhancements
Contrôle les améliorations créatives Advantage+ :
{ "creativeEnhancements": "none" }
| Valeur | Effet |
|---|---|
| omis | Hérite des améliorations de l'annonce modèle ou du préréglage |
"metaDefaults" | Obsolète. N'active aucune fonctionnalité, donc toutes sont envoyées comme désactivées. |
"all" | Toutes les fonctionnalités activées |
"none" | Toutes les fonctionnalités désactivées |
["feature1", "feature2"] | Seules les fonctionnalités listées sont activées, les autres sont désactivées |
{ "feature1": true, "feature2": false } | Active ou désactive explicitement chaque fonctionnalité listée |
Fonctionnalités disponibles : text_translation, inline_comment, enhance_cta, text_optimizations, reveal_details_over_time, show_destination_blurbs, image_brightness_and_contrast, image_touchups, video_auto_crop, video_filtering, pac_relaxation, image_animation, image_templates, adapt_to_placement, product_extensions, product_tags, description_automation, add_text_overlay, music, carousel_to_video, carousel_dynamic_description, multi_share_end_card, multi_share_optimized
La clé show_destination_blurbs s'affiche sous le nom Show spotlights, et pac_relaxation sous le nom Flex media.
Quand tu choisis des fonctionnalités une par une, ne liste que celles qui concernent le type de média. Les fonctionnalités vidéo (video_auto_crop, video_filtering) ne s'appliquent qu'aux annonces vidéo. Les fonctionnalités carrousel (carousel_to_video, carousel_dynamic_description, multi_share_end_card, multi_share_optimized) ne s'appliquent qu'aux annonces carrousel.
product_tags s'applique aux annonces image et vidéo, et uniquement en mode clonage. Il ne peut être activé que si l'annonce source a un catalogue associé et des tags produit positionnés explicitement ; tous les tags de la source et leurs positions sont conservés. "all" ne l'inclut que pour une source éligible et n'invente jamais de tag produit.
Carousel Ads
Regroupe des fichiers importés en annonces carrousel, avec un texte par carte et un texte global facultatif pour le carrousel. cardTexts contrôle chaque carte. Le texte global du carrousel peut être placé directement sur l'objet carrousel ou défini dans texts.perAd avec le name du carrousel ; les champs placés sur l'objet l'emportent quand les deux existent.
{
"carousel": [
{
"name": "My Carousel",
"cards": ["slide1.jpg", "slide2.jpg", "slide3.jpg"],
"headlines": ["Overall Carousel Headline"],
"bodies": ["Overall primary text"],
"descriptions": ["Overall description"],
"cta": "SHOP_NOW",
"link": "https://example.com/carousel",
"urlTags": "utm_content=my_carousel",
"cardTexts": [
{ "headline": "Slide 1", "description": "First card", "link": "https://example.com/1" },
{ "headline": "Slide 2", "description": "Second card", "link": "https://example.com/2" }
]
}
]
}
Autre forme possible pour le texte global :
{
"texts": {
"perAd": {
"My Carousel": {
"headlines": ["Overall Carousel Headline"],
"bodies": ["Overall primary text"],
"descriptions": ["Overall description"],
"cta": "SHOP_NOW",
"link": "https://example.com/carousel",
"urlTags": "utm_content=my_carousel"
}
}
},
"carousel": [
{
"name": "My Carousel",
"cards": ["slide1.jpg", "slide2.jpg", "slide3.jpg"]
}
]
}
Les cartes doivent faire référence à des noms de fichier du lot d'import ou aux médias capturés d'un build enregistré. Chaque carrousel a besoin de 2 à 10 cartes. Les fichiers utilisés par un carrousel sont retirés de la liste des annonces standard.
Flexible Ads
Regroupe plusieurs éléments dans une seule annonce flexible, où Meta choisit le meilleur élément pour chaque placement :
{
"flexible": [
{
"name": "Multi-Asset Ad",
"assets": ["hero.jpg", "promo.mp4", "banner.jpg"]
}
]
}
Chaque groupe flexible a besoin de 2 à 10 éléments. Les fichiers utilisés par un groupe flexible sont retirés de la liste des annonces standard.
Annonces Multi Media
Regroupe de 2 à 10 images ou vidéos importées dans une annonce Multi Media de Meta :
{
"multimedia": [
{
"name": "Mixed Media Ad",
"assets": ["hero.jpg", "promo.mp4", "banner.jpg"],
"assetTexts": [
{
"headline": "Hero headline",
"primaryText": "Hero primary text",
"description": "Hero description",
"link": "https://example.com/hero",
"displayUrl": "example.com/hero"
}
]
}
]
}
Les éléments doivent faire référence à des noms de fichier du lot d'import ou aux médias capturés d'un build enregistré. assetTexts est facultatif et s'aligne sur assets par index ; chaque champ est une substitution unique pour cet élément, et les champs vides reprennent le texte principal et les URL de l'annonce. L'élément affiché en premier utilise le texte principal et l'URL de l'annonce, et toute substitution de texte sur cet élément principal devient la première option de texte principal. Les vidéos ont besoin d'une URL publique de miniature capturée et mise en cache. Les fichiers utilisés par un groupe Multi Media sont retirés de la liste des annonces standard.
Nommage des annonces
Personnalise le nom de tes annonces :
{ "adNamePattern": "{filename} - {date}" }
| Espace réservé | Ce qu'il insère |
|---|---|
{filename} | Nom de fichier d'origine sans extension |
{index} | Numéro de position (1, 2, 3...) |
{index:01} | Position complétée par des zéros. Le nombre fixe le point de départ et le remplissage : {index:01} donne 01, 02, 03 ; {index:50} donne 50, 51, 52. |
{variation} | Identifiant de variation si le regroupement par variante est activé |
{campaign} | Nom de la campagne |
{date} | Date du jour (YYYY-MM-DD) |
{date:short} | Date courte (MMDD) |
{timestamp} | Horodatage Unix en millisecondes |
Les transformations s'appliquent autour d'une valeur. Une valeur vide désigne le nom de fichier :
| Transformation | Ce qu'elle fait |
|---|---|
{split:_:2} | Découpe le nom de fichier selon le délimiteur (ici _) et insère la 2e partie |
{clean:} | Supprime un suffixe de ratio en fin de nom, comme _9x16 ou -1x1 |
{uppercase:}, {lowercase:}, {titlecase:} | Change la casse |
Les transformations peuvent être imbriquées, par exemple {titlecase:{split:_:2}}. Un modèle peut compter jusqu'à 200 caractères. Consulte Nommage des annonces pour plus d'exemples.
Options
{
"options": {
"status": "PAUSED",
"pauseAt": "adSet",
"schedule": {
"startTime": "2026-04-01T09:00:00",
"endTime": "2026-04-30T23:59:59"
}
}
}
| Champ | Valeurs | Description |
|---|---|---|
status | "PAUSED", "ACTIVE" | Statut des annonces au lancement (par défaut : ACTIVE) |
pauseAt | "ad", "adSet", "campaign" | Niveau auquel mettre en pause (par défaut : ad) |
schedule.startTime | Chaîne ISO 8601 | Heure de début programmée (fuseau horaire du compte publicitaire) |
schedule.endTime | Chaîne ISO 8601 | Heure de fin programmée (facultatif) |
Quand les annonces vont dans un ensemble d'annonces existant, options.schedule ne fonctionne que pour les campagnes Ventes et Promotion d'application, car Meta ne prend en charge la programmation par annonce que pour ces objectifs. Pour les autres objectifs, crée un nouvel ensemble d'annonces ou retire options.schedule.
Limites de la spec
| Limite | Maximum |
|---|---|
| Titres, textes principaux ou descriptions dans une annonce (texte flexible ou entrée par annonce) | 5 de chaque |
Variantes de texte avec la stratégie "separate" | 50 |
Entrées dans texts.perAd ou texts.perAdset | 200 |
Groupes d'ensembles d'annonces personnalisés (adSet.groups) | 50 |
| Médias dans un groupe personnalisé | 100 |
| Groupes carrousel, flexibles ou Multi Media (de chaque type) | 50 |
| Cartes ou éléments dans un groupe carrousel, flexible ou Multi Media | De 2 à 10 |
Longueur de adNamePattern | 200 caractères |
Import et détection des variantes
Les groupes de variantes sont détectés automatiquement à partir des conventions de nommage des fichiers, comme dans l'application web. Consulte Variations de format pour tous les détails sur les conventions de nommage.
Suffixes de ratio : hero_1x1.jpg + hero_4x5.jpg + hero_9x16.jpg + hero_16x9.jpg + hero_1.91x1.jpg sont regroupés en une seule annonce à variantes. Jusqu'à 5 ratios par groupe.
Position du jeton : le jeton de ratio peut se trouver à la fin (hero_4x5.jpg), au milieu (hero_4x5_v2.jpg) ou au début (4x5_hero.jpg).
Anciens suffixes en toutes lettres : hero.jpg + hero_vertical.jpg + hero_horizontal.jpg fonctionnent toujours et correspondent à 9x16 et 16x9.
Le délimiteur par défaut est _. Tu peux le changer (ou en accepter plusieurs) dans Account > Defaults > Placements > Filename Separator.
Modèles courants
Importer et créer avec un préréglage
ads upload ./creatives/hero.jpg ./creatives/banner.jpg
ads create:preview spec.json
ads create spec.json
Où spec.json contient :
{ "adPresetId": "PRESET_ID", "uploadId": "BATCH_ID" }
Copier les paramètres d'une annonce existante
Parcours ton compte pour trouver l'annonce :
ads campaigns
ads campaign 120233848666410472
ads adset 120233848666620472
ads ad 120233848667930472
Puis crée une spec qui y fait référence :
{
"copyFromAd": "120233848667930472",
"uploadId": "BATCH_ID"
}
L'annonce source doit avoir des paramètres de créatif intégrés. Si elle a été créée à partir d'une publication de Page existante, le CLI la refuse avant d'envoyer une requête de création.
Enregistrer un préréglage d'API à partir d'une annonce existante
ads presets:save --from-ad 120233848667930472 --name "Spring Purchase Template"
ads create --preset PRESET_ID --upload BATCH_ID
Cela enregistre un préréglage d'API de même forme que ceux de l'application web. L'annonce source doit avoir des paramètres de créatif intégrés ; les annonces basées sur une publication de Page ne peuvent pas être enregistrées comme préréglages d'API.
Texte par annonce, avec un texte unique par fichier
{
"adPresetId": "PRESET_ID",
"uploadId": "BATCH_ID",
"texts": {
"perAd": {
"hero.jpg": {
"headlines": ["Summer Sale Now On"],
"bodies": ["Save up to 50% on all items"],
"cta": "SHOP_NOW",
"link": "https://example.com/summer"
},
"banner.jpg": {
"headlines": ["New Collection Available"],
"bodies": ["Browse our latest styles"],
"cta": "LEARN_MORE",
"link": "https://example.com/new"
}
}
}
}
Regroupement automatique en plusieurs ensembles d'annonces
{
"adPresetId": "PRESET_ID",
"uploadId": "BATCH_ID",
"adSet": { "mode": "autoGroup", "adsPerAdSet": 3 }
}
Remarques importantes
- Prévisualise toujours d'abord.
create:previewdétecte les erreurs de configuration avant de toucher à Facebook. - Les annonces sont actives par défaut. Utilise
--status PAUSEDou"status": "PAUSED"dans la spec pour les créer en pause. uploadIdvient de la sortie de l'import. C'est l'ID de lot renvoyé parads upload.- Les imports sont liés à un compte publicitaire. Les fichiers sont importés directement dans la bibliothèque de médias Facebook du compte sélectionné. L'ID de lot ne peut être utilisé qu'avec ce même compte.
copyFromAda besoin de médias résolvables. FournisuploadId, ou lance un build enregistré dont les images capturées ont unmediaHashet les vidéos unmediaId. Tu peux aussi fournircampaign.idetadSet.idpour contrôler l'emplacement.- Les clés de texte par annonce sont des noms de fichier. Utilise
"hero.jpg", pas"/path/to/hero.jpg". textPresetIdettextssont exclusifs l'un de l'autre. Utilise l'un ou l'autre, pas les deux.- Les CTA propres à un objectif sont hérités du modèle. Ne définis pas
MESSAGE_PAGE,WHATSAPP_MESSAGE, etc. à la main.
Annonces partenariat avec tes propres médias
Le CLI et le MCP peuvent lancer des annonces partenariat avec des médias importés sur Facebook et Instagram. Utilise ta spec habituelle (image/vidéo, carrousel, flexible, Multi Media ou variantes de placement) et ajoute profile.partnership.enabled: true. Les médias importés suivent l'assemblage normal avec une Second Identity. Omets uploaderMode ou mets-le à false ; true sélectionne les publications importées et ne peut pas être utilisé avec des médias importés.
Choisis ta First Identity avec profile.pageId et profile.instagramId. Le partenaire partagé est la Second Identity :
{
"accountId": "act_123",
"copyFromAd": "SOURCE_AD_ID",
"adSet": { "id": "EXISTING_AD_SET_ID" },
"mediaItems": [
{ "mediaName": "one.jpg", "mediaType": "image", "mediaHash": "UPLOADED_IMAGE_HASH_ONE" },
{ "mediaName": "two.jpg", "mediaType": "image", "mediaHash": "UPLOADED_IMAGE_HASH_TWO" }
],
"profile": {
"pageId": "111",
"instagramId": "222",
"partnership": {
"enabled": true,
"sponsorPageId": "333",
"sponsorInstagramId": "444",
"displayMode": "both"
}
},
"options": { "status": "PAUSED" }
}
Pour avoir des partenaires différents selon l'annonce, ajoute ce bloc texts à la même spec. La deuxième ligne utilise explicitement No Partner (aucun partenaire) :
{
"texts": {
"mode": "perAd",
"perAd": {
"one.jpg": { "sponsorPageId": "555", "sponsorInstagramId": "666" },
"two.jpg": { "sponsorPageId": null, "sponsorInstagramId": null }
}
}
}
Au niveau des ensembles d'annonces, utilise texts.mode: "perAdset" et texts.perAdset, avec comme clé le nom ou l'ID final de l'ensemble d'annonces, ou campaign::key. Dans les lancements multi-campagnes, utilise profile.campaigns[<id or unambiguous name>] pour les substitutions de sponsor par campagne. L'ordre de résolution est : partenaire partagé, puis campagne, puis ligne active. Les champs de sponsor omis sont hérités indépendamment l'un de l'autre ; mets explicitement les deux ID à null pour No Partner. Changer uniquement la Page partenaire n'efface pas un ID Instagram hérité sur les médias importés ; définis cet ID explicitement quand tu changes la paire. Les champs First Identity de la ligne (pageId, instagramId, threadsId) restent indépendants.
Pour une Second Identity uniquement Instagram, mets sponsorPageId: null, sponsorInstagramId sur l'ID du compte approuvé et sponsorPageUseInstagramAccount: true. Une Page Facebook partenaire est aussi prise en charge pour les médias importés. La restriction sur les imports de publications Facebook ne s'applique pas aux médias importés.
displayMode s'applique à tout le lancement : both (par défaut), first ou dynamic. Chaque partenaire effectif doit être différent de la First Identity et disposer d'un accès approuvé aux publicités en partenariat. Une approbation en attente ou absente est refusée, avec le nom de l'identité concernée. Chaque ligne a besoin d'un partenaire complet, hérité ou explicite, ou d'une substitution explicite No Partner. Activer les partenariats sans aucun sponsor est refusé. L'approbation est revérifiée à l'aperçu et à la création ; un build enregistré ne stocke pas les autorisations.
ads create:preview et ads_preview montrent pour chaque annonce le partenaire effectif, l'approbation et le mode d'en-tête, regroupés par ensemble d'annonces. ads create:test, réservé aux admins, ou ads_create avec options.testMode: true valide les appels éligibles auprès de Meta sans créer d'annonces, et indique le nombre d'appels réussis, en échec et non vérifiés. Les builds de partenariat complets avec médias importés, enregistrés sur le web, peuvent être lancés via le CLI et le MCP ; les builds modifiés via ces outils restaurent Partnership Ads, les identités, les partenaires par ligne et le mode d'en-tête dans l'uploader web.
Spec de partenariat avec une publication Instagram existante
Les specs JSON du CLI et les outils MCP ads_preview / ads_create acceptent des publications Instagram avec mediaItems[].kind: "partnershipPost". L'annonce source ou le préréglage fournit les paramètres ; la publication importée fournit son identité de créateur fixe et sa légende organique. Choisis le sponsor partagé dans profile.partnership, ou définis le sponsor et d'éventuelles substitutions de texte dans texts.perAdset ou texts.perAd. Le titre, le CTA, l'URL du site web et le témoignage peuvent être vides. Un CTA non vide exige une URL de site web. Les imports de publications Facebook ne sont pas pris en charge.
L'aperçu vérifie le contenu et les autorisations via des appels Meta en lecture et en validation seule, sans créer d'annonces ni stocker de codes. Son resolvedSpec sans code peut être enregistré, mais les codes doivent être fournis à nouveau à la création. La création revérifie l'autorisation.
Utilise mediaItems[].kind: "partnershipPost" avec platform: "instagram". Choisis exactement un localisateur : sourceInstagramMediaId, import.postUrl ou import.instagramShortcode. Un import.adCode correspondant peut accompagner un localisateur, ou être utilisé seul. L'annonce source ou le préréglage fournit les paramètres, pas la publication. Les champs facultatifs creator.pageId et creator.instagramId confirment le créateur résolu.
{
"accountId": "act_123",
"copyFromAd": "456",
"adSet": { "mode": "single", "id": "789" },
"mediaItems": [{ "kind": "partnershipPost", "mediaName": "creator-post-one", "platform": "instagram", "import": { "postUrl": "https://www.instagram.com/p/POST_SHORTCODE/" } }],
"profile": { "partnership": { "enabled": true, "uploaderMode": true, "sponsorPageId": "111", "sponsorInstagramId": "222", "displayMode": "both" } },
"texts": { "mode": "common", "common": { "headline": "Discover the collection", "callToAction": "LEARN_MORE", "link": "https://example.com/", "multiAdvertiserAds": false } },
"options": { "status": "PAUSED", "pauseAt": "ad" }
}
Pour un import par code uniquement, utilise ce corps de requête complet avec tes ID et un code inséré par un générateur de secret en mémoire. N'enregistre pas le vrai code dans un fichier :
{
"accountId": "act_123",
"copyFromAd": "456",
"adSet": { "mode": "single", "id": "789" },
"mediaItems": [{ "kind": "partnershipPost", "mediaName": "creator-post-one", "platform": "instagram", "import": { "adCode": "REPLACE_IN_MEMORY" } }],
"profile": { "partnership": { "enabled": true, "uploaderMode": true, "sponsorPageId": "111", "sponsorInstagramId": "222", "displayMode": "both" } },
"texts": { "mode": "common", "common": { "headline": "Discover the collection", "callToAction": "LEARN_MORE", "link": "https://example.com/", "multiAdvertiserAds": false } },
"options": { "status": "PAUSED", "pauseAt": "ad" }
}
Utilise de 1 à 250 publications par requête, chacune avec un mediaName unique de 200 caractères maximum. sponsorPageId doit correspondre à une vraie Page Facebook de marque pour chaque annonce prévue ; sponsorInstagramId est facultatif. Le displayMode de l'en-tête s'applique à tout le lancement : both, first ou dynamic. Pour les publications importées, first correspond à l'en-tête avec le créateur seul, intitulé Partner identity only in the header dans l'uploader, et non à un en-tête avec la marque seule.
Les sponsors par campagne utilisent profile.campaigns, avec comme clé l'ID de la campagne ou un nom de campagne sans ambiguïté, et sponsorPageId plus un sponsorInstagramId facultatif. L'ordre de résolution est : sponsor partagé, puis campagne, puis substitution active par ensemble d'annonces ou par annonce. Place les champs de sponsor partagé dans profile.partnership, jamais dans texts.common ; un adCode va dans l'import de la ligne ou dans un bloc actif par annonce ou par ensemble d'annonces. Les valeurs pageId / instagramId du créateur sont des vérifications, pas un moyen de changer l'auteur de la publication.
multiAdvertiserAds vaut true par défaut ; mets-le explicitement à false pour le désactiver. Les valeurs de CTA doivent être des enums Meta comme SHOP_NOW ou LEARN_MORE, pas des libellés comme Shop Now, et un CTA non vide exige une destination en http:// ou https://. La légende organique ne peut pas être modifiée. Les blocs de texte des publications importées acceptent un titre, un CTA, un lien, des paramètres d'URL, un témoignage, la déclaration IA et le choix multi-annonceurs. Chaque table de substitutions par annonce ou par ensemble d'annonces accepte au maximum 200 entrées.
Pour les publications importées, le CLI et le MCP refusent les imports de publications Facebook, les lots qui mélangent publications importées et médias importés, les structures carrousel, flexibles et Multi Media, le regroupement par variation de placement et les identités Threads. Les médias importés acceptent les formats créatifs habituels et les partenaires par ligne. Les nouveaux imports de publications Facebook ne sont pas non plus pris en charge dans l'uploader web pour le moment. L'uploader n'a pas de navigateur de publications approuvées ; importe une URL, un ID de publication ou un code Instagram autorisé.
Pour texts.mode: "perAd", utilise le mediaName comme clé de texts.perAd. Pour texts.mode: "perAdset", utilise comme clé de texts.perAdset le nom ou l'ID final de l'ensemble d'annonces, ou campaign::key. Le texte partagé utilise texts.common. adSet.groups[].media contient ces noms de médias ; réutilise une même ligne de média dans plusieurs groupes au lieu d'importer deux fois la même source.
Utilise ads create:preview /dev/stdin --account act_123 pour l'aperçu, puis ads create /dev/stdin --account act_123 --status PAUSED pour la création. Ne passe les codes sensibles que via stdin, jamais en argument, dans une chaîne de requête ou dans un fichier enregistré sur le disque. Fournis à nouveau les codes à la création ; les builds enregistrés et la sortie de l'aperçu ne les contiennent pas. Utilise --account ou lance d'abord ads account act_123, même si le JSON contient accountId.
Les admins peuvent lancer ads create:test /dev/stdin --account act_123 --status PAUSED. Cette commande ne crée aucune annonce Meta et indique pour chaque appel metaValidation s'il a réussi, échoué ou n'a pas été vérifié. Un refus de Meta renvoie le code de sortie 1. Les appels qui ont besoin d'ID simulés ne sont pas vérifiés ; une validation réussie ne garantit ni la diffusion ni l'apparence. Le Test Mode peut enregistrer des codes d'autorisation chiffrés et des historiques de lancement.