Check if Campaign has Endedn

317 views
Skip to first unread message

Sindy T

unread,
Feb 24, 2021, 10:45:43 PM2/24/21
to Google Ads Scripts Forum
Hi, 

Is it possible to create a script that checks if the campaign status is 'ended' on a daily basis and if so, send an email on that?

I saw this script, is there any way I could combine this
/**
 * Return true when id campaign ended
 *
 * @param {AdWordsApp.​Campaign} Campaign
 * @return {Boolean} True if campaign ended
 */
function isCampaignEnded(campaign){
 var campaignEndDate = campaign.getEndDate();
 if(campaignEndDate == null) {
 return false;
 }

 var endDate = new Date(campaignEndDate.year, campaignEndDate.month - 1, campaignEndDate.day, 23, 59, 59);
 var currentDate = new Date();

 return currentDate.getTime() > endDate.getTime();
}

with this, removing the impressions = 0 conditions, just to solely use it for ended campaign?

var config = {

 

  LOG : true,

 

  EMAIL : "X...@XX.com.sg",

  EMAIL_INTRO : "The following campaigns have ended!<br />",

  EMAIL_SUBJECT : " Ended Campaigns",

 

  DATE_RANGE : "TODAY",

  COMPARE : true,

  COMPARE_DATERANGE : "LAST_7_DAYS",

  ACCOUNT_LABEL : "X"

 

}

 

////////////////////////////////////////////////////////////////////

 

function main() {

 

  var emailContent = config.EMAIL_INTRO;

 

  var accountIterator = MccApp

              .accounts()

              .withCondition("LabelNames CONTAINS '" + config.ACCOUNT_LABEL + "'")

              .get();

 

  while(accountIterator.hasNext()){

    var account = accountIterator.next();

    MccApp.select(account);

 

    var campaignIterator = AdsApp

              .campaigns()

              .withCondition("Status = ENABLED")

              .withCondition("Impressions = 0")

              .withCondition("CampaignExperimentType = BASE")

              .withCondition("ServingStatus = SERVING")

              .forDateRange("TODAY")

              .get();

   

                //Add accountname as heading in email

        if(campaignIterator.hasNext()){

          emailContent += "<br /><b>" + account.getName() + "</b><br />";

         

          if(config.LOG === true){

            Logger.log("Account: " + account.getName());

          }

        }

   

    while(campaignIterator.hasNext()){

      var campaign = campaignIterator.next();

     

      // Only add campaigns with > 0 impressions previous period

      if(config.COMPARE === true){

       

        // Check for impressions previous period

        if(campaign.getStatsFor(config.COMPARE_DATERANGE).getImpressions() > 0){

         

          if(config.LOG === true){

            Logger.log("Campaign: " + campaign.getName());

          }

         

          emailContent += campaign.getName() + "<br />";

         

        }

       

      } // compare with previous period

      else {

       

        if(config.LOG === true){

          Logger.log("Campaign: " + campaign.getName());

        }

     

        emailContent += campaign.getName() + "<br />";

       

      }

     

    } // campaignIterator   

   

    var shoppingCampaignIterator = AdsApp

      .shoppingCampaigns()

      .withCondition("Status = ENABLED")

      .withCondition("Impressions = 0")

      .withCondition("CampaignExperimentType = BASE")

      .withCondition("ServingStatus = SERVING")

      .forDateRange("TODAY")

      .get();

   

    //Add accountname as heading in email

    if(shoppingCampaignIterator.hasNext() && !campaignIterator.hasNext()){

      emailContent += "<br /><b>" + account.getName() + "</b><br />";

     

      if(config.LOG === true){

        Logger.log("Account: " + account.getName());

      }

    }

   

    while(shoppingCampaignIterator.hasNext()){

      var campaign = shoppingCampaignIterator.next();     

 

      // Only add campaigns with > 0 impressions previous period

      if(config.COMPARE === true){

       

        // Check for impressions previous period

        if(campaign.getStatsFor(config.COMPARE_DATERANGE).getImpressions() > 0){

         

          if(config.LOG === true){

            Logger.log("Campaign: " + campaign.getName());

          }

         

          emailContent += campaign.getName() + "<br />";

         

        }

       

      } // compare with previous period

      else {

       

        if(config.LOG === true){

          Logger.log("Campaign: " + campaign.getName());

        }

     

        emailContent += campaign.getName() + "<br />";

       

      }

     

    } // shoppingCampaignIterator   

   

    if(config.LOG === true){

      Logger.log("----");

    }

   

  } // accountIterator

 

  sendEmail(emailContent);

  Logger.log(emailContent);

 

} // function main

 

////////////////////////////////////////////////////////////////////

 

function sendEmail(emailContent) {

 

  MailApp.sendEmail({

    to: config.EMAIL,

    subject: config.EMAIL_SUBJECT,

    htmlBody: emailContent});

 

} // function sendEmail



Thanks.

Sigurd Fabrin

unread,
Feb 25, 2021, 3:45:42 AM2/25/21
to Google Ads Scripts Forum
Hi, 

Sure, that is possible :)

In your code you filter on serving campaigns .withCondition("ServingStatus = SERVING") at least you need to change that to fetch the ended campaigns.

-----

I would use a different approach - opting for AdsApp.report() instead. It's faster and simpler.

You are welcome to use my short script below


// Send email with list of campaigns that received impressions yesterday but have now ended
// schedule to run daily

var settings = {

  notify: 'sig...@example.com', // send email to this address
  cc: 'anothe...@example.com', // optional extra emails. One string only and sep. by comma
  scriptName: 'Send email with list of ended campaigns', // should match actual name of script in account
  
}

function main() { 
  var campaigns = [];
  var report = AdsApp.report(
    'SELECT ' +
    'CampaignName ' +
    'FROM CAMPAIGN_PERFORMANCE_REPORT ' +
    'WHERE ServingStatus IN ["ENDED"] ' +
    'AND Impressions > 0 ' +
    'DURING YESTERDAY'
  )
    var rows = report.rows();
  while (rows.hasNext()) {
    campaigns.push(rows.next()['CampaignName'])
  }
 if (campaigns.length > 0) {
   var account = AdsApp.currentAccount().getName();
   MailApp.sendEmail(settings.notify,'Ended campaigns in Google Ads account: "'+account+'"',
                     'Here\'s a list of '+campaigns.length+' campaigns that received impressions yesterday but have now ended.\n\n'+campaigns.join('\n')+
                     '\n\n---\n*Notification sent by the script "'+settings.scriptName+'" running in this account: "'+account+'"\n sigurd',{cc:settings.cc})
   Logger.log('Found '+campaigns.length+' ended campaigns with impressions yesterday. Mail sent to: '+settings.notify+' and cc to: '+settings.cc)
 }
  else {Logger.log('Didn\'t find any ended campaigns with impressions yesterday')}
}


 sigurd



Sindy T

unread,
Feb 25, 2021, 8:04:15 AM2/25/21
to Google Ads Scripts Forum

Hi sigurd,

Thank you so much, will try that out!

Google Ads Scripts Forum Advisor

unread,
Feb 26, 2021, 3:31:50 AM2/26/21
to adwords...@googlegroups.com
Hi Sigurd,

Thank you for actively sharing you knowledge to Google Ads Script community forum.

@Sindy,

Please let me know how it goes after doing what Sigurd suggested.

Regards,
Google Logo
Teejay Wennie Pimentel
Google Ads Scripts Team
 


ref:_00D1U1174p._5004Q2DIopC:ref

Sindy T

unread,
Mar 23, 2021, 7:40:44 AM3/23/21
to Google Ads Scripts Forum

Hi Sigurd & Teejay,

Unfortunately, the codes didn't work (I did made the changes in the //comments accordingly).
Would it be better if the codes are based on all the ended 'status' instead of comparison against yesterday's?
How do I add another campaign label filter so it won't be applied to all campaigns?
 Is it using   .withCondition("LabelNames CONTAINS '" + config.ACCOUNT_LABEL + "'")?

Thanks!

Google Ads Scripts Forum Advisor

unread,
Mar 23, 2021, 11:29:22 PM3/23/21
to adwords...@googlegroups.com
Hi Sindy,

Thanks for coming back. I am Harry, teammate of Teejay on the Google Ads Scripts Team. 

Can you kindly provide context as to how the script didn't worked? Sigurd's suggestion is a simpler script so integrating it to the script you found is another discussion. If you want to check campaigns that have ended on a daily basis, then you should set the forDateRange to TODAY instead of YESTERDAY and schedule the script to execute daily. You may utilize the withCondition method to filter campaigns that would be returned by the selector. Kindly refer to Campaign Columns to see other fields you can filter and yes, you may use a label filter like the one you referenced. Just take note of the value you are comparing the LabelNames with.

For further assistance, kindly provide your CID and the script's name so I could check what you have so far on our end.


Thanks,
Google Logo
Harry Cliford Rivera
Google Ads Scripts Team
 


ref:_00D1U1174p._5004Q2DIopC:ref

Sindy T

unread,
Mar 24, 2021, 12:15:48 AM3/24/21
to Google Ads Scripts Forum
Hi Harry,

I don't need to have it integrated with the script that I have found.
I just need a script to check for campaigns that have 'ended' with these conditions:
- Campaigns that are active
- Certain label
- Send an email on the campaigns that have ended

Initially, I tried to set 'rules' for that instead but Google support told me it wasn't supported at the moment :(

Google Ads Scripts Forum Advisor

unread,
Mar 24, 2021, 3:14:46 AM3/24/21
to adwords...@googlegroups.com
Hi Sindy,

Thanks for clarifying your requirement. Kindly try the below CampaignSelector for your use case:
 
  var campaignSelector = AdsApp.videoCampaigns()
   .withCondition("Status = ENABLED")
   .withCondition("ServingStatus = ENDED")
   // Option to filter by LabelNames
   //.withCondition("LabelNames CONTAINS_ANY ['Test']")

After that, use a CampaignIterator to iterate through the returned campaigns and retrieve campaign information or statistics that you need to be emailed to you. Kindly refer to this example on how you can use the MailApp service through scripts.

Let me know how it goes and if you have questions or clarifications.

Avkeren

unread,
Jul 23, 2023, 11:23:33 AM7/23/23
to Google Ads Scripts Forum
Hi,
It looks like that ServingStatus  no longer exists.
So how can this be done?
Thanks in advance...


Nils Rooijmans

unread,
Jul 24, 2023, 3:28:03 AM7/24/23
to Google Ads Scripts Forum
one solution: you can use GAQL queries to retrieve campaigns that have ended:

function main() {

  var campaignIds = [];

  var gaqlQuery = "SELECT campaign.id, campaign.name, campaign.serving_status FROM campaign WHERE campaign.serving_status = 'ENDED'";

  var queryResults = AdsApp.search(gaqlQuery);

  while (queryResults.hasNext()) {
    var result = queryResults.next();
    var campaignId = result.campaign.id;
    var campaignName = result.campaign.name;
    var campaignServingStatus = result.campaign.servingStatus;
    console.log(`campaign '${campaignName}' has status '%s'`, campaignServingStatus); // notice the use of backquotes here.
    campaignIds.push(campaignId);
  }
}


this will give you an array with the id's of all campaigns that have ended.

Hope this helps,

Nils Rooijmans
https://nilsrooijmans.com
See my Google Ads Scripts FAQ to avoid the same mistakes I made: https://nilsrooijmans.com/google-ads-scripts-faq/

Google Ads Scripts Forum Advisor

unread,
Jul 24, 2023, 4:41:17 AM7/24/23
to adwords...@googlegroups.com

Hi All,

 

@Nils - Thank you for providing a solution to this.

 

@Avkeren - I would agree with Nils as the provided approach is good to follow. If you would only need to make use of an iterator, then you would just need to migrate the snippet of code our team previously provided to the new script experience environment. I would recommend checking the resource mapping documentation in order to get you started as it states there that the field ServingStatus maps to the field campaign.serving_status. Kindly see below for reference:

var campaignSelector = AdsApp.videoCampaigns()
   .withCondition("campaign.serving_status = 'ENDED'");

 

Let us know if you have any further clarifications.

 

Reference links:

 

This message is in relation to case "ref:_00D1U1174p._5004Q2DIopC:ref"

Thanks,
 
Google Logo Google Ads Scripts Team


Avkeren Cohen

unread,
Jul 26, 2023, 12:57:36 AM7/26/23
to Nils Rooijmans via Google Ads Scripts Forum
Nils,
Thank you very much.
Your time and efforts helping here are much appreciated.

--
-- You received this message because you are subscribed to the Google Groups AdWords Scripts Forum group. Please do not reply to this email. To post to this group or unsubscribe please visit https://developers.google.com/adwords/scripts/community.
---
You received this message because you are subscribed to a topic in the Google Groups "Google Ads Scripts Forum" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/adwords-scripts/LMZUn5cxqu0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to adwords-scrip...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/adwords-scripts/af504fee-c15e-4f5e-bfaf-00c47c53433bn%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages