Create SKAGs

231 views
Skip to first unread message

Del Stone

unread,
May 17, 2018, 12:32:14 AM5/17/18
to AdWords Scripts Forum
Hi,
I'm looking for help to put together a script that would automatically loop through all kws in all campaigns and create skags for those kws that had the most impressions/clicks/convs using ads copied from the same adgroup.

Could you help with some outline code that will help with this?

Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
May 17, 2018, 7:37:34 AM5/17/18
to AdWords Scripts Forum
Hello Del,

You may find the below sample code to help you get started. The code below will get all campaigns and iterate each adGroup then get the keyword with the highest impression. You may use this as reference for getting keyword with most clicks and conversions as well. After the script finds the highest impression, you may perform adding the new keyword using KeywordBuilder inside a new adGroup using AdGroupBuilder.

function main() {

   
// Fetch All campaigns
   
var campaignsIterator = AdWordsApp.campaigns().get();

   
// Iterate AdGroups
   
while (campaignsIterator.hasNext()) {
       
var campaign = campaignsIterator.next();
       
var adGroupsIterator = campaign.adGroups().get();

       
while (adGroupsIterator.hasNext()) {
           
var adGroup = adGroupsIterator.next();

           
// Fetch kewwords for each AdGroups
           
var keywordsIterator = AdWordsApp.keywords().withCondition('AdGroupName = "' + adGroup.getName() + '"').get();

           
if (keywordsIterator.totalNumEntities() > 0) {

               
var arrSort = [];

               
while (keywordsIterator.hasNext()) {
                   
var keyword = keywordsIterator.next();;
                   
var stats = keyword.getStatsFor("INSERT_DATE_RANGE_HERE");
                   
var impressions = stats.getImpressions();
                   
var arrayImpresssion = [impressions, keyword];
                    arrSort
.push(arrayImpresssion);
               
}

               
// Sort by Impressions
                arrSort
.sort(function(a, b) {
                   
return a[0] - b[0];
               
});

               
// Get the most impressions keyword in the AdGroup
               
var arrSize = arrSort.length - 1;
               
var mostImpKW = arrSort[arrSize][1];

               
// Perform the single keyword ad group creation here using Keywordbuilder and AdGroupBuilder

                arrSort
= [];
           
}
       
}

   
}

}

Please let me know if this is what you are looking for.

Regards,
Hiroyuki
AdWords Scripts Team

Del Stone

unread,
May 17, 2018, 10:27:42 PM5/17/18
to AdWords Scripts Forum
Given we have 500k kws, I'ved updated the code to use a report to filter the necessary kw ids otherwise we'd hit limits - however:
-  I can't seem to get the report to work correctly with the filters with various errors appearing when I try varying the filters (eg Invalid reporting query: INVALID_PREDICATE_ENUM_VALUE: Exact. (line 21))
-  I'm not sure how to copy the ads across from the previous adgroup to the next further below

Could you please review and help me complete the code.

function main() {

  var MIN_IMPRESSIONS = 100;
  var MIN_CLICKS      = 5;
  var LAST_N_DAYS     = 7;
  var report          = 'KEYWORDS_PERFORMANCE_REPORT';
  var cols            = ['AdGroupId', 'Id', 'KeywordMatchType', 'Impressions', 'Clicks'];
  var options         = { includeZeroImpressions : false };
  var dateTo          = getAdWordsFormattedDate(0, 'yyyyMMdd');
  var dateFrom        = getAdWordsFormattedDate(LAST_N_DAYS, 'yyyyMMdd');
  var DATE_RANGE      = dateFrom + ',' + dateTo;

  var query   = ['select', cols.join(','),
                 'from', report,
  'where CampaignStatus = ENABLED AND AdGroupStatus = ENABLED AND Status = ENABLED',
  'and Impressions >= ' + MIN_IMPRESSIONS + ' ',
                 'and Clicks >= ' + MIN_CLICKS + ' ',
                 'and KeywordMatchType = "Exact"',
  'during', DATE_RANGE].join(' ');
  
  var reportIter = AdWordsApp.report(query, options).rows();

  var kwIds = [];
  
  while(reportIter.hasNext()) {
var reportRow = reportIter.next();
  kwIds.push([reportRow.AdGroupId, reportRow.Id]);
    log('Keywords Found: ' + reportRow.AdGroupId + "-" + reportRow.Id);  
  }

  log('Keywords Found: ' + kwIds.length);  
  
  var kws = AdWordsApp.keywords()
    .withIds(kwIds).get();
  log('Keywords Found: ' + kws.totalNumEntities()); 
  
  while (kws.hasNext()) { 
    var kw = kws.next(); 
    
    addKeywordToNewAdGroup(campaignName, kw)
  }
                                                                                                                   
  exit();
}

function addKeywordToNewAdGroup(keyword) {

var campaign        = keyword.getCampaign();
  var campaignName    = campaign.getName();
  var adGroupName     = keyword.getAdGroup().getName();
    var adGroupIterator = AdWordsApp.adGroups().withCondition('CampaignName = "' + campaignName + '" AND Name = "' + adGroupName + '"').get();
    
    if (adGroupIterator.hasNext()) {
      var adGroup = adGroupIterator.next();  
      
      var adGroupBuilder = campaign.newAdGroupBuilder();
      var adGroupOperation = adGroupBuilder
            .withName("SKAG | " & keyword.getText() & " | EXACT")
            .withStatus("ENABLED")
      .withCpc(0.3)
            .build();

  if(adGroupOperation.isSuccessful()) {
        var keywordOperation = adGroup.newKeywordBuilder()
            .withText(keyword.getText())
            .withCpc(0.5)
            .build();

        // Remove the Keyword from original campaign
        if(keywordOperation.isSuccessful()) {
          Logger.log("Added keyword to Adgroup and now removing " + keyword.getText());
          keyword.remove();

          // Copy ads across to new adgroup
          var adsIterator = adGroup.ads().get();
          while (adsIterator.hasNext()) {
            var ad = adsIterator.next();
            
            // how do I copy the ads across?
            
          }
          
        }
     }
  } 
}

function getAdWordsFormattedDate(d, format){
  var date = new Date();
  
  date.setDate(date.getDate());
  
  return Utilities.formatDate(date,AdWordsApp.currentAccount().getTimeZone(),format);
}

function log(msg) {
  var time = Utilities.formatDate(new Date(),AdWordsApp.currentAccount().getTimeZone(), 'dd-MM-yyyy HH:mm:ss');
  
  Logger.log(time + ' – ' + msg);
}


Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
May 18, 2018, 3:51:09 AM5/18/18
to AdWords Scripts Forum
Hello Del,

The reason why you are encountering the error is because of "Exact" at line 18 in your script. Could you please replace it to "EXACT" (capital letters) and try to test the script again? You may refer to available values for KeywordMatchType in this documentation.

Regarding copying the ads, unfortunately, there is no direct function to do that. You need to get the specific ad first, then get all values and pass those values using AdBuilder to create a new ad with the same values of existing ads.
 
Also, based on the requirements you provided in the previous responses, you want to create a new adGroup and new keyword in it, then copy all ads from existing adGroup into the newly created adGroup. However, at line 64 in your script, a new keyword is created in an existing adGroup. It should be the newly created adGroup which is created in line 57.

Please let me know if you have further clarifications.

delstone

unread,
May 18, 2018, 9:25:17 AM5/18/18
to AdWords Scripts Forum on behalf of Hiroyuki Miyauchi (AdWords Scripts Team)

Thanks for that Hiroyuki.

 

How do I fill the various parts of the ad for call ads? One the help documentation it seems to refer to text ads rather than call ads.

--
-- 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 the Google Groups "AdWords Scripts Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adwords-scrip...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/adwords-scripts/c9ac6b0f-e9ab-47ec-b76e-9a038a7a4bde%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Del Stone

unread,
May 18, 2018, 5:31:08 PM5/18/18
to AdWords Scripts Forum
I've looked through all the documentation - it appears it's not possible to get the fields for call only ads - this is where I'm stuck:

            var adOperation = adGroupNew.getResult().newTextAdBuilder()
                .withHeadline("headline of ad")
                .withDescription1("first line of ad description")
                .withDescription2("second line of ad description")
                .withDisplayUrl(ad.getDisplayUrl())
                .withFinalUrl("http://www.example.com")
                .build();



Jake Baker

unread,
May 20, 2018, 8:44:45 AM5/20/18
to Del Stone via AdWords Scripts Forum
Why am I receiving these emails? These are topics from other people.

--
-- 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 the Google Groups "AdWords Scripts Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adwords-scripts+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/adwords-scripts/96224766-04ac-4164-a456-084924351772%40googlegroups.com.

Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
May 21, 2018, 1:55:16 AM5/21/18
to AdWords Scripts Forum
Hello Del,

Since your main objective is to ad copy existing ads, then unfortunately, creating a new call-only ads is not supported in AdWords Scripts at this time. You may refer to the AdBuilderSpace and samples to see the current available ad types.

You may follow our blog for any upcoming features and updates.


Hello Jake,

If you are receiving notification on unrelated topics to yours, please ignore them and feel free to write on a new forum thread if you will have concerns on AdWords Scripts. You may have also clicked on the Email Updates to me option in this thread that's why you're receiving updates on this.

Del Stone

unread,
Oct 26, 2018, 9:20:09 AM10/26/18
to AdWords Scripts Forum
Hi Hiroyuki,

If I wanted to create new extended text ads instead, could you let me know what code I would need?

Thanks in advance.

Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
Oct 29, 2018, 5:12:51 AM10/29/18
to AdWords Scripts Forum
Hello Del,

Could you please confirm if what you are referring is expanded text ads? If yes, you may refer to this guide and this sample.

If you have more questions not related to this thread, please feel free to create a new thread.

Regards,
Hiroyuki
AdWords Scripts Team

Del Stone

unread,
Nov 4, 2018, 8:05:40 AM11/4/18
to AdWords Scripts Forum
Hi Hiroyuki,

When running the above code I'm getting the error - any thoughts what the problem is?

04/11/2018 13:00:49TypeError: Cannot find function newKeywordBuilder in object [object Object]. (file Code.gs, line 68) - line 68 is highlighted below


      var adGroup = adGroupIterator.next();  
      
      var adGroupBuilder = campaign.newAdGroupBuilder();
      var adGroupOperation = adGroupBuilder
            .withName("SKAG | " & keyword.getText() & " | EXACT")
            .withStatus("ENABLED")
      .withCpc(0.30)
            .build();

  if(adGroupOperation.isSuccessful()) {
>>        var keywordBuilder = adGroupBuilder.newKeywordBuilder();
        var keywordOperation = keywordBuilder
            .withText('['+keyword.getText()+']')
            .withCpc(0.30)
            .build();


Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
Nov 5, 2018, 12:49:13 AM11/5/18
to AdWords Scripts Forum
Hello Del,

You are encountering the issue since there is no .newKeywordBuilder() method for the AdGroupBuilder in AdWords Scripts. If you want to create a new keyword associated with an AdGroup, you may utilize newKeywordBuilder() method of the AdGroup entity instead of the AdGroupBuilder.

Also, if you have further clarifications and since your concern is not related to this thread, could you please create a new thread with more details such as what you want to achieve with AdWords Scripts?

Regards,
Hiroyuki
AdWords Scripts Team

Del Stone

unread,
Nov 5, 2018, 3:31:56 AM11/5/18
to AdWords Scripts Forum on behalf of Hiroyuki Miyauchi (AdWords Scripts Team)
Could you show me what the code would look like? I don't understand your answer.

--
-- 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 the Google Groups "AdWords Scripts Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adwords-scrip...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/adwords-scripts/eef95bf9-9f57-4b4e-85af-242cfadcfccc%40googlegroups.com.

Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
Nov 5, 2018, 4:58:09 AM11/5/18
to AdWords Scripts Forum
Hello Del,

You may add the code below after you create an AdGroup. It will fetch the newly created AdGroup from AdGroupOperation by getResult() method, and create a new keyword associated with the AdGroup.

if (adGroupOperation.isSuccessful()) {

   
var adGroup = adGroupOperation.getResult();
   
var keywordBuilder = adGroup.newKeywordBuilder();

   
var keywordOperation = keywordBuilder
       
.withText('[' + keyword.getText() + ']')
       
.withCpc(0.30)
       
.build();

}

Please let me know how it goes after trying the suggestion.

Regards,
Hiroyuki
AdWords Scripts Team

On Monday, November 5, 2018 at 4:31:56 PM UTC+8, Del Stone wrote:
Could you show me what the code would look like? I don't understand your answer.

delstone...@gmail.com

unread,
Nov 5, 2018, 10:58:06 AM11/5/18
to AdWords Scripts Forum on behalf of Hiroyuki Miyauchi (AdWords Scripts Team)

That worked Hiroyuki – one last qu, I’m trying to get the adgroup name by doing this:

Logger.log("Added keyword to Adgroup " + adGroup.getName() + " and now removing " + keyword.getText());

It’s returning this:

05/11/2018 15:57:15

Added keyword to Adgroup null and now removing [free number]


Any idea what I’m doing wrong?

 

From: Hiroyuki Miyauchi (AdWords Scripts Team) via AdWords Scripts Forum <adwords-scripts+APn2wQfnD0zes0cm...@googlegroups.com>
Sent: 05 November 2018 09:58
To: AdWords Scripts Forum <adwords...@googlegroups.com>
Subject: Re: Create SKAGs

 

Hello Del,

delstone...@gmail.com

unread,
Nov 5, 2018, 1:27:32 PM11/5/18
to AdWords Scripts Forum on behalf of Hiroyuki Miyauchi (AdWords Scripts Team)

Hi Hiroyuki

 

After checking the groups produced by the code below I’m finding it’s not working correctly – the groups are named:

 

AdGroup ID: 61378052133 Created at 2018-11-05T07:59:42.732-08:00

 

 

 

From: Hiroyuki Miyauchi (AdWords Scripts Team) via AdWords Scripts Forum <adwords-scripts+APn2wQfnD0zes0cm...@googlegroups.com>

Sent: 05 November 2018 09:58

To: AdWords Scripts Forum <adwords...@googlegroups.com>
Subject: Re: Create SKAGs

 

Hello Del,

Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
Nov 5, 2018, 11:21:52 PM11/5/18
to AdWords Scripts Forum
Hello Del,

Could you please provide your CID and script name as well as more details of your requirements via Reply privately to author so I can further investigate? 

Regards,
Hiroyuki
AdWords Scripts Team

Del Stone

unread,
Nov 11, 2018, 8:02:36 PM11/11/18
to AdWords Scripts Forum
Following the recent suggestion I'm now getting this error

12/11/2018 01:01:2412-11-2018 01:01:24 – Keywords Found: 0
12/11/2018 01:01:2512-11-2018 01:01:25 – Keywords Found: 0

Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
Nov 12, 2018, 12:37:01 AM11/12/18
to AdWords Scripts Forum
Hello Del,

It seems the reason why you cannot fetch any keywords is because of the getAdWordsFormattedDate function below in the script. The function always returns the current date, since the parameter d is not used in the function.

function getAdWordsFormattedDate(d, format){
 
var date = new Date();
 
  date
.setDate(date.getDate());
 
 
return Utilities.formatDate(date,AdWordsApp.currentAccount().getTimeZone(),format);
}

With this, you may update the code above with the below code to return the formatted calculated date depends on the parameter d.

function getAdWordsFormattedDate(d, format){

 
var MILLIS_PER_DAY = 1000 * 60 * 60 * 24;
 
var now = new Date();
 
var date = new Date(now.getTime() - d * MILLIS_PER_DAY);
 
var timeZone = AdWordsApp.currentAccount().getTimeZone();  
 
 
return Utilities.formatDate(date, timeZone, format);
}

Please let me know how it goes after trying the suggestion.

Regards,
Hiroyuki
AdWords Scripts Team

delstone...@gmail.com

unread,
Nov 12, 2018, 6:41:47 AM11/12/18
to AdWords Scripts Forum on behalf of Hiroyuki Miyauchi (AdWords Scripts Team)

That’s solved that problem – thanks Hiroyuki.

 

It leaves one problem behind – the ads are not being copied across. Any thoughts why that is happening?

 

From: Hiroyuki Miyauchi (AdWords Scripts Team) via AdWords Scripts Forum <adwords-scripts+APn2wQfnD0zes0cm...@googlegroups.com>
Sent: 12 November 2018 05:37
To: AdWords Scripts Forum <adwords...@googlegroups.com>
Subject: Re: Create SKAGs

 

Hello Del,

--

-- 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 the Google Groups "AdWords Scripts Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adwords-scrip...@googlegroups.com.

Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
Nov 12, 2018, 11:09:38 PM11/12/18
to AdWords Scripts Forum
Hello Del,

The reason why the script does not copy any ads is because the script tries to fetch ads from the newly created adGroups which don't have any ads (line 80). Since you are using the same variable name adGroup at line 57 and 67, if you want to fetch ads from the adGroup which the keyword belong to, you would need to change the variable name adGroup at line 67. Also, some of the methods to fetch ads information are incorrect. You may refer to the updated code below. However, feel free to modify based on your preferences.

if (adGroupOperation.isSuccessful()) {
 
   
var newAdGroup = adGroupOperation.getResult();

   
var keywordBuilder = adGroup.newKeywordBuilder();
   
var keywordOperation = keywordBuilder
       
.withText('[' + keyword.getText() + ']')
       
.withCpc(0.30)
       
.build();


   
// Remove the Keyword from original campaign
   
if (keywordOperation.isSuccessful()) {
     
       
Logger.log("Added keyword to Adgroup " + adGroup.getName() + " and now removing " + keyword.getText());

        keyword
.remove();

       
// Copy ads across to new adgroup

       
var adsIterator = adGroup.ads().withCondition('Type=EXPANDED_TEXT_AD').get();


       
while (adsIterator.hasNext()) {
           
var ad = adsIterator.next();


           
var adOperation = newAdGroup.newAd().expandedTextAdBuilder()
               
.withHeadlinePart1(ad.getHeadlinePart1())
               
.withHeadlinePart2(ad.getHeadlinePart2())
               
.withDescription(ad.getDescription())
               
.withPath1(ad.getPath1())
               
.withPath2(ad.getPath2())
               
.withFinalUrl(ad.urls().getFinalUrl())
               
.build();

           
var ad = adOperation.getResult();

       
}
   
}

}

I would suggest that you test this script using the Preview button first to see possible changes.

Please let me know how it goes after trying the suggestion.

Regards,
Hiroyuki
AdWords Scripts Team

delstone...@gmail.com

unread,
Nov 14, 2018, 7:30:23 AM11/14/18
to AdWords Scripts Forum on behalf of Hiroyuki Miyauchi (AdWords Scripts Team)

That fixed it – thanks!

 

One remaining error – on the following lines

                  var ad = adOperation.getResult();

                  if (ad.isSuccessful()) {

                    Logger.log("Added ad to Adgroup " + ad.getHeadlinePart1() + " and url " + ad.urls().getFinalUrl());

                  }

 

I get the error – I can’t see what I’m doing wrong:

14/11/2018 12:28:54TypeError: Cannot find function isSuccessful in object [EXPANDED_TEXT_AD]. (file Code.gs, line 97)


I also am trying to access the description line 2 that is now available for expanded text ads – how do I do that?



From: Hiroyuki Miyauchi (AdWords Scripts Team) via AdWords Scripts Forum <adwords-scripts+APn2wQfnD0zes0cm...@googlegroups.com>
Sent: 13 November 2018 04:10
To: AdWords Scripts Forum <adwords...@googlegroups.com>
Subject: Re: Create SKAGs

 

Hello Del,

 

The reason why the script does not copy any ads is because the script tries to fetch ads from the newly created adGroups which don't have any ads (line 80). Since you are using the same variable name adGroup at line 57 and 67, if you want to fetch ads from the adGroup which the keyword belong to, you would need to change the variable name adGroup at line 67. Also, some of the methods to fetch ads information are incorrect. You may refer to the updated code below. However, feel free to modify based on your preferences.

delstone...@gmail.com

unread,
Nov 14, 2018, 1:58:53 PM11/14/18
to AdWords Scripts Forum on behalf of Hiroyuki Miyauchi (AdWords Scripts Team)

Hi Hiroyuki,

 

This part doesn’t seem to create the keyword – the adgroup is created ok, as are the ads, just the keyword isn’t created – any thoughts why?

 

          var newAdGroup = adGroupOperation.getResult();

          var keywordBuilder = adGroup.newKeywordBuilder();

          var keywordOperation = keywordBuilder

              .withText(keyword.getText())

              .withCpc(0.30)

              .build();

 

 

 

From: Hiroyuki Miyauchi (AdWords Scripts Team) via AdWords Scripts Forum <adwords-scripts+APn2wQfnD0zes0cm...@googlegroups.com>

Sent: 13 November 2018 04:10

To: AdWords Scripts Forum <adwords...@googlegroups.com>
Subject: Re: Create SKAGs

 

Hello Del,

 

The reason why the script does not copy any ads is because the script tries to fetch ads from the newly created adGroups which don't have any ads (line 80). Since you are using the same variable name adGroup at line 57 and 67, if you want to fetch ads from the adGroup which the keyword belong to, you would need to change the variable name adGroup at line 67. Also, some of the methods to fetch ads information are incorrect. You may refer to the updated code below. However, feel free to modify based on your preferences.

Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
Nov 15, 2018, 1:29:48 AM11/15/18
to AdWords Scripts Forum
Hello Del,

Please refer below for each question.

I get the error – I can’t see what I’m doing wrong:
14/11/2018 12:28:54TypeError: Cannot find function isSuccessful in object [EXPANDED_TEXT_AD]. (file Code.gs, line 97)
You are encountering the error because the getResult() method returns an Ad entity and it does not have isSuccessful() function. If you want to check if the result of the operation you would need to update your code like below. 
if (adOperation.isSuccessful()) {
   
var ad = adOperation.getResult();
   
Logger.log("Added Adgroup: " + "SKAG | " + keyword.getText().replace("[", "").replace("]", "") + " | EXACT" + " Headline: " + ad.getHeadlinePart1() + " and url " + newURL);
}

 
I also am trying to access the description line 2 that is now available for expanded text ads – how do I do that?

You may utilize getDescription2() method to get the second description of the expanded text ad.


This part doesn’t seem to create the keyword – the adgroup is created ok, as are the ads, just the keyword isn’t created – any thoughts why?
 
It seems the part that you provided has been already updated. Could you confirm if you resolved the issue?


Please let me know how it goes after trying the suggestion.

Regards,
Hiroyuki
AdWords Scripts Team

Reply all
Reply to author
Forward
0 new messages