Rôle
Vous êtes chargé de créer en masse des creative sets AppLovin pour le responsable des campagnes. L'encapsulation API et les identifiants sont gérés par le script scripts/creative_tuner.py (qui fournit ct.set_account() / ct.APL_MGMT_KEY / ct.APL_ACCOUNT_ID / ct.APL_MGMT_URL). Tous les outils sont dans scripts/, fichiers nommés _cs_*.py.
Installation / Configuration (à lire impérativement la première fois)
- Placez l'intégralité du dossier
apl-creative-set/dans~/.claude/skills/(ou%USERPROFILE%\.claude\skills\sous Windows). - Dans
scripts/, exécutezcp config.example.json config.jsonet renseignez vos identifiants AppLovin :accounts.<ID_compte>.report_key= votre clé de rapport AppLovin ;.mgmt_key= votre clé Management API.account_aliasespermet de définir des alias (ex :"monapp": "ID_de_votre_compte"), utilisables dans les scripts viact.set_account("monapp").- La section
feishuest optionnelle ; elle n'est utilisée que par le rapport quotidien decreative_tuner.py. Pour la création de creative sets uniquement, laissez-la vide.
- Ne commitez ni ne partagez jamais
config.json(contient des clés réelles ; ajoutez-le à.gitignore). - Dans les scripts, toutes les constantes en majuscules comme
CAMP="",PA_IDS,VIDS,PREFIX,PP,SUFFIX, ainsi quect.set_account("VOTRE_COMPTE")sont des espaces réservés TODO – modifiez-les selon vos besoins.
Ce skill est conçu pour être piloté par Claude après lecture du SKILL.md : vous indiquez votre objectif (campagne, vidéos, nommage, CPP) et Claude modifie les constantes en haut des scripts, puis les exécute.
Règles absolues
- ★ Avant chaque session, demandez impérativement ces trois points à l'utilisateur (iOS/Android diffèrent, ne pas réutiliser les précédents) :
① Règles de nommage des sets ; ② Faut-il ajouter un suffixe CPP ; ③ Quelle valeur pour le
product_pagedu CPP. Même s'il s'agit de la même gamme de produits, demandez – ne présumez jamais. - Sécurité des identifiants : n'affichez, n'imprimez et ne renvoyez jamais aucune clé/secret/token/open_id du fichier
config.json. Les scripts ne doivent jamais afficher les identifiants. - Par défaut PAUSED : tous les nouveaux sets sont créés avec
status:"PAUSED". Ne les activez qu'après confirmation explicite de l'utilisateur (« active » →LIVE). - Limitez-vous aux ressources demandées : l'utilisateur précise parfois « créer uniquement ceux avec ce préfixe », « uniquement les téléchargements récents », etc. Filtrez strictement, ne créez pas de sets supplémentaires.
- Vérifiez chaque étape par relecture : après chaque create/attach/CPP/activation, relisez via
creative_set/listpour confirmer ; ne vous fiez pas au code de retour. - Indiquez les sources des chiffres, précision à 2 décimales, en cas de doute demandez d'abord, confirmez avant toute action d'écriture.
★ Mécanismes clés de l'API (pièges identifiés, à suivre impérativement)
- Pour attacher une campagne, utilisez
add-to-campaigns; ne comptez pas sur le create pour le faire. Dans le body dePOST /creative_set/create, vous pouvez trouvercampaign_id:"<id_interne>"(singulier) oucampaign_ids:["<id_interne>"](pluriel), mais rien ne garantit que l'attachement fonctionne (le pluriel est souvent ignoré silencieusement). Donc procédure fixe : create → immédiatementadd-to-campaignspour sécuriser l'attachement → relecture descampaign_idspour vérification. Body de create (version pratique) :{"account_id":AID,"type":"APP","name":..,"status":"PAUSED","campaign_ids":["<id_interne>"],"product_page":"","languages":[],"countries":[],"assets":[{"id":".."},..]}→ retourne{"id":..,"version":"V2"} - Attachement supplémentaire de campagne :
POST /creative_set/add-to-campaigns, avec un tableau d'entiers :{"campaign_ids":[<id_interne>],"creative_set_ids":[..]}(max 20 campagnes, 50 sets par lot). C'est la méthode la plus fiable. Considéré réussi quand lescampaign_idslus contiennent bien la campagne cible. - Modifier un set (nom/CPP/activer/désactiver/ajouter/supprimer des assets) :
POST /creative_set/update{"id":..,"type":"APP","status":"LIVE|PAUSED","name":..,"product_page":..,"assets":[..]}- update génère une nouvelle version. Envoyez
assetsen remplacement complet (pas un ajout) : supprimer = ne pas inclure l'id, ajouter = inclure l'id dans la liste complète ; les ids manquants seront supprimés (conservez toutes les vidéos + playables à garder). - Les champs non transmis (ex : name/product_page/association campaign) restent inchangés en pratique ; par sécurité, lors d'un changement d'état ou d'assets, transmettez name+product_page+languages+countries pour éviter toute perte.
- Envoyer
campaign_idsdans update est inefficace (retour 200 mais n'attache pas) – utilisez toujoursadd-to-campaignspour attacher.
- update génère une nouvelle version. Envoyez
- Custom Product Page : champ
product_page.- Page produit par défaut =
product_page:""(chaîne vide, pas de suffixe dans le nom). - Pour définir un CPP, remplissez la valeur
product_page(slug en chaîne, pas UUID). Il n'y a pas d'endpoint de liste ; pour trouver la valeur correspondant à un nom, scannez tous les sets du compte en analysantproduct_pagevs le suffixe du nom (voir_cpp_map.py).
- Page produit par défaut =
- Le champ du type d'asset diffère entre les deux endpoints (piège fréquent) :
- Dans
asset/list(bibliothèque media), le champ s'appelleasset_type; - Dans
creative_set->assets[], le champ s'appelletype. - Valeurs : vidéo =
VID_LONG_P/VID_SHORT_P(ou "commence par VID") ; playable =HOSTED_HTML.
- Dans
- ★ Limite d'assets par creative set = 11 : une fois 11 assets atteints, tout update pour en ajouter est silencieusement rejeté (retour 200 mais pas d'ajout, détectable uniquement par relecture). Avant d'ajouter un playable, vérifiez
len(assets); si = 11, supprimez d'abord un élément pour faire de la place (remplacement), sinon l'ajout échouera. creative_set/listetasset/listont une pagination de taille max 100/200. Certaines pages renvoient une liste nue (pas{results:[]}), donc pour l'analyse utilisezisinstancepour être compatible.asset/list: taille max 100 par page : pour la pagination, arrêtez-vous quandlen(res) < 100(utiliser 200 ferait s'arrêter à la première page, ne donnant que les 100 premiers médias).
Avant de commencer, clarifiez (sauf si l'utilisateur a déjà fourni)
- Campagne cible (nom/ID) -> localisez le compte dans la config, obtenez l'ID interne.
- Périmètre des assets : quelles vidéos ? Filtre par préfixe (ex : préfixe de la gamme), limite de date de téléchargement (upload_time ≥ date), statut (généralement ACTIVE et non utilisé par d'autres sets).
- Playables fixes : quels playables HTML attacher (l'utilisateur donne le nom exact).
- Règles de nommage : par défaut
EN_TypeVidéo(AI/3D/JJ…extrait du nom)_NomVidéo_groupeTopPlayablePA; plusieurs vidéos d'une série dans un même set ->EN_Type_NomBase_groupeTopPlayablePA(nom de base = nom sans le numéro de suffixe). - Détermination des séries : mêmes concepts + numéro final (itération 1/4) -> regroupés. En cas de doute (ex : version de base / version avancée), demandez s'il faut les séparer.
- CPP : faut-il définir
product_page? Quelle valeur ? Faut-il ajouter un suffixe dans le nom ?
Procédure standard (pipeline de scripts, tous dans scripts/)
_apl_active_assets.py-> extrait les assets ACTIVE dédupliqués (résultat dans_apl_active_assets.json)._cs_plan_scan.py-> trouve l'ID du playable fixe + les vidéos candidates (préfixe + is_video + pas déjà utilisées dans un set existant + filtre temporel) ->_cs_scan.json. Modifiez d'abord les constantesPREFIX,CAMP,targetsen haut du script._cs_group.py-> regroupe les candidats par série/asset unique, génère les noms ->_cs_build_plan.json. Utilisez_cs_plan_show.pypour afficher et faire confirmer par l'utilisateur._cs_build_all.py(idempotent : vérifie les noms existants et ignore les sets déjà créés) -> crée chaque set (PAUSED, avec campaign_id) +add-to-campaignspour sécuriser l'attachement + relecture ->_cs_create_result.json.- (Optionnel)
_cpp_apply.py all-> définitproduct_page+ ajoute le suffixe dans le nom (modifiez d'abordPP/SUFFIXen haut du script). - Après confirmation de l'utilisateur,
_cs_enable.py-> passe status → LIVE (avec name+product_page pour éviter les pertes) + relecture. - Vérification ponctuelle :
_cs_spotcheck.py <id..>pour examiner la composition des assets (nombre de vidéos + playables).
Chemin simplifié : créer directement un groupe avec quelques vidéos spécifiées (nom connu, pas de scan complet)
À utiliser lorsque l'utilisateur a téléchargé quelques nouvelles vidéos et demande explicitement leur regroupement.
_cs_find_new.py <mot-clé..>-> recherche par nom dans la bibliothèque media : nom complet + id + statut + date de téléchargement (lecture seule) ; vérifiez que c'est bien la bonne vidéo et qu'elle est ACTIVE.- Modifiez les constantes en haut de
_cs_en_new_create.py:VIDS=[(nom_core,id_video),..],PA_IDS(playable fixe),CAMP; avant, appliquez la règle absolue 0 (confirmation nommage + CPP avec l'utilisateur).python _cs_en_new_create.py(dry-run : vérifie les doublons + affiche le plan) ->go(crée PAUSED + page produit par défaut""+ sans langue (suivra la campagne) + add-to-campaigns + relecture : attachment / nombre d'assets / pp / status). - Quand l'utilisateur dit « active » ->
_cs_en_new_enable.py(lit_cs_en_new_ids.json, transmet explicitement name/product_page/languages/countries pour éviter les pertes, status → LIVE + relecture).
Ajouter / Supprimer / Remplacer un playable dans un set
Sur la base du mot-clé du nom du set, traitez par lots (via update avec assets complet, en préservant name/product_page/languages/countries/status, puis relecture) :
- Ajouter :
_cs_add_pa.py <id_playable> <mot_clé_nom_set> [enonly](dry-run) -> puisgo.enonly= ne cibler que les groupes commençant parEN_(exclut les groupes ciblant d'autres langues). Idempotent (ignore les playables déjà présents) ; les groupes à 11 assets déclenchent un avertissement et sont ignorés (il faut d'abord en supprimer un pour faire de la place). - Supprimer :
_cs_rm_pa.py <id_playable>(dry-run) ->go. Filet de sécurité : si après suppression le set a moins d'1 vidéo ou moins d'1 playable, le script marque le set en rouge et ne le modifie pas. - Remplacer = dans la liste complète des assets, remplacez l'ancien id par le nouveau, puis faites update.
- Pour trouver l'id d'un playable, utilisez
_cs_find_new.py <mot-clé>dans la bibliothèque media (type HOSTED_HTML).
Script de livraison
Rapport : nombre de groupes créés (séries/individuels), nombre de vidéos couvertes, chaque groupe = vidéos correspondantes + N playables, tous PAUSED + attachés + CPP, avec une liste « nom du groupe -> vidéo » ; signalez les assets non approuvés / non téléchargés (vous pouvez utiliser _b8_leftover.py pour classer les REJECTED / non téléchargés). Attendez que l'utilisateur dise « active » pour exécuter l'étape 6.