AdWords
2.1K members online now
2.1K members online now
Dive into advanced features like Remarketing, Flexible Bid Strategies, AdWords Editor, and AdWords Scripts
Guide Me
star_border
Reply

Adjust Monthly Script Adwords, Is it possible?

Visitor ✭ ✭ ✭
# 1
Visitor ✭ ✭ ✭

Good evening to all, I would like to know if you know about a script that I readjust the budget monthly. That is to say:

 

 

Let's say that my monthly budget is 500 euros, and for the month of May only spent 490 euros. I want the script to automatically send the rest (10 euros) to the budget of the month of June, in total would be 510 = 500 euros + 10 euros.

 

It's possible? Do you know where you could get that script?

 

@Jon_Gritton I have seen that you are a great connoisseur and expert on the subject of adwords scripts, what do you think?

2 Expert replyverified_user

Adjust Monthly Script Adwords, Is it possible?

Rising Star
# 2
Rising Star

Hi there,

 

be aware that AdWords uses daily budgets, not monthly...

 

This logic should work for such a script:

 

Choose a start date that is the beginning of a certain month, Day 1.

 

On the 2nd of each month, calculate the difference between actual spend since Day 1 and now, and your daily budget times the number of days.

 

If there is a surplus to be spent, divide that by 30 and increase the daily budget by that amount.

 

Day 2 instead of Day 1, divide by 30 instead of 31, won't make much difference, just makes things easier.

 

As to the coding, that's not something I can do... It might already exist out there...

Re: Adjust Monthly Script Adwords, Is it possible?

Top Contributor
# 3
Top Contributor

Hi @Poke R sorry for the delay in replying, for some reason I only got the notification of my mention today.


I do actually have a script that does exactly this, I use it all the time on some client Accounts and it works as @RobSkelton described, also taking into account Campaigns that have ended during the month and, of course, using the correct number of days for the specific month.  I've got a few versions around, give me a while to find the right one and I'll post it up.  If I don't reply within a day, give me another mention.

 

Quick check - do you want this to run at the Account or MCC (Manager) level?  (If you don't know what an MCC is, the answer is Account!).

 

Jon

AdWords Top Contributor Google+ Profile | Partner Profile | AdWords Audits
Marked as Best Answer.
Solution
Accepted by topic author Poke R
May

Re: Adjust Monthly Script Adwords, Is it possible?

Top Contributor
# 4
Top Contributor

Hi @Poke R this appears to be the latest version that includes all the features.  (I've put the code at the end of this message).  All the settings of importance are in the variables at the top of the code.  Note that at the time of writing, scripts are unable to control Video Campaigns, so these will simply be ignored, but it should work with all others (including Shopping).

 

TOTAL_BUDGET is the total amount you want to spend across all the Campaigns being controlled by this script.
FLEX_LABEL is an optional Label you can apply to Campaigns so that only some are affected by the script.  For example, if you wanted some Campaigns to have a fixed and unchanging daily budget, you'd apply this Label to all the others that you want to be changed.  You can use any Label name you like here, but I'd suggest "FlexibleBudget" to make things clear.
IGNORE_LABELS  The script allows you to use Labels to allocate the given TOTAL_BUDGET by percentages per Campaign.  For example, if you had two Campaigns and you wanted one to get 60% of the budget and the other to get 40% of the budget, you'd give one a Label named 60 and another a Label named 40.  If you have other Labels on your Campaigns (other than the one defined in FLEX_LABEL - the script knows to ignore that one) you'll need to list them here so the script knows which Label is the percentage indicator.  For example, if your 60% Campaign had Labels named Local and BroadMatch, then you'd make the IGNORE_LABELS variable:

var IGNORE_LABELS = "Local, BroadMatch";

USE_PERC This is a flag to tell the script to read and use your percentage Labels.  Set it to 0 to ignore them (whether or not they actually exist) or 1 to use them.
MIN_BUDGET is the absolute minimum you want any Campaign to have as its daily budget. It's a good idea to set this so every Campaign gets something to spend each day!
DAYSPERC The script also allows you to distribute the spend by days of the week using percentages.  For example, if you want to spend more on a Monday than a Tuesday, you can change the Monday percentage to 120 and Tuesday to 80.  The figures in the array must add up to 700 but the script won't run if they don't. The week for this array starts on Sunday, so if you wanted to do what I've said above, this variable should look like this:

var DAYSPERC = [100,120,80,100,100,100,100];

I think that's everything.  Any problems, give me a shout.  As always, please make sure you PREVIEW this script to check what it does before scheduling it to run.  I'd suggest scheduling it for midnight each day when it'll run sometime between 00:00 and 01:00.

 

full script below:

 

// Advanced Budget Control Script (c) Jon Gritton 2017

var TOTAL_BUDGET = 1000;  // your total desired spend for an entire month
var FLEX_LABEL = "";    // Label used to identify Campaigns to be affected.  Leave blank to affect all enabled.
var IGNORE_LABELS = ""; // Any Labels other than percentages (if USE_PERC is 1) that are applied to Campaigns (separate by commas,
                          // e.g. "ThisLabel,ThatLabel";
var USE_PERC = "1";       // Ask the script to read and use percentage Labels.  0 = no, 1 = yes  If 1, you must have Labels applied
var MIN_BUDGET = 10;      // The minimum budget for any Campaign; this should ideally be higher than your typical CPC
var DAYSPERC = [100,100,100,100,100,100,100];  // Daily percentage spend.  Adjust figures to adjust spend by day, first number is Sunday.  All figures MUST add up to 700.

var d = new Date(Utilities.formatDate(new Date(), AdWordsApp.currentAccount().getTimeZone(), "MMM dd,yyyy HH:mm:ss"));
var thisDay = d.getDay();
var thisMonth=d.getMonth();
var thisYear=d.getFullYear();
// DAYS_SO_FAR is -1 because "today" hasn't happened yet
var DAYS_SO_FAR = d.getDate() - 1;
var TOTAL_DAYS = daysInMonth(thisMonth + 1, thisYear);
var DAYS_REMAINING = TOTAL_DAYS - DAYS_SO_FAR;

var START_DATE = new Date(thisYear, thisMonth, 1);
var END_DATE = new Date(thisYear, thisMonth, TOTAL_DAYS);

function main() {
  Logger.log("Total Monthly Budget: " + TOTAL_BUDGET);
  Logger.log("Days this month: " + TOTAL_DAYS);
  Logger.log("Days remaining: " + DAYS_REMAINING);
  if(FLEX_LABEL != "") {Logger.log("Action Label: " + FLEX_LABEL);}
  if(IGNORE_LABELS != "") {Logger.log("Ignore Labels: " + IGNORE_LABELS);}
  var totalPercs = checkPercs();
  if(checkPercs() != 700) {
    Logger.log("Daily percentages don't add up to 700 (they add up to " + totalPercs + "%), please check!");
    Logger.log("Quitting...");
    return;
  }
  if(USE_PERC == 1) {
      Logger.log("Using percentage labels...");
  }
  else {
  Logger.log("Splitting budget evenly...");
  }
  Logger.log("Percentage budget allocation today: " + DAYSPERC[thisDay] + "%");
  Logger.log("*** Run begins ***");
  Logger.log("");
  setNewBudget(TOTAL_BUDGET, START_DATE, END_DATE);
}

function setNewBudget(totalBudget, start, end) {
  var costSoFar = 0;
  var campaignsToSet = [];
  var campaigns = AdWordsApp.campaigns();
  Logger.log(start + ", " + end);
  if(FLEX_LABEL != "") {
    campaigns = campaigns.withCondition("LabelNames CONTAINS_ANY ['" + FLEX_LABEL + "']");
  }  
  campaigns = campaigns.get();
  while(campaigns.hasNext()) {
    var campaign=campaigns.next();
    var thisCost = campaign.getStatsFor(dateToString(start), dateToString(end)).getCost();
    costSoFar += thisCost;
    var ended = chkEnded(campaign);
    if(campaign.isEnabled() && !ended) {
      campaignsToSet.push(campaign);
      Logger.log("CampaignToSet: " + campaign.getName());
    }
  }
  var shpCampaigns = AdWordsApp.shoppingCampaigns();
  if(FLEX_LABEL != "") {
    shpCampaigns = shpCampaigns.withCondition("LabelNames CONTAINS_ANY ['" + FLEX_LABEL + "']");
  }  
  shpCampaigns = shpCampaigns.get();
  while(shpCampaigns.hasNext()) {
    var shpCampaign=shpCampaigns.next();
    var thisCost = shpCampaign.getStatsFor(dateToString(start), dateToString(end)).getCost();
    costSoFar += thisCost;
    var shpEnded = chkEnded(shpCampaign);
    if(shpCampaign.isEnabled() && !shpEnded) {
      campaignsToSet.push(shpCampaign);
      Logger.log("CampaignToSet: " + shpCampaign.getName());
    }
  }
  var totalCalcd = 0;
  Logger.log("CostSoFar: " + costSoFar);
  totalBudget -= costSoFar;
  Logger.log("Total available for selected Campaigns for the rest of the month: " + totalBudget);
  
  var newBudgets = [];
  
  if(USE_PERC == 1) {
    //uses percentage labels
    for(var i in campaignsToSet) {
      var thisCampaign=campaignsToSet[i];
      var ignoreLabels = "'" + FLEX_LABEL + "'";
      if(IGNORE_LABELS != "") {
        var igLabs = IGNORE_LABELS.split(",");
        for(var i in igLabs) {
          ignoreLabels += ",'" + igLabs[i] + "'";
        }
      }
      cLabels=thisCampaign.labels();
      // Ensure only the "percentage" Label is selected - you may need to add others if you use them  
      if(ignoreLabels != "") {
        cLabels = cLabels.withCondition("Name NOT_IN [" + ignoreLabels + "]");
      }
      cLabels = cLabels.get(); 
      if(cLabels.totalNumEntities() > 0) {
	    var percentage = cLabels.next().getName();
        //set the new budgets
      	var newBudget = calculateBudgetByPerc(totalBudget, percentage);
        newBudgets.push([thisCampaign,newBudget]);
      }
      else {
	      Logger.log("Percentage Labels don't appear set; check Account and Script Services Settings");
      }
    }
  }
  else {
    // split budget evenly
    var totNumCampaigns = campaignsToSet.length;
    var newBudget = totalBudget / totNumCampaigns;
    newBudget = (DAYS_REMAINING <=0)? newBudget : newBudget/DAYS_REMAINING;
    for(var i in campaignsToSet) {
      newBudgets.push([campaignsToSet[i],newBudget]);
    }
  }
  
  if(newBudgets.length > 0) {
    for(var i in newBudgets) {
      var thisCampaign = newBudgets[i][0];
      var theBudget = newBudgets[i][1];
      theBudget *= (DAYSPERC[thisDay]/100);
      theBudget = (theBudget < MIN_BUDGET)? MIN_BUDGET : theBudget;
      thisCampaign.getBudget().setAmount(theBudget);
      Logger.log("Campaign Set: " + thisCampaign.getName() + " Budget: " + theBudget.toFixed(2));
    }
  }
  else {
    Logger.log("No eligible Campaigns found to set.  If you expected some, check your settings!");
  }
}

function calculateBudgetByPerc(totalBudget, percentage) {
  //set budget based upon percentage Label
  var budgetRemaining = totalBudget*(percentage / 100);
  return (DAYS_REMAINING <= 0)? budgetRemaining : budgetRemaining / DAYS_REMAINING;
}

function daysInMonth(month, year) {
  //returns number of days in a given month of a given year
  return new Date(year, month, 0).getDate();
}

function dateToString(date) {
  return date.getFullYear() + zeroPad(date.getMonth() + 1) + zeroPad(date.getDate());
}

function zeroPad(n) {
  if (n < 10) {
    return '0' + n;
  } else {
    return '' + n;
  }
}

function chkEnded(campaign) {
  var campEndDate = campaign.getEndDate();
  var thisDate = d.getDate();
  if(campEndDate == null) {return false;}
  if(campEndDate.year < thisYear) {return true;}
  if(campEndDate.year > thisYear) {return false;}
  if(campEndDate.month < (thisMonth + 1)) {return true;}
  if(campEndDate.month > (thisMonth + 1)) {return false;}
  if(campEndDate.day < thisDate) {return true;}
  if(campEndDate.day >= thisDate) {return false;}
}

function checkPercs() {
  var total = 0;
  for(i=0;i<7;i++) {
    total += DAYSPERC[i];
  }
  return total;
}

 

 

AdWords Top Contributor Google+ Profile | Partner Profile | AdWords Audits

Adjust Monthly Script Adwords, Is it possible?

Visitor ✭ ✭ ✭
# 5
Visitor ✭ ✭ ✭

Thanks for the script @Jon_Gritton, I will check it out and see if it gets everything right. Answering your question, I wanted the script run at the Account. Would it serve anyway?

Adjust Monthly Script Adwords, Is it possible?

Top Contributor
# 6
Top Contributor

Hi @Poke R the script is an Account level version so should be fine.

AdWords Top Contributor Google+ Profile | Partner Profile | AdWords Audits

Re: Adjust Monthly Script Adwords, Is it possible?

Visitor ✭ ✭ ✭
# 7
Visitor ✭ ✭ ✭

Hi @Jon_Gritton, thanks again for the script, I was checking it and I have only these doubts:

 

  1. I understand that the first number with which the "var DAYSPERC" begins is Sunday. So if my Campaign runs only from Monday to Friday, would it be correct to put the following numbers in the "var DAYSPERC"?:

 

Var DAYSPERC = [0.140,140,140,140,140.0]

 

I put "0" for Sunday and Saturday because those days the campaign will not be active, and for everything sum 700, I put 140 in every day.

 

  1. The use of the script has some conflict if I use it simultaneously with some automatic bid? (For example: Maximize Clicks)
  2. I have changed the data that is framed in red in the image, for the script.

Pantallazo1.jpg

Because I want it to run taking into account the current date (for example Today 21/05) and the script counts from the 1st of the month. Dividing the monthly budget between "30 days":

Pantallazo2.jpg

But I understand that the ideal is to divide between 30.4, because if I consider 30 days, the annual budget will end in 360 days and not 365 days. Is there a way that the value of "Days remaining" will be 30.4 always?. Thanks in advance for your help @Jon_Gritton

 

 

 

Re: Adjust Monthly Script Adwords, Is it possible?

Top Contributor
# 8
Top Contributor

Hi @Poke R

 

Your percentages are correct.  You may want to make the minimum budget figure (MIN_BUDGET) quite low to account for these days when the Campaign isn't running, but since the script always looks at the remaining budget, it won't have a huge effect.

 

Budget settings don't affect bidding strategies, so there's no conflict with them.

 

A better way to run for the first month is to adjust the total budget variable.  So if there's 8 days left in the first month, you should make your budget 8/30 of what it would normally be, then on the 1st June set it to your full monthly desired spend.

 

The script doesn't use 30.4 days as a "month", but instead checks how many days are actually in each month (i.e. 31 for January, 28 or 29 for February and so on), so over the course of a year it'll take account of the correct number of days.

 

Jon

AdWords Top Contributor Google+ Profile | Partner Profile | AdWords Audits

Re: Adjust Monthly Script Adwords, Is it possible?

Visitor ✭ ✭ ✭
# 9
Visitor ✭ ✭ ✭

Dear @Jon_Gritton I'm sorry to bother you again. It is that I was interested in the subject of the scripts to understand. I was reviewed all the code because I wanted to try to identify the lines that allow the monthly adjustment. I mean, if consumed in the month for example 180 usd of the budget of 200 usd / monthly, then the remaining 20 usd will be moved to the next month.  Is it something that is distributed in all the lines of the code ?, because I thought it was between line 83 to 86.

 

 script codigo.jpg

 

Ahh I forgot to ask @Jon_Gritton, the remaining 20 usd will be distributed throughout the following month or only in the following day(the first day of the month)?

Re: Adjust Monthly Script Adwords, Is it possible?

Top Contributor
# 10
Top Contributor

Hi @Poke R the script in this form works only on an individual month basis, no budget is "carried over" to the next month.  The script works best when daily budgets are close to the actual spend and where daily spend varies.  If the budget is consistently underused day to day, then there will be some left over at the end of the month, if the budget is consistently too low, then few adjustments will be made.

AdWords Top Contributor Google+ Profile | Partner Profile | AdWords Audits