Script for changing bids depending on Keywords and Campaign labels

121 views
Skip to first unread message

Никита Евсей

unread,
Jun 12, 2014, 10:30:42 AM6/12/14
to adwords...@googlegroups.com
Hello, to everybody.
I made a script to adjust bids depending on campaign and keyword labels. I use it to control average position of keywords when it's necessary.

You can use it. Suggestions are appreciated especially as long as I'm new to coding.

Sincerely, Nikita



/*************************************************************** 
Bidding on Campaign and Keyword Labels 
Version 1.2.4
ChangeLog v1.2.4
-Fixed bug with MIN_BID
-Added function for logging main actions
-Logs made in comments to speed up the script
ChangeLog v1.2.3 
- Added RUSH_BID coefficients.
- Added lowering bids that are too big for the 1 spot.
ChangeLog v1.2.2 - Added strategies for all 1.0 - 3.2 spots.
ChangeLog v1.2.1 - Non existed keyword label fixed.
ChangeLog v1.2 - Keyword labels added.
ChangeLog v1.1.1 - Made loops for strategy interation.
ChangeLog v1.1 - Added non existed labels creation.
Nikita Yevsey
Eting Mark Agency
*****************************************************************/

var RUSH_BID = 1; //Use this to increase script effect both ways: increasing and decreasing bids. The more number - the more aggressively script bids.
var RUSH_BID_INCREASING = 1; // Increase bids more aggressively then decrease. The more number - the more aggressively script rises bids. 
var RUSH_BID_DECREASING = 1; // Decrease bids more aggressively then decrease. The more number - the more aggressively script lowers bids.

var DATE_RANGE = "LAST_7_DAYS"; // Date range. TODAY, YESTERDAY, LAST_7_DAYS, THIS_WEEK_SUN_TODAY, LAST_WEEK, LAST_14_DAYS, LAST_30_DAYS, LAST_BUSINESS_WEEK, LAST_WEEK_SUN_SAT, THIS_MONTH, LAST_MONTH, ALL_TIME

var MAX_BID = 2; // The maximum bid script should reach.
var MIN_BID = 0.02; // The minimum bid script should reach. If 0 - then it sets AdGroup default bid for keywords that are 0 bid.

var BID_FROM_1_SPOT = 1.04; // How much to lower bid if got to the first spot and the target is the 1 spot too. This lowers bids if they are not necessarily big for the 1 spot.

var EXTRA_LOGS = false; // Sets if to show info messages. Set true to show logs. Needed more while bugtesting

var BID_CHANGE_COEFFICIENT_5 = 1.05; // How much to adjust the bids.
var BID_CHANGE_COEFFICIENT_10 = 1.1;
var BID_CHANGE_COEFFICIENT_15 = 1.15;
var BID_CHANGE_COEFFICIENT_30 = 1.3;
var BID_CHANGE_COEFFICIENT_50 = 1.5;

var SPOT_1_0_LABEL = '1 spot'; // Setting names for labels
var SPOT_1_1_LABEL = '1.1 spot';
var SPOT_1_2_LABEL = '1.2 spot';
var SPOT_1_3_LABEL = '1.3 spot';
var SPOT_1_4_LABEL = '1.4 spot';
var SPOT_1_5_LABEL = '1.5 spot';
var SPOT_1_6_LABEL = '1.6 spot';
var SPOT_1_7_LABEL = '1.7 spot';
var SPOT_1_8_LABEL = '1.8 spot';
var SPOT_1_9_LABEL = '1.9 spot';
var SPOT_2_0_LABEL = '2 spot';
var SPOT_2_1_LABEL = '2.1 spot';
var SPOT_2_2_LABEL = '2.2 spot';
var SPOT_2_3_LABEL = '2.3 spot';
var SPOT_2_4_LABEL = '2.4 spot';
var SPOT_2_5_LABEL = '2.5 spot';
var SPOT_2_6_LABEL = '2.6 spot';
var SPOT_2_7_LABEL = '2.7 spot';
var SPOT_2_8_LABEL = '2.8 spot';
var SPOT_2_9_LABEL = '2.9 spot';
var SPOT_3_0_LABEL = '3 spot';
var SPOT_3_1_LABEL = '3.1 spot';
var SPOT_3_2_LABEL = '3.2 spot';

var SPOT_LABELS_STRING = "['1 spot','1.1 spot','1.2 spot','1.3 spot','1.4 spot','1.5 spot','1.6 spot','1.7 spot','1.8 spot','1.9 spot','2 spot','2.1 spot','2.2 spot','2.3 spot','2.4 spot','2.5 spot','2.6 spot','2.7 spot','2.8 spot','2.9 spot','3 spot','3.1 spot','3.2 spot']"
 
var spotsArray = [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3, 3.1, 3.2]; // Array for spot strategies
function main() {
  info('Started to check and create labels');
  createLabelIfNeeded(SPOT_1_0_LABEL,"#00ff30"); //Calling function to create labels if needed. Setting the colours of the labels here
  createLabelIfNeeded(SPOT_1_1_LABEL,"#0bf237");
  createLabelIfNeeded(SPOT_1_2_LABEL,"#16e53d");
  createLabelIfNeeded(SPOT_1_3_LABEL,"#1fda42");
  createLabelIfNeeded(SPOT_1_4_LABEL,"#26cc46");
  createLabelIfNeeded(SPOT_1_5_LABEL,"#2ebf49");
  createLabelIfNeeded(SPOT_1_6_LABEL,"#35ac4c");
  createLabelIfNeeded(SPOT_1_7_LABEL,"#3a954b");
  createLabelIfNeeded(SPOT_1_8_LABEL,"#3b7b47");
  createLabelIfNeeded(SPOT_1_9_LABEL,"#335d3b");  
  createLabelIfNeeded(SPOT_2_0_LABEL,"#0096ff");
  createLabelIfNeeded(SPOT_2_1_LABEL,"#148fe5");
  createLabelIfNeeded(SPOT_2_2_LABEL,"#2087d0");
  createLabelIfNeeded(SPOT_2_3_LABEL,"#257ebc");
  createLabelIfNeeded(SPOT_2_4_LABEL,"#2771a5");
  createLabelIfNeeded(SPOT_2_5_LABEL,"#286590");
  createLabelIfNeeded(SPOT_2_6_LABEL,"#26587b");
  createLabelIfNeeded(SPOT_2_7_LABEL,"#254d69");
  createLabelIfNeeded(SPOT_2_8_LABEL,"#234258");
  createLabelIfNeeded(SPOT_2_9_LABEL,"#213442");   
  createLabelIfNeeded(SPOT_3_0_LABEL,"#a102fd"); 
  createLabelIfNeeded(SPOT_3_1_LABEL,"#7a23ac");  
  createLabelIfNeeded(SPOT_3_2_LABEL,"#582177");
  info('Finished to check and create labels');
  
var i = 0; 
while (i < 23) { // Loop for all strategies that we have
info('Started getting labled campaigns for '+spotsArray[i]+' strategy');
var campaignsToBid = AdWordsApp.campaigns() //Getting campaigns that match strategy
.withCondition("LabelNames CONTAINS_ALL ['"+spotsArray[i]+" spot']")
.withCondition("Status = ENABLED")
.get();
info('Finished getting labled campaigns for '+spotsArray[i]+' strategy');
while (campaignsToBid.hasNext()) { // Loop to get keywords for current campaign for current strategy
var spotToGet = spotsArray[i]; //setting target position from strategy array
var campaign = campaignsToBid.next();
info('Started getting non labled keywords for '+campaign+' campaign');
var keywordsToChangeBid = campaign.keywords() //Getting keywords without bid labels
.withCondition("Status = ENABLED")
.withCondition("Impressions > 0")
.withCondition("LabelNames CONTAINS_NONE "+SPOT_LABELS_STRING)
.orderBy("AveragePosition ASC")
.forDateRange(DATE_RANGE)
.get();
info('Finished getting non labled keywords for '+campaign+' campaign');
info('Started changing bids for non labled keywords for '+campaign+' campaign');
ChangeBids(spotToGet); //Calling function to change bids
info('Finished changing bids for non labled keywords for '+campaign+' campaign');
}
i++;
}
  
var i = 0; 
while (i < 23) { // Loop for all strategies that we have
info('Started getting all campaigns for '+spotsArray[i]+' strategy');
var campaignsToBid = AdWordsApp.campaigns() //Getting all campaigns
.withCondition("Status = ENABLED")
.get();
info('Finished getting all campaigns for '+spotsArray[i]+' strategy');
while (campaignsToBid.hasNext()) { // Loop to get keywords for current campaign for current strategy
var spotToGet = spotsArray[i]; //setting target position for current strategy from strategy array
var campaign = campaignsToBid.next();
info('Started getting labled keywords for '+campaign+' campaign');
var keywordsToChangeBid = campaign.keywords() //Getting keywords with labels
.withCondition("Status = ENABLED")
.withCondition("Impressions > 0")
.withCondition("LabelNames CONTAINS_ALL ['"+spotsArray[i]+" spot']")
.orderBy("AveragePosition ASC")
.forDateRange(DATE_RANGE)
.get();
info('Finished getting labled keywords for '+campaign+' campaign');
info('Started changing bids for labled keywords for '+campaign+' campaign');
ChangeBids(spotToGet); //Calling function to change bids
info('Finished changing bids for labled keywords for '+campaign+' campaign');
}
i++;
}  
 
// Let's do the job. Setting bids depending on current average position. The more difference between current and target position - the more bid adjustment 
function ChangeBids(targetPosition){
while (keywordsToChangeBid.hasNext()) {
var keyword = keywordsToChangeBid.next();

if (keyword.getStatsFor(DATE_RANGE).getAveragePosition() > targetPosition + 3 && (keyword.getMaxCpc() * BID_CHANGE_COEFFICIENT_50 * RUSH_BID * RUSH_BID_INCREASING) + 0.01 < MAX_BID){ 
keyword.setMaxCpc((keyword.getMaxCpc() * BID_CHANGE_COEFFICIENT_50 * RUSH_BID * RUSH_BID_INCREASING) + 0.01);
}
else if (keyword.getStatsFor(DATE_RANGE).getAveragePosition() > targetPosition + 1.5 && keyword.getStatsFor(DATE_RANGE).getAveragePosition() < targetPosition + 3.1 && (keyword.getMaxCpc() * BID_CHANGE_COEFFICIENT_30 * RUSH_BID * RUSH_BID_INCREASING) + 0.01 < MAX_BID){
keyword.setMaxCpc((keyword.getMaxCpc() * BID_CHANGE_COEFFICIENT_30 * RUSH_BID * RUSH_BID_INCREASING) + 0.01);
}
else if (keyword.getStatsFor(DATE_RANGE).getAveragePosition() > targetPosition + 0.5 && keyword.getStatsFor(DATE_RANGE).getAveragePosition() < targetPosition + 1.6 && (keyword.getMaxCpc() * BID_CHANGE_COEFFICIENT_15 * RUSH_BID * RUSH_BID_INCREASING) + 0.01 < MAX_BID){ 
keyword.setMaxCpc((keyword.getMaxCpc() * BID_CHANGE_COEFFICIENT_15 * RUSH_BID * RUSH_BID_INCREASING) + 0.01);
}
else if (keyword.getStatsFor(DATE_RANGE).getAveragePosition() > targetPosition + 0.3 && keyword.getStatsFor(DATE_RANGE).getAveragePosition() < targetPosition + 0.6 && (keyword.getMaxCpc() * BID_CHANGE_COEFFICIENT_10 * RUSH_BID * RUSH_BID_INCREASING) + 0.01 < MAX_BID){
keyword.setMaxCpc((keyword.getMaxCpc() * BID_CHANGE_COEFFICIENT_10 * RUSH_BID * RUSH_BID_INCREASING) + 0.01);
}
else if (keyword.getStatsFor(DATE_RANGE).getAveragePosition() > targetPosition + 0.1 && keyword.getStatsFor(DATE_RANGE).getAveragePosition() < targetPosition + 0.4 && (keyword.getMaxCpc() * BID_CHANGE_COEFFICIENT_5 * RUSH_BID * RUSH_BID_INCREASING) + 0.01 < MAX_BID){
keyword.setMaxCpc((keyword.getMaxCpc() * BID_CHANGE_COEFFICIENT_5 * RUSH_BID * RUSH_BID_INCREASING) + 0.01);
}
else if (keyword.getStatsFor(DATE_RANGE).getAveragePosition() > targetPosition - 0.2 && keyword.getStatsFor(DATE_RANGE).getAveragePosition() < targetPosition + 0.2 ){
}
else if (keyword.getStatsFor(DATE_RANGE).getAveragePosition() > targetPosition - 0.3 && keyword.getStatsFor(DATE_RANGE).getAveragePosition() < targetPosition - 0.1 && (keyword.getMaxCpc() / BID_CHANGE_COEFFICIENT_5 / RUSH_BID / RUSH_BID_DECREASING) - 0.01 > MIN_BID){
keyword.setMaxCpc((keyword.getMaxCpc() / BID_CHANGE_COEFFICIENT_5 / RUSH_BID / RUSH_BID_DECREASING) - 0.01);
}
else if (keyword.getStatsFor(DATE_RANGE).getAveragePosition() > targetPosition - 0.5 && keyword.getStatsFor(DATE_RANGE).getAveragePosition() < targetPosition - 0.2 && (keyword.getMaxCpc() / BID_CHANGE_COEFFICIENT_10 / RUSH_BID / RUSH_BID_DECREASING) - 0.01 > MIN_BID){
keyword.setMaxCpc((keyword.getMaxCpc() / BID_CHANGE_COEFFICIENT_10 / RUSH_BID / RUSH_BID_DECREASING) - 0.01);
}
else if ((keyword.getMaxCpc() / BID_CHANGE_COEFFICIENT_15 / RUSH_BID / RUSH_BID_DECREASING) - 0.01 > MIN_BID){
keyword.setMaxCpc((keyword.getMaxCpc() / BID_CHANGE_COEFFICIENT_15 / RUSH_BID / RUSH_BID_DECREASING) - 0.01);
}
else{}
if (keyword.getStatsFor(DATE_RANGE).getAveragePosition() == 1 && targetPosition == 1 && keyword.getMaxCpc() / BID_FROM_1_SPOT - 0.01 > MIN_BID){
keyword.setMaxCpc(keyword.getMaxCpc() / BID_FROM_1_SPOT - 0.01);
}
}
}

// A helper function to create a new label if it doesn't exist in the account.
function createLabelIfNeeded(name,color) { 
  if(!AdWordsApp.labels().withCondition("Name = '"+name+"'").get().hasNext()) {
    AdWordsApp.createLabel(name,"",color);
  } else { }
}

// Helper function to print info logs
function info(msg) {
  if(EXTRA_LOGS) {
    Logger.log('INFO: '+msg);
  }
}
}


Никита Евсей

unread,
Jun 12, 2014, 10:45:20 AM6/12/14
to adwords...@googlegroups.com
Do anybody have experience with such scripts?

How often it's better to run it and how agressively bid? 

From my automated rules experience - twice a week with getting LAST_7_DAYS data.

If you have any suggestions and best practices - you are more then welcome.


Sincerely, Nikita



Anash Oommen

unread,
Jun 23, 2014, 11:19:19 AM6/23/14
to adwords...@googlegroups.com
Hi,

You'd have to find out what times work for you, though once a week is a good period. It is also a good idea to ask on the AdWords product forum at https://www.en.adwords-community.com/, to get more insights about how people use AdWords as a product.

Cheers,
Anash P. Oommen,
AdWords Scripts Team.

Bjørn Are Solstad

unread,
Jan 8, 2016, 9:14:55 AM1/8/16
to AdWords Scripts Forum
I'm trying it out on a client account now. Looks promising so far. I have set it to run once per day, but will probably adjust this when it has been running for a while. 
Reply all
Reply to author
Forward
0 new messages