Procedure consigliate per Microsoft Advertising Scripts
Per migliorare le prestazioni degli script e della piattaforma, esaminare e seguire le procedure consigliate descritte di seguito.
Uso dei selettori
Usare i filtri
Usare i filtri di un selettore invece di filtrare le entità manualmente. I selettori consentono di filtrare in base agli ID e alle condizioni. Ad esempio, è possibile filtrare in base alle prestazioni di un'entità (campagna restituita con un CPC medio maggiore di 10), il relativo stato (campagna sospesa), il nome dell'oggetto padre dell'entità e altro ancora.
Vantaggi dell'uso dei filtri:
Limita il numero di entità restituite dal selettore solo alle entità necessarie.
Consente di eseguire lo script più velocemente (meno entità da restituire ed elaborare)
Riduce la probabilità di urtare contro i limiti di lettura delle entità (vedere Limiti di esecuzione dello script).
Giusto modo
var adGroups = AdsApp.adGroups()
.withCondition('Status = PAUSED')
.get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
// Do something with paused ad group.
}
Modo sbagliato
var adGroups = AdsApp.adGroups().get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
if (adGroup.isPaused() == true) {
// Do something with paused ad group.
}
}
Non attraversare la gerarchia di entità
Se si desidera ottenere le entità figlio di un'entità o l'entità padre dell'entità, non attraversare la gerarchia di entità per ottenerle.
Per ottenere entità figlio, usare la raccolta dell'entità figlio al livello desiderato.
Giusto modo
// Get all ads.
var ads = AdsApp.ads().get();
while (ads.hasNext()) {
var ad = ads.next();
// Do something with ad.
}
Oppure, se vuoi annunci da una campagna specifica:
// 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.
}
In alternativa, ottenere gli annunci di una campagna se si dispone dell'oggetto campagna:
// Get all ads in the campaign.
var ads = campaign.ads().get();
while (ads.hasNext()) {
var ad = ads.next();
// Do something with ad.
}
Modo sbagliato
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.
}
}
}
Lo stesso vale se si vuole ottenere l'elemento padre di un'entità. Anziché attraversare la gerarchia per ottenere l'elemento padre, usare il metodo della funzione di accesso padre dell'entità figlio.
Giusto modo
// 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();
}
Modo sbagliato
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.
}
}
}
}
Usare gli ID entità quando possibile
L'uso degli ID per filtrare le entità offre prestazioni ottimali.
Questo
var adGroups = AdsApp.adGroups()
.withIds(["123456"])
.get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
// Do something with adGroup.
}
Offre prestazioni migliori rispetto a questo
var adGroups = AdsApp.adGroups()
.withCondition("Name = 'myadgroup'")
.get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
// Do something with adGroup.
}
Evitare cicli stretti con selettori e un numero non necessario di ottiene
Evitare cicli con richieste get che ottengono una singola entità. Si supponga, ad esempio, di eseguire un report sulle prestazioni delle parole chiave e di voler aggiornare le parole chiave nel report. Anziché ottenere una riga dal report, ottenere la parola chiave e quindi aggiornarla, è necessario creare un elenco degli ID parola chiave durante il ciclo di ogni riga del report. Passare quindi l'elenco di ID al selettore per ottenere tutte le parole chiave in una singola richiesta get. È quindi possibile eseguire l'iteratore tramite l'elenco di parole chiave e aggiornarle.
Giusto modo
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
}
}
Modo sbagliato
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
}
Includere il metodo forDateRange solo se si prevede di chiamare il metodo getStats dell'entità
Se si chiama il metodo di forDateRange
un selettore, il selettore ottiene i dati sulle prestazioni dell'entità. Ottenere i dati sulle prestazioni di un'entità è costoso, quindi ottenerli solo se si prevede di chiamare il metodo dell'entità getStats
e usare i dati.
L'intervallo di date specificato per un'entità non si applica alle entità padre o figlio a cui si accede da tale entità. Ad esempio, se si ottiene un gruppo di annunci e quindi si ottiene la campagna padre e si tenta di accedere alle metriche delle prestazioni della campagna, la chiamata ha esito negativo.
La campaignStats.getReturnOnAdSpend()
chiamata nell'esempio seguente ha esito negativo perché l'intervallo di date si applica al gruppo di annunci e non alla campagna.
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();
}
Per il funzionamento di questa operazione, è necessario creare un selettore per la campagna.
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();
}
Non modificare la proprietà di un'entità usata come condizione nel selettore
Gli iteratori riducono la pressione della memoria caricando un solo elemento alla volta anziché l'intero set di elementi. Per questo motivo, la modifica di una proprietà usata come condizione nel selettore può causare un comportamento imprevisto.
Giusto modo
var adGroups = [];
var iterator = AdsApp.adGroups()
.withCondition('Status = ENABLED')
.get();
while (iterator.hasNext()) {
adGroups.push(iterator.next());
}
for (var adGroup of adGroups) {
adGroup.pause();
}
Modo sbagliato
var adGroups = AdsApp.adGroups()
.withCondition('Status = ENABLED')
.get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
adGroup.pause();
}
Invio in batch degli aggiornamenti
Per migliorare le prestazioni, script elabora le richieste di compilazione in batch. Se si chiama il metodo di operazione di una richiesta di compilazione, gli script devono elaborare immediatamente le richieste di compilazione in coda, negando eventuali miglioramenti delle prestazioni. Se si creano più entità, non eseguire i metodi di operazione nello stesso ciclo usato per compilare l'entità. Ciò comporta prestazioni scarse perché viene elaborata una sola entità alla volta. Creare invece una matrice delle operazioni ed elaborarle dopo il ciclo di compilazione.
Giusto modo
// 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();
}
Modo sbagliato
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();
}
Lo stesso vale se si aggiorna un'entità e quindi si ottiene la stessa proprietà aggiornata. Non eseguire questa operazione:
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()})`);
}
}
Usare la parola chiave yield per ottenere set di entità di grandi dimensioni
Il recupero di un numero elevato di entità e il caricamento in un singolo elenco elaborato in un ciclo presenta un paio di svantaggi:
A seconda delle dimensioni della richiesta, potrebbero essere necessari n numero di richieste back-end per recuperare tutte le entità prima dell'avvio del ciclo. Se non vengono elaborati tutti, il tempo e la potenza di calcolo usati per ottenere le entità non elaborate vengono sprecati. Ad esempio, se si recuperano parole chiave da 10K e il ciclo si interrompe dopo l'elaborazione di solo parole chiave 2K, il tempo e la potenza di calcolo usati per ottenere le rimanenti parole chiave 8K vengono sprecati.
La creazione dell'elenco richiede più memoria per contenere tutte le entità contemporaneamente.
Per risolvere questi problemi, usare la parola chiave yield , che consente allo script di recuperare le entità su richiesta o, in un certo senso, recuperarle "pigramente" solo quando sono necessarie. Ciò significa che lo script non esegue più chiamate di quanto sia necessario al momento e non passa in giro elenchi di oggetti di grandi dimensioni.
Questo esempio include la registrazione per illustrare il flusso del controllo quando si usa la parola chiave yield .
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");
}
}
Modello di chiamata per evitare limiti di entità
Esiste un limite al numero di entità che gli script possono restituire per un account. Se la richiesta restituisce più di questo limite, script genera un errore con il messaggio, Sono presenti troppe entità. Nell'esempio seguente viene illustrato il modello di chiamata da usare quando si ottiene un numero elevato di entità. L'esempio tenta di recuperare prima tutte le parole chiave a livello di account. In caso di esito negativo, tenta di effettuare più chiamate per recuperare parole chiave per campagna, poiché in genere sono presenti meno entità a livello di campagna. In genere puoi continuare questo modello fino al livello del gruppo di annunci, se necessario.
Per informazioni sull'uso della parola chiave yield , vedere Usare la parola chiave yield quando si ottengono set di entità di grandi dimensioni.
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();
}
}
}
}