Script to manage BMM/Phrase/Exact Campaign splits

251 views
Skip to first unread message

Del Stone

unread,
May 7, 2018, 6:04:33 PM5/7/18
to AdWords Scripts Forum
Hi

BMM/Phrase/Exact Campaign splits seems to be a common way of splitting campaigns.

However I cannot find any scripts that allow exact kws appearing on BMM/Phrase campaign adgroups to be automatically moved across to the corresponding adgroup on Exact campaign. Likewise exact keywords should be added to BMM/Phrase and Phrase keywords should be added as negatives to BMM.

Does such a script exist?

If not, can you help with an example script that I can try tailoring? My experience with Adwords API is that of a newbie albeit one with JS coding skills.


Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
May 8, 2018, 4:33:29 AM5/8/18
to AdWords Scripts Forum
Hello Del,

Could you confirm if you are using AdWords API or AdWords Scripts? If it is AdWords Scripts, you may refer to the sample code in this previous Forum thread which seems to have discussed a similar concern as yours, and could you confirm if it meets your requirement?
Feel free to get back to me if you have further clarifications.

Regards,
Hiroyuki
AdWords Scripts Team

delstone

unread,
May 8, 2018, 10:04:48 AM5/8/18
to AdWords Scripts Forum on behalf of Hiroyuki Miyauchi (AdWords Scripts Team)

Hi Hiroyuki,

 

I’m using AW Scripts. I have seen this script along with a couple of others.

The problem with this script and its sister script on https://remkovanderzwaag.nl/blog/updated-adwords-script-auto-add-negative-keywords-dsa is that they add all keywords to lists of -ve kws which are then applied to all campaigns.

Whilst the idea is sound in principle it does not scale. We have over 300k keywords – in lists of 5k that is over 60 lists – google’s limit is 20 lists.

We need a more scalable way of doing this.

--
-- 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/492f2abd-a92a-4de1-a6c8-b01f096bb9f3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
May 9, 2018, 12:03:02 AM5/9/18
to AdWords Scripts Forum
Hello Del,

As you mentioned, AdWords has limits and you need to build your entities within the limits.
Aside from the limits, if you need another specific script aside from those scripts discussed in the forum thread, that will be suitable for your requirements, then could you provide more details with a step-by-step instruction about your use-case so I can further check?

delstone

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

Hi Hiroyuk,

 

We are using lots of campaigns, set up as clusters of 3 campaigns for given organisations: BMM/Phrase/Exact – a relatively common way of ensuring keyword splits.

1 We need a script that runs daily and loops through all campaigns.

2 Exact kws appearing on BMM/Phrase campaign adgroups should be automatically moved across to the corresponding adgroup on the associated Exact campaign.

3 Phrase kws appearing on BMM campaign adgroups should be automatically moved across to the corresponding adgroup on the associated Phrase campaign.

4 All of the exact keywords from the Exact campaign should be added to BMM/Phrase as exact campaign negatives.

5 All of the phrase keywords from the phrase campaign should be added as phrase campaign negatives to the BMM campaign.

 

Each campaign name ends with BROAD, PHRASE, EXACT to indicate the kw types.

Thanks in advance.


 

From: Hiroyuki Miyauchi (AdWords Scripts Team) via AdWords Scripts Forum <adwords-scripts+APn2wQfnD0zes0cm...@googlegroups.com>
Sent: 09 May 2018 05:03
To: AdWords Scripts Forum <adwords...@googlegroups.com>
Subject: Re: Script to manage BMM/Phrase/Exact Campaign splits

 

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,
May 10, 2018, 1:58:54 AM5/10/18
to AdWords Scripts Forum
Hello Del,

Thank you for providing the requirement, since there is no available solution scripts that will perform this requirement, you would have to create and implement it on your end and if you encounter any issues, feel free to let us know.

To help you get started, you may implement the script which meets your requirement using KeywordSelector. Since you want to fetch and loop all campaigns which have specific word "BROAD, PHRASE, EXACT" in their names and fetch specific KeywordMatchType. Below is the sample code snippet to fetch Exact match keywords from campaigns which contain "BROAD" in the name.

// Fetch Exact match Keywords from Broad Campaigns
var exactKWs = AdWordsApp.keywords().withCondition("CampaignName CONTAINS 'BROAD' AND KeywordMatchType = EXACT").get();  

After fetching the keywords, you may loop them and add to other campaigns with KeywordBuilder or remove them from their current campaign association.
Also, I would suggest that you split the scripts into multiple scripts to avoid timeouts, since you have multiple campaigns/entities. You may also schedule the script based on your preference by clicking the +Create Schedule button (in old AdWords UI) beside the script.

delstone

unread,
May 11, 2018, 11:31:54 AM5/11/18
to AdWords Scripts Forum on behalf of Hiroyuki Miyauchi (AdWords Scripts Team)

Hi Hiroyuki,

 

I’m struggling to put this script together – could you help sketch out the main structure. I can hopefully pull it together from there…

 

 

From: Hiroyuki Miyauchi (AdWords Scripts Team) via AdWords Scripts Forum <adwords-scripts+APn2wQfnD0zes0cm...@googlegroups.com>
Sent: 10 May 2018 06:59
To: AdWords Scripts Forum <adwords...@googlegroups.com>
Subject: Re: Script to manage BMM/Phrase/Exact Campaign splits

 

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,
May 13, 2018, 11:46:47 PM5/13/18
to AdWords Scripts Forum
Hello Del,

The sample code below is for adding Exact keywords from a Broad campaign to an Exact campaign's adGroup, and removing the keywords from the Broad campaign. Since there is no "OR" operator, it fetches the keywords only from Broad campaigns. You may also use this as reference to implement for Phrase campaign and other requirements you described, but feel free to modify this based on your preference.

function main() {
 
 
// Fetch Exact Keywords from Broad Campaigns

 
var exactKWs = AdWordsApp.keywords().withCondition("CampaignName CONTAINS 'BROAD' AND KeywordMatchType = EXACT").get();
 
 
 
// Fetch AdGroup to add the keyword (Exact Campaign)
 
var adGroupIterator = AdWordsApp.adGroups().withCondition("CampaignName CONTAINS 'EXACT' AND Name = 'INSERT_ADGROUP_NAME_HERE'").get();


 
if (exactKWs.hasNext() && adGroupIterator.hasNext()) {
   
var adGroup = adGroupIterator.next();  
 
   
// Loop the Keywords
   
while (exactKWs.hasNext()){
     
var exactKW = exactKWs.next();    
     
     
// Add the Keyword to adgroup on the associated Exact campaign
     
var keywordOperation = adGroup.newKeywordBuilder().withText(exactKW.getText()).build();
     
     
// Remove the Keyword from Broad campaign
     
if(keywordOperation.isSuccessful()){
      exactKW
.remove();
     
}
   
}
   
 
}
 
}

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

Regarding adding a keyword to an existing ad group, you may also refer to this sample.
Please let me know if you have any clarifications.
Message has been deleted

Del Stone

unread,
May 14, 2018, 8:24:46 PM5/14/18
to AdWords Scripts Forum
Thanks for that. I've got the script close to completion - just a couple of few issues remain:

- how to resolve the error 
Considering ABC 9am-8pm,9am-4pm,9am-5pm- Exact Match,
Processing ABC 9am-8pm,9am-4pm,9am-5pm- Exact Match,
TypeError: Cannot find function charAt in object [keyword [support number]]. (line 115)

- is the code sensible/efficient or are there any parts that should be refactored




/****************************
 * Move all active exact match keywords in broad / phrase campaign adgroups to their corresponding exact campaign adgroups
 * Add all exact match keywords to their corresponding broad / phrase campaign negative adgroups
 ****************************/

function main() {

    var bmmIdentifier    = 'Broad';
    var phraseIdentifier = 'Phrase';
    var exactIdentifier  = 'Exact';
    var exactKeywords1, exactKeywords2, phraseKeywords;

  
  // Get all enabled campaigns
    var campaignIterator = AdWordsApp.campaigns()
        .withCondition('Status = ENABLED')
        .get();

  
// Loop through all campaigns
  while (campaignIterator.hasNext()) {
        var campaign = campaignIterator.next();
        var exactCampaignName = campaign.getName();
      
Logger.log('Considering ' + exactCampaignName + ', ');

        // if campaign name contains 'Exact' 
        if (exactCampaignName.indexOf(exactIdentifier) != -1) {
Logger.log('Processing ' + exactCampaignName + ', ');

            var bmmCampaignName     = exactCampaignName.replace(exactIdentifier, bmmIdentifier);
            var phraseCampaignName  = exactCampaignName.replace(exactIdentifier, phraseIdentifier);
            var bmmCampaignIterator = AdWordsApp.campaigns().withCondition('CampaignName = "' + bmmCampaignName + '"').get();
          var phraseCampaignIterator = AdWordsApp.campaigns().withCondition('CampaignName = "' + phraseCampaignName + '"').get();

          if  (bmmCampaignIterator.hasNext()) var bmmCampaign = bmmCampaignIterator.next();
          if  (phraseCampaignIterator.hasNext()) var phraseCampaign = phraseCampaignIterator.next();
          
// Get exact keywords from bmm and phrase campaigns
          var exactKeywords1 = getKeywords(bmmCampaignName, exactIdentifier);
          var exactKeywords2 = getKeywords(phraseCampaignName, exactIdentifier);

            // Add all exact match keywords to their corresponding broad / phrase campaign negative adgroups
            addNegativeKWsToCampaign(bmmCampaign, exactKeywords1);
            addNegativeKWsToCampaign(bmmCampaign, exactKeywords2);
            addNegativeKWsToCampaign(phraseCampaign, exactKeywords1);
            addNegativeKWsToCampaign(phraseCampaign, exactKeywords2);
Logger.log("Added -ve exact kws to campaign!");
          
            // Move all active exact match keywords in broad / phrase campaign adgroups to their corresponding exact campaign adgroups
            // Remove keywords from original campaign too
            addKeywordsToCampaign(exactCampaignName, exactKeywords1);
            addKeywordsToCampaign(exactCampaignName, exactKeywords2);
            Logger.log("Total Exact match kws: " + exactKeywords1 + exactKeywords2);
          
            // Add phrase keywords to their corresponding broad campaign negative adgroups
            var phraseKeywords = getKeywords(phraseCampaignName, phraseIdentifier);
            addNegativeKWsToCampaign(bmmCampaign, phraseKeywords);
            Logger.log("Added -ve phrase kws to campaign: " + phraseKeywords);

        } 
    }
  
}

function getKeywords(campaignName, keywordMatchType) {

  var keywords = AdWordsApp.keywords()
        .withCondition('CampaignName = "' + campaignName + '" AND KeywordMatchType = ' + keywordMatchType.toUpperCase())
        .get();
 
  return keywords;

}

function addKeywordsToCampaign(campaignName, keywords) {

  while (keywords.hasNext()) {
    
    var keyword = keywords.next();
    
var adGroupName = keyword.getAdGroup().getName();

    var adGroupIterator = AdWordsApp.adGroups().withCondition('CampaignName = "' + campaignName + '" AND Name = "' + adGroupName + '"').get();
    //var adGroup = campaign.adGroups().withCondition('Name = "' + adGroupName + '"').get();
    
    if (adGroupIterator.hasNext()) {
    var adGroup = adGroupIterator.next();  
      
    var keywordOperation = adGroup.newKeywordBuilder()
          .withText(keyword.getText())
          .withCpc(0.5)
          .build();
    }
    
    // Remove the Keyword from Broad campaign
if(keywordOperation.isSuccessful()){
      Logger.log("Added keyword to Adgroup name: " + adGroupName + " and now removing " + keyword.getText());
      keyword.remove();
}

  }

}

function addNegativeKWsToCampaign(campaign, keywords) {

//create the negative exact match keyword on a campaign level
while (keywords.hasNext()) {
    
    var keyword = keywords.next();

campaign.createNegativeKeyword(keyword);

      Logger.log("Added -ve kw to campaign" + keyword);

      // maybe should be at adgroup level due to -ve kw limits at campaign level?
      //adGroup.createNegativeKeyword('"INSERT_KEYWORD_HERE"');//phrase match
        //adGroup.createNegativeKeyword('INSERT_KEYWORD_HERE');//broad match
        //adGroup.createNegativeKeyword('[INSERT_KEYWORD_HERE]');//exact match
}

}



Hiroyuki Miyauchi (AdWords Scripts Team)

unread,
May 15, 2018, 4:04:04 AM5/15/18
to AdWords Scripts Forum
Hello Del,

The reason why you are encountering the issue is because of the line below:

campaign.createNegativeKeyword(keyword);

Since createNegativeKeyword(keywordText) should be used with a string parameter. However, In your script, the variable named "keyword" is a Keyword object. To resolve this issue, please modify the code above to the sample code below.

campaign.createNegativeKeyword(keyword.getText());

Please let me know how it goes after trying the suggestion.
Message has been deleted
Message has been deleted

Del Stone

unread,
May 15, 2018, 3:07:48 PM5/15/18
to AdWords Scripts Forum
I'm facing a  remaining issue:

The keywords iterator loops through keywords using next() - however the next function that tries looping through them finds the end of the list and ends.

Is there an easy way of restarting from the top?

At the moment I'm setting multiple variables all set to grab the same list and different functions are using each variable - a clumsy solution...

I had assumed passing it by value to functions would unaffect the variable - it seems however to be passed by reference.

Thanks in advance.

Del Stone

unread,
May 15, 2018, 8:00:19 PM5/15/18
to AdWords Scripts Forum
I'm also finding the following code line isn't returning the no of elements correctly (returning 1 when several elements exist) - any thoughts?

// Get exact keywords from bmm and phrase campaigns
          var exactKeywords1 = getKeywords(bmmCampaignName, exactIdentifier);
          var exactKeywords2 = getKeywords(phraseCampaignName, exactIdentifier);
          
exactKeywordNo = (exactKeywords1.totalNumEntities() > 0) ? exactKeywords1.totalNumEntities() : exactKeywords2.totalNumEntities();
Logger.log("No of exact keywords: " + exactKeywordNo);
          


Del Stone

unread,
May 15, 2018, 10:02:43 PM5/15/18
to AdWords Scripts Forum
Finally when running the script, the script history shows lots of lines containing the phrase
Change "Add audience" Successful

What does this mean? I don't recall adding audiences...


Hiroyuki Miyauchi (AdWords Scripts Team)

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

I have checked the script in the CID you provided privately, and upon checking at the moment, the lines which creates multiple variables for the same list are correct. Since there is no way to restart iteration from the top in AdWords Scripts, also, the parameters for non-primitive types (e.g. exactKeywords1 in your script) are passed by reference (changing the actual value of the parameter).

Also, I have checked the "no of elements"  issue with the script you provided, but I did not see any issues. Could you provide me more details about the issue you are encountering?

About the log "Add audience" Successful", I did not see the message in your latest Script history. I have also checked your script, but I did not see any adding audience or user list in your script. Have you already resolved this issue?

Please let me know if you have further clarifications.
Reply all
Reply to author
Forward
0 new messages