Bonnes pratiques pour les scripts Microsoft Advertising
Pour améliorer les performances de vos scripts et celle de la plateforme, consultez et suivez les bonnes pratiques décrites ci-dessous.
Utilisation des sélecteurs
Utiliser des filtres
Utilisez les filtres d’un sélecteur au lieu de filtrer les entités vous-même. Les sélecteurs vous permettent de filtrer par ID et conditions. Par exemple, vous pouvez filtrer en fonction des performances d’une entité (campagnes de retour avec un CPC moyen supérieur à 10), de ses status (campagnes suspendues), du nom de l’objet parent de l’entité, etc.
Avantages de l’utilisation de filtres :
Limite le nombre d’entités retournées par le sélecteur aux entités dont vous avez besoin.
Permet au script de s’exécuter plus rapidement (moins d’entités à retourner et à traiter)
Réduit le risque d’atteindre les limites de lecture d’entité (voir Limites d’exécution de script).
À droite
var adGroups = AdsApp.adGroups()
.withCondition('Status = PAUSED')
.get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
// Do something with paused ad group.
}
Mauvaise façon
var adGroups = AdsApp.adGroups().get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
if (adGroup.isPaused() == true) {
// Do something with paused ad group.
}
}
Ne pas traverser la hiérarchie d’entités
Si vous souhaitez obtenir les entités enfants d’une entité ou l’entité parente de l’entité, ne parcourez pas la hiérarchie d’entités pour les obtenir.
Pour obtenir des entités enfants, utilisez la collection de l’entité enfant au niveau souhaité.
À droite
// Get all ads.
var ads = AdsApp.ads().get();
while (ads.hasNext()) {
var ad = ads.next();
// Do something with ad.
}
Ou, si vous souhaitez des publicités d’une campagne spécifique :
// Get all ads in the campaign, 'mycampaign'.
var ads = AdsApp.ads()
.withCondition("CampaignName = 'mycampaign'")
.get();
while (ads.hasNext()) {
var ad = ads.next();
// Do something with ad.
}
Ou obtenir les annonces d’une campagne si vous avez l’objet de campagne :
// Get all ads in the campaign.
var ads = campaign.ads().get();
while (ads.hasNext()) {
var ad = ads.next();
// Do something with ad.
}
Mauvaise façon
var campaigns = AdsApp.campaigns().get();
while (campaigns.hasNext()) {
var adGroups = campaigns.next().adGroups().get();
while (adGroups.hasNext()) {
var ads = adGroups.next().ads().get();
while (ads.hasNext()) {
var ad = ads.next();
// Do something with ad.
}
}
}
Il en va de même si vous souhaitez obtenir le parent d’une entité. Au lieu de parcourir la hiérarchie pour obtenir le parent, utilisez la méthode d’accesseur parent de l’entité enfant.
À droite
// Get all ads.
var ads = AdsApp.ads()
.withCondition('Clicks > 5')
.forDateRange('LAST_7_DAYS')
.get();
while (ads.hasNext()) {
var ad = ads.next();
// Do something with campaign and adGroup.
var adGroup = ad.adGroup();
var campaign = ad.campaign();
}
Mauvaise façon
var campaigns = AdsApp.campaigns().get();
while (campaigns.hasNext()) {
var campaign = campaigns.next();
var adGroups = campaign.adGroups().get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
var ads = adGroup.ads().get();
while (ads.hasNext()) {
var ad = ads.next();
if ('<some condition is met>') {
// Do something with campaign and adGroup.
}
}
}
}
Utiliser des ID d’entité lorsque cela est possible
L’utilisation d’ID pour filtrer les entités offre les meilleures performances.
Ce
var adGroups = AdsApp.adGroups()
.withIds(["123456"])
.get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
// Do something with adGroup.
}
Offre de meilleures performances que celle-ci
var adGroups = AdsApp.adGroups()
.withCondition("Name = 'myadgroup'")
.get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
// Do something with adGroup.
}
Évitez les boucles serrées avec des sélecteurs et un nombre inutile de obtient
Évitez les boucles avec des demandes d’obtention qui obtiennent une seule entité. Par exemple, supposons que vous exécutez un rapport de performances mot clé et que vous souhaitez mettre à jour les mots clés dans le rapport. Au lieu d’obtenir une ligne à partir du rapport, d’obtenir la mot clé, puis de la mettre à jour, vous devez créer une liste des ID de mot clé à mesure que vous parcourez chaque ligne du rapport. Ensuite, transmettez la liste des ID au sélecteur pour obtenir tous les mots clés d’une seule demande d’obtention. Vous pouvez ensuite effectuer une itération dans la liste des mots clés et les mettre à jour.
À droite
var report = AdsApp.report('<report query goes here>');
var rows = report.rows();
var idLists = []; // an array where each element contains an array of IDs.
var idList = []; // array of IDs that's limited to maxCount.
var maxCount = 10000;
while (rows.hasNext()) {
var row = rows.next();
if (idList.length < maxCount) {
idList.push(row['id']);
}
else {
idLists.push(idList);
idList = [];
}
}
for (idList of idLists) {
var keywords = AdsApp.keywords()
.withIds(idList)
.get();
while (keywords.hasNext()) {
var keyword = keywords.next();
// update the keyword
}
}
Mauvaise façon
var report = AdsApp.report('<report query goes here>');
var rows = report.rows();
while (rows.hasNext()) {
var row = rows.next();
var keyword = AdsApp.keywords()
.withIds([row['id']])
.get()
.next();
// update the keyword
}
N’incluez la méthode forDateRange que si vous envisagez d’appeler la méthode getStats de l’entité
L’appel de la méthode d’un forDateRange
sélecteur entraîne l’obtention des données de performances de l’entité. L’obtention des données de performances d’une entité est coûteuse. Vous ne les obtenez donc que si vous envisagez d’appeler la méthode de getStats
l’entité et d’utiliser les données.
La plage de dates que vous spécifiez pour une entité ne s’applique pas aux entités parentes ou enfants auxquelles vous accédez à partir de cette entité. Par exemple, si vous obtenez un groupe d’annonces, que vous obtenez sa campagne parente et que vous essayez d’accéder aux métriques de performances de la campagne, l’appel échoue.
L’appel campaignStats.getReturnOnAdSpend()
dans l’exemple suivant échoue, car la plage de dates s’applique au groupe d’annonces et non à la campagne.
var myAdGroups = AdsApp.adGroups().
.withCondition("CampaignName CONTAINS 'gen'")
.forDateRange("LAST_7_DAYS")
.get();
while (myAdGroups.hasNext()) {
var adGroup = myAdGroups.next();
var campaign = adGroup.getCampaign();
var campaignStats = campaign.getStats();
var campaignROAS = campaignStats.getReturnOnAdSpend();
}
Pour que cela fonctionne, vous devez créer un sélecteur pour la campagne.
var myAdGroups = AdsApp.adGroups().
.withCondition("CampaignName CONTAINS 'gen'")
.forDateRange("LAST_7_DAYS")
.get();
while (myAdGroups.hasNext()) {
var adGroup = myAdGroups.next();
var campaign = AdsApp.campaigns()
.withIds([adGroup.getCampaign().getId()])
.forDateRange("LAST_7_DAYS")
.get()
.next();
var campaignStats = campaign.getStats();
var campaignROAS = campaignStats.getReturnOnAdSpend();
}
Ne modifiez pas la propriété d’une entité utilisée comme condition dans le sélecteur
Les itérateurs réduisent la sollicitation de la mémoire en ne chargeant qu’un seul élément à la fois plutôt que l’ensemble des éléments. Pour cette raison, la modification d’une propriété que vous avez utilisée comme condition dans le sélecteur peut entraîner un comportement inattendu.
À droite
var adGroups = [];
var iterator = AdsApp.adGroups()
.withCondition('Status = ENABLED')
.get();
while (iterator.hasNext()) {
adGroups.push(iterator.next());
}
for (var adGroup of adGroups) {
adGroup.pause();
}
Mauvaise façon
var adGroups = AdsApp.adGroups()
.withCondition('Status = ENABLED')
.get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
adGroup.pause();
}
Mises à jour de traitement par lot
Afin d’améliorer les performances, Scripts traite les demandes de génération par lots. Si vous appelez la méthode d’opération d’une demande de build, cela force Scripts à traiter immédiatement les demandes de build mises en file d’attente, ce qui annule les gains de performances. Si vous créez plusieurs entités, n’exécutez pas les méthodes d’opération dans la même boucle que celle que vous utilisez pour générer l’entité. Cela entraîne des performances médiocres, car une seule entité à la fois est traitée. Au lieu de cela, créez un tableau des opérations et traitez-les après la boucle de génération.
À droite
// An array to hold the operations, so you
// can process them after all the entities are queued.
var operations = [];
// Create all the new entities.
for (var i = 0; i < keywords.length; i++) {
var keywordOperation = AdsApp.adGroups().get().next()
.newKeywordBuilder()
.withText(keywords[i])
.build();
operations.push(keywordOperation);
}
// Now call the operation method so the build requests
// get processed in batches.
for (var i = 0; i < operations.length; i++) {
var newKeyword = operations[i].getResult();
}
Mauvaise façon
for (var i = 0; i < keywords.length; i++) {
var keywordOperation = AdsApp.adGroups().get().next() // Get the first ad group
.newKeywordBuilder() // Add the keyword to the ad group
.withText(keywords[i])
.build();
// Don't get results in the same loop that creates
// the entity because Scripts then only processes one
// entity at a time.
var newKeyword = keywordOperation.getResult();
}
Il en va de même si vous mettez à jour une entité, puis obtenez la même propriété que celle que vous avez mise à jour. Ne procédez pas comme suit :
var bidAmount = 1.2;
while (keywords.hasNext()) {
var keyword = keywords.next();
keyword.bidding().setCpc(bidAmount);
if (keyword.bidding().getCpc() != bidAmount) {
Logger.log(`Failed to update bid amount for keyword, ${keyword.getText()} (${keyword.getId()})`);
}
}
Utiliser la mot clé de rendement lors de l’obtention de grands ensembles d’entités
La récupération d’un grand nombre d’entités et leur chargement dans une liste unique que vous traitez dans une boucle présente deux inconvénients :
En fonction de la taille de la demande, il peut s’avérer nécessaire de n nombre de requêtes back-end pour extraire toutes les entités avant le démarrage de la boucle. Si vous ne les traitez pas tous, le temps et la puissance de calcul utilisés pour obtenir les entités non traitées sont gaspillés. Par exemple, si vous récupérez 10 000 mots clés et que la boucle s’interrompt après avoir traité seulement 2 000 mots clés, le temps et la puissance de calcul utilisés pour obtenir les mots clés 8K restants sont gaspiller.
La création de la liste nécessite plus de mémoire pour contenir toutes les entités en même temps.
Pour résoudre ces problèmes, utilisez la mot clé de rendement, qui permet à votre script d’extraire des entités à la demande, ou, dans un certain sens, de les extraire de manière « différée » uniquement lorsqu’elles sont nécessaires. Cela signifie que votre script n’effectue pas plus d’appels qu’il n’en a besoin pour le moment et ne passe pas de grandes listes d’objets.
Cet exemple inclut la journalisation pour illustrer le flux de contrôle lors de l’utilisation de la mot clé de rendement.
function main() {
const keywords = getKeywords();
//@ts-ignore <-- suppresses iterator error
for (const keyword of keywords) {
Logger.log("in for loop\n\n");
}
}
// Note that you must use the yield keyword in a generator function - see the
// '*' at the end of the function keyword.
function* getKeywords() {
const keywords = AdsApp.keywords()
.withCondition("Status = ENABLED")
.withCondition("CombinedApprovalStatus = APPROVED")
.withLimit(10)
.get();
Logger.log(`total keywords in account: ${keywords.totalNumEntities()} \n\n`);
while (keywords.hasNext()) {
Logger.log("before next()\n\n");
yield keywords.next();
Logger.log("after next\n\n");
}
}
Modèle d’appel pour éviter les limites d’entité
Il existe une limite au nombre d’entités que les scripts peuvent retourner pour un compte. Si la requête retourne plus que cette limite, scripts génère une erreur avec le message « Il y a trop d’entités ». L’exemple suivant montre le modèle d’appel que vous devez utiliser lors de l’obtention d’un grand nombre d’entités. L’exemple tente d’abord d’extraire tous les mots clés au niveau du compte. En cas d’échec, il tente d’effectuer plusieurs appels pour extraire des mots clés par campagne, car il y a généralement moins d’entités au niveau de la campagne. Vous pouvez généralement poursuivre ce modèle jusqu’au niveau du groupe d’annonces si nécessaire.
Pour plus d’informations sur l’utilisation de l’mot clé de rendement, consultez Utiliser la mot clé de rendement lors de l’obtention de grands ensembles d’entités.
function* getEntities() {
const applyConditions = _ => _
.withCondition('CampaignStatus = ENABLED')
.withCondition('AdGroupStatus = ENABLED')
.withCondition('Status = ENABLED')
.withCondition("CombinedApprovalStatus = DISAPPROVED");
try {
// Get the account's keywords.
const keywords = applyConditions(AdsApp.keywords()).get();
while (keywords.hasNext()) {
yield keywords.next();
}
} catch (e) {
if (!e.message.startsWith('There are too many entities')) {
throw e;
}
// If there are too many keywords at the account level,
// get keywords by campaigns under the account.
const campaigns = AdsApp.campaigns().get();
while (campaigns.hasNext()) {
const campaign = campaigns.next();
const keywords = applyConditions(campaign.keywords()).get();
while (keywords.hasNext()) {
yield keywords.next();
}
}
}
}