Automação Google Ads: Como programar os Lances e Orçamentos

Nessa série especial, reunimos alguns scripts úteis para você automatizar e aumentar o retorno de suas campanhas no Google Ads. Confira abaixo como automatizar o Google Ads para “Modificação de Lances”.

 

1. Teste de Lances – por Google Ads. O script do Google testa vários lances e escreve os resultados em uma planilha do Google. Assim você pode determinar é o lance que vai gerar maior resultado para sua campanha ou determinar qual vai ser o impacto de um aumento de lances no seu resultado.

 

var keywordIter = campaign.keywords().get();
while (keywordIter.hasNext()) {
var keyword = keywordIter.next();
var oldBid = startingBids[keyword.getText()];
if (!oldBid) {
// If we don't have a starting bid, keyword has been added since we
// started testing.
oldBid = keyword.bidding().getCpc() || keyword.getAdGroup().bidding().getCpc();
startingBids[keyword.getText()] = oldBid;
}
var newBid = oldBid * multiplier;
keyword.bidding().setCpc(newBid);
}

 

Veja os demais códigos (Teste de lance)

 

2. Lances para posição de anúncios – por Google Ads. A primeira posição nem sempre é a que traz melhor resultado para sua empresa, pode ser muito custoso manter um anúncio na primeira posição, fazendo com que um anúncio na terceira sobressaia melhor do que na primeira posição. Esse script ajusta seus lances para manter uma posição determinada.

 

 

// Copyright 2015, Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
* @name Bid To Impression Share
*
* @overview The Bid To Impression Share script adjusts your bids and allows you
* to steer ads in an advertiser account into a desired impression share in
* the search results. See
* https://developers.google.com/adwords/scripts/docs/solutions/bid-to-impression-share
* for more details.
*
* @author AdWords Scripts Team [[email protected]]
*
* @version 2.0.1
*
* @changelog
* - version 2.0.1
* - Fixed logic when determining which keywords to raise and lower.
* - version 2.0.0
* - Refactored to target impression share rather than position.
* - version 1.0.1
* - Refactored to improve readability. Added documentation.
* - version 1.0
* - Released initial version.
*/

// Impression share you are trying to achieve.
var TARGET_IMPRESSION_SHARE = 50;

// Once the keywords fall within TOLERANCE of TARGET_IMPRESSION_SHARE,
// their bids will no longer be adjusted.
var TOLERANCE = 5;

// How much to adjust the bids.
var BID_ADJUSTMENT_COEFFICIENT = 1.05;

/**
* Main function that lowers and raises keywords' CPC to move closer to
* target impression share.
*/
function main() {
raiseKeywordBids();
lowerKeywordBids();
}

/**
* Increases the CPC of keywords that are below the target impression share.
*/
function raiseKeywordBids() {
var keywordsToRaise = getKeywordsToRaise();

while (keywordsToRaise.hasNext()) {
var keyword = keywordsToRaise.next();
keyword.bidding().setCpc(getIncreasedCpc(keyword.bidding().getCpc()));
}
}

/**
* Decreases the CPC of keywords that are above the target impression share.
*/
function lowerKeywordBids() {
var keywordsToLower = getKeywordsToLower();

while (keywordsToLower.hasNext()) {
var keyword = keywordsToLower.next();
keyword.bidding().setCpc(getDecreasedCpc(keyword.bidding().getCpc()));
}
}

/**
* Increases a given CPC using the bid adjustment coefficient.
* @param {number} cpc - the CPC to increase
* @return {number} the new CPC
*/
function getIncreasedCpc(cpc) {
return cpc * BID_ADJUSTMENT_COEFFICIENT;
}

/**
* Decreases a given CPC using the bid adjustment coefficient.
* @param {number} cpc - the CPC to decrease
* @return {number} the new CPC
*/
function getDecreasedCpc(cpc) {
return cpc / BID_ADJUSTMENT_COEFFICIENT;
}

/**
* Gets an iterator of the keywords that need to have their CPC raised.
* @return {Iterator} an iterator of the keywords
*/
function getKeywordsToRaise() {
// Condition to raise bid: Average impression share is worse (less) than
// target - tolerance
return AdWordsApp.keywords()
.withCondition('Status = ENABLED')
.withCondition(
'SearchImpressionShare < ' + (TARGET_IMPRESSION_SHARE - TOLERANCE))
.orderBy('SearchImpressionShare ASC')
.forDateRange('LAST_7_DAYS')
.get();
}

/**
* Gets an iterator of the keywords that need to have their CPC lowered.
* @return {Iterator} an iterator of the keywords
*/
function getKeywordsToLower() {
// Conditions to lower bid: Ctr greater than 1% AND
// average impression share better (greater) than target + tolerance
return AdWordsApp.keywords()
.withCondition('Ctr > 0.01')
.withCondition(
'SearchImpressionShare > ' + (TARGET_IMPRESSION_SHARE + TOLERANCE))
.withCondition('Status = ENABLED')
.orderBy('SearchImpressionShare DESC')
.forDateRange('LAST_7_DAYS')
.get();
}

 

3. Multiproponente – por Google Ads. Manter controle de uma grande quantidade de regras automatizadas pode ser difícil. Com esse script é possível utilizar uma planilha para controlar suas regras automatizadas, uma vez que, ela oferece as mesmas funcionalidades do recurso do Google Ads em uma planilha.

 

// Copyright 2015, Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
* @name Multi Bidder
*
* @overview The Multi Bidder script offers functionality similar to that of
* Automated Rules based on a spreadsheet. See
* https://developers.google.com/adwords/scripts/docs/solutions/multi-bidder
* for more details.
*
* @author AdWords Scripts Team [[email protected]]
*
* @version 1.0.3
*
* @changelog
* - version 1.0.3
* - Replaced deprecated keyword.getMaxCpc() and keyword.setMaxCpc().
* - version 1.0.2
* - Added validation of user settings.
* - version 1.0.1
* - Improvements to time zone handling.
* - version 1.0
* - Released initial version.
*/

var SPREADSHEET_URL = 'YOUR_SPREADSHEET_URL';

var spreadsheetAccess = new SpreadsheetAccess(SPREADSHEET_URL, 'Rules');

var totalColumns;

function main() {
// Make sure the spreadsheet is using the account's timezone.
spreadsheetAccess.spreadsheet.setSpreadsheetTimeZone(
AdWordsApp.currentAccount().getTimeZone());
spreadsheetAccess.spreadsheet.getRangeByName('account_id').setValue(
AdWordsApp.currentAccount().getCustomerId());

var columns = spreadsheetAccess.sheet.getRange(5, 2, 5, 100).getValues()[0];
for (var i = 0; i < columns.length; i++) {
if (columns[i].length == 0 || columns[i] == 'Results') {
totalColumns = i;
break;
}
}
if (columns[totalColumns] != 'Results') {
spreadsheetAccess.sheet.getRange(5, totalColumns + 2, 1, 1).
setValue('Results');
}
// clear the results column
spreadsheetAccess.sheet.getRange(6, totalColumns + 2, 1000, 1).clear();

var row = spreadsheetAccess.nextRow();

while (row != null) {
var argument;
var stopLimit;
try {
argument = parseArgument(row);
stopLimit = parseStopLimit(row);
} catch (ex) {
logError(ex);
row = spreadsheetAccess.nextRow();
continue;
}
var selector = AdWordsApp.keywords();
for (var i = 3; i < totalColumns; i++) {
var header = columns[i];
var value = row[i];
if (!isNaN(parseFloat(value)) || value.length > 0) {
if (header.indexOf("'") > 0) {
value = value.replace(/\'/g, "\\'");
} else if (header.indexOf('\"') > 0) {
value = value.replace(/"/g, '\\\"');
}
var condition = header.replace('?', value);
selector.withCondition(condition);
}
}
selector.forDateRange(spreadsheetAccess.spreadsheet.
getRangeByName('date_range').getValue());

var keywords = selector.get();

try {
keywords.hasNext();
} catch (ex) {
logError(ex);
row = spreadsheetAccess.nextRow();
continue;
}

var fetched = 0;
var changed = 0;

while (keywords.hasNext()) {
var keyword = keywords.next();
var oldBid = keyword.bidding().getCpc();
var action = row[0];
var newBid;

fetched++;
if (action == 'Add') {
newBid = addToBid(oldBid, argument, stopLimit);
} else if (action == 'Multiply by') {
newBid = multiplyBid(oldBid, argument, stopLimit);
} else if (action == 'Set to First Page Cpc' ||
action == 'Set to Top of Page Cpc') {
var newBid = action == 'Set to First Page Cpc' ?
keyword.getFirstPageCpc() : keyword.getTopOfPageCpc();
var isPositive = newBid > oldBid;
newBid = applyStopLimit(newBid, stopLimit, isPositive);
}
if (newBid < 0) {
newBid = 0.01;
}
newBid = newBid.toFixed(2);
if (newBid != oldBid) {
changed++;
}
keyword.bidding().setCpc(newBid);
}
logResult('Fetched ' + fetched + '\nChanged ' + changed);

row = spreadsheetAccess.nextRow();
}

spreadsheetAccess.spreadsheet.getRangeByName('last_execution')
.setValue(new Date());
}

function addToBid(oldBid, argument, stopLimit) {
return applyStopLimit(oldBid + argument, stopLimit, argument > 0);
}

function multiplyBid(oldBid, argument, stopLimit) {
return applyStopLimit(oldBid * argument, stopLimit, argument > 1);
}

function applyStopLimit(newBid, stopLimit, isPositive) {
if (stopLimit) {
if (isPositive && newBid > stopLimit) {
newBid = stopLimit;
} else if (!isPositive && newBid < stopLimit) {
newBid = stopLimit;
}
}
return newBid;
}

function parseArgument(row) {
if (row[1].length == 0 && (row[0] == 'Add' || row[0] == 'Multiply by')) {
throw ('\"Argument\" must be specified.');
}
var argument = parseFloat(row[1]);
if (isNaN(argument)) {
throw 'Bad Argument: must be a number.';
}
return argument;
}
function parseStopLimit(row) {
if (row[2].length == 0) {
return null;
}
var limit = parseFloat(row[2]);
if (isNaN(limit)) {
throw 'Bad Argument: must be a number.';
}
return limit;
}
function logError(error) {
spreadsheetAccess.sheet.getRange(spreadsheetAccess.currentRow(),
totalColumns + 2, 1, 1)
.setValue(error)
.setFontColor('#c00')
.setFontSize(8)
.setFontWeight('bold');
}
function logResult(result) {
spreadsheetAccess.sheet.getRange(spreadsheetAccess.currentRow(),
totalColumns + 2, 1, 1)
.setValue(result)
.setFontColor('#444')
.setFontSize(8)
.setFontWeight('normal');
}

function SpreadsheetAccess(spreadsheetUrl, sheetName) {
Logger.log('Using spreadsheet - %s.', spreadsheetUrl);
this.spreadsheet = validateAndGetSpreadsheet(spreadsheetUrl);

this.sheet = this.spreadsheet.getSheetByName(sheetName);
this.cells = this.sheet.getRange(6, 2, this.sheet.getMaxRows(),
this.sheet.getMaxColumns()).getValues();
this.rowIndex = 0;

this.nextRow = function() {
for (; this.rowIndex < this.cells.length; this.rowIndex++) {
if (this.cells[this.rowIndex][0]) {
return this.cells[this.rowIndex++];
}
}
return null;
};
this.currentRow = function() {
return this.rowIndex + 5;
};
}

/**
* Validates the provided spreadsheet URL
* to make sure that it's set up properly. Throws a descriptive error message
* if validation fails.
*
* @param {string} spreadsheeturl The URL of the spreadsheet to open.
* @return {Spreadsheet} The spreadsheet object itself, fetched from the URL.
* @throws {Error} If the spreadsheet URL hasn't been set
*/
function validateAndGetSpreadsheet(spreadsheeturl) {
if (spreadsheeturl == 'YOUR_SPREADSHEET_URL') {
throw new Error('Please specify a valid Spreadsheet URL. You can find' +
' a link to a template in the associated guide for this script.');
}
return SpreadsheetApp.openByUrl(spreadsheeturl);
}

 

Como configurar

 

4. Campanhas com regras de lances únicas – por Russel Savage. Determine um conjunto de regras para cada campanha do Google Ads nesse script. Faça seus lances aumentarem quando sua posição cair ou diminua seus lances quando o custo por conversão aumente demais.

 

//-----------------------------------
// Unique Bid Updates By Campaign
// Created By: Russ Savage
// FreeAdWordsScripts.com
//-----------------------------------
function main() {
// this is the structure that holds all the bid information about your accounts.
var CAMP_LIST = [
{
'camp_name' : 'camp name 1',
'rules' : [
{
'cpv_min' : 0, 'cpv_max' : 10,
'avg_pos_min' : 2, 'avg_pos_max' : 6,
'bid_change_amt' : 1.1, 'bid_limit' : 10
},
{
'cpv_min' : 10, 'cpv_max' : 20,
'avg_pos_min' : 6, 'avg_pos_max' : 10,
'bid_change_amt' : 1.2, 'bid_limit' : 10
}
]
},
{
'camp_name' : 'camp name 2',
'rules' : [
{
'cpv_min' : 0, 'cpv_max' : 5,
'avg_pos_min' : 3, 'avg_pos_max' : 5,
'bid_change_amt' : .9, 'bid_limit' : .01
},
{
'cpv_min' : 5, 'cpv_max' : 20,
'avg_pos_min' : 5, 'avg_pos_max' : 8,
'bid_change_amt' : 1.2, 'bid_limit' : 10
}
]
}
];
var date_range = 'LAST_7_DAYS';

for (index in CAMP_LIST) {
var camp = CAMP_LIST[index];
var camp_name = camp.camp_name;
var rules = camp.rules;

var kw_iter = AdWordsApp.keywords()
.withCondition("CampaignName CONTAINS_IGNORE_CASE '" + camp_name + "'")
.get();

while(kw_iter.hasNext()) {
var kw = kw_iter.next();
var kw_stats = kw.getStatsFor(date_range);
var conv = kw_stats.getConversions();

if (conv == 0) { continue; } //skip anything with no conversions

var cost = kw_stats.getCost();
var cpv = cost/conv;
var avg_pos = kw_stats.getAveragePosition();
var max_cpc = kw.getMaxCpc();

for(i in rules) {
var r = rules[i];

if(cpv >= r.cpv_min &&
cpv < r.cpv_max &&
avg_pos >= r.avg_pos_min &&
avg_pos < r.avg_pos_max)
{
kw.setMaxCpc(calculate_bid(max_cpc,r.bid_change_amt,r.bid_limit));
break;
}
}
}
}

function calculate_bid(current_bid,perc_to_change,max_min_amt) {
if(perc_to_change >= 1) {
return (current_bid * perc_to_change > max_min_amt) ? max_min_amt : (current_bid * perc_to_change);
} else {
return (current_bid * perc_to_change < max_min_amt) ? max_min_amt : (current_bid * perc_to_change);
}
}
}

 

5. Orçamentos Flexíveis – por Google Ads. Esse script permite que os orçamentos sejam aumentados ou diminuídos durante um período de tempo. Por exemplo, caso tenha um orçamento de R$5.000 para gastar em 10 dias, você pode configurá-lo para gastar uniformemente R$4.000 nos 5 primeiros dias e R$300 nos outros 3 dias e R$700 nos últimos 2.

 

// Copyright 2015, Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
* @name Flexible Budgets
*
* @overview The Flexible budgets script dynamically adjusts campaign budget for
* an advertiser account with a custom budget distribution scheme on a daily
* basis. See
* https://developers.google.com/adwords/scripts/docs/solutions/flexible-budgets
* for more details.
*
* @author AdWords Scripts Team [[email protected]]
*
* @version 1.0.3
*
* @changelog
* - version 1.0.3
* - Add support for video and shopping campaigns.
* - version 1.0.2
* - Use setAmount on the budget instead of campaign.setBudget.
* - version 1.0.1
* - Improvements to time zone handling.
* - version 1.0
* - Released initial version.
*/

var START_DATE = new Date('May 1, 2016 0:00:00 -0500');
var END_DATE = new Date('June 1, 2016 0:00:00 -0500');
var TOTAL_BUDGET = 500;
var CAMPAIGN_NAME = 'Special Promotion';

function main() {
testBudgetStrategy(calculateBudgetEvenly, 10, 500);
// setNewBudget(calculateBudgetEvenly, CAMPAIGN_NAME, TOTAL_BUDGET,
// START_DATE, END_DATE);
}

function setNewBudget(budgetFunction, campaignName, totalBudget, start, end) {
var today = new Date();
if (today < start) {
Logger.log('Not ready to set budget yet');
return;
}
var campaign = getCampaign(campaignName);
var costSoFar = campaign.getStatsFor(
getDateStringInTimeZone('yyyyMMdd', start),
getDateStringInTimeZone('yyyyMMdd', end)).getCost();
var daysSoFar = datediff(start, today);
var totalDays = datediff(start, end);
var newBudget = budgetFunction(costSoFar, totalBudget, daysSoFar, totalDays);
campaign.getBudget().setAmount(newBudget);
}

function calculateBudgetEvenly(costSoFar, totalBudget, daysSoFar, totalDays) {
var daysRemaining = totalDays - daysSoFar;
var budgetRemaining = totalBudget - costSoFar;
if (daysRemaining <= 0) {
return budgetRemaining;
} else {
return budgetRemaining / daysRemaining;
}
}

function calculateBudgetWeighted(costSoFar, totalBudget, daysSoFar,
totalDays) {
var daysRemaining = totalDays - daysSoFar;
var budgetRemaining = totalBudget - costSoFar;
if (daysRemaining <= 0) {
return budgetRemaining;
} else {
return budgetRemaining / (2 * daysRemaining - 1);
}
}

function testBudgetStrategy(budgetFunc, totalDays, totalBudget) {
var daysSoFar = 0;
var costSoFar = 0;
while (daysSoFar <= totalDays + 2) {
var newBudget = budgetFunc(costSoFar, totalBudget, daysSoFar, totalDays);
Logger.log('Day %s of %s, new budget %s, cost so far %s', daysSoFar + 1,
totalDays, newBudget, costSoFar);
costSoFar += newBudget;
daysSoFar += 1;
}
}

/**
* Returns number of days between two dates, rounded up to nearest whole day.
*/
function datediff(from, to) {
var millisPerDay = 1000 * 60 * 60 * 24;
return Math.ceil((to - from) / millisPerDay);
}

function getDateStringInTimeZone(format, date, timeZone) {
date = date || new Date();
timeZone = timeZone || AdWordsApp.currentAccount().getTimeZone();
return Utilities.formatDate(date, timeZone, format);
}

/**
* Finds a campaign by name, whether it is a regular, video, or shopping
* campaign, by trying all in sequence until it finds one.
*
* @param {string} campaignName The campaign name to find.
* @return {Object} The campaign found, or null if none was found.
*/
function getCampaign(campaignName) {
var selectors = [AdWordsApp.campaigns(), AdWordsApp.videoCampaigns(),
AdWordsApp.shoppingCampaigns()];
for(var i = 0; i < selectors.length; i++) {
var campaignIter = selectors[i].
withCondition('CampaignName = "' + campaignName + '"').
get();
if (campaignIter.hasNext()) {
return campaignIter.next();
}
}
throw new Error('Could not find specified campaign: ' + campaignName);
}

Como configurar 

 

6. Utilize uma planilha para gerenciar seus lances – por Russel Savage. Esse script utiliza uma planilha do Google para gerenciar os lances de suas campanhas do Google Ads (contanto que os 2 estejam em uma mesma conta do Google).

 

/****************************************
* Update Bids Using a Google Spreadsheet
* Version 1.1
* Created By: Russ Savage
* FreeAdWordsScripts.com
****************************************/
function main() {
var SPREADSHEET_URL = "Insert Url Here";

var spreadsheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
var sheet = spreadsheet.getSheetByName('KeywordBids');
var data = sheet.getRange("A:E").getValues();

var kwBidHash = {};
for(var i in data) {
if(i == 0) { continue; }
if(data[i][0] === '') { break; }
var kwKey = Utilities.base64Encode([data[i][0],data[i][1],data[i][2]].join('~~!~~'));
kwBidHash[kwKey] = data[i];
}

var kwIter = AdWordsApp.keywords()
.withCondition("Status = ENABLED")
.get();

while(kwIter.hasNext()) {
var kw = kwIter.next();
var campName = kw.getCampaign().getName();
var kwKey = Utilities.base64Encode([campName,kw.getText(),kw.getMatchType()].join('~~!~~'));
if(kwBidHash[kwKey]) {
if(kwBidHash[kwKey][3] === "FIXED") {
kw.setMaxCpc(kwBidHash[kwKey][4]);
}else{
kw.setMaxCpc(kw.getMaxCpc() * (1+kwBidHash[kwKey][4]));
}
}
}
}

 

7. Ajuste de orçamentos dinâmicos – por Russel Savage. Esse script possibilita que todas as campanhas sejam pausadas caso o custo total alcance um limite impedindo que a conta ultrapasse o limite de orçamento. Este é um script muito útil caso trabalhe com orçamentos limitados.

 

/********************************
* Dynamically Adjust Campaign Budgets v2.1
* Changelog v2.1 - Fixed opening of spreadsheet
* Created By: Russ Savage
* FreeAdWordsScripts.com
********************************/
// Let's set some constants
var TIMEFRAME = "THIS_MONTH";
//if the campaign is not in the spreadsheet, the budget is reset
//to this value at the beginning of the month.
var DEFAULT_BUDGET = 100;
var SPREADSHEET_URL = "PLACE EMPYT SPREADSHEET URL HERE";
var LABEL = ""; //Fill in if you only want to operate on campaigns with this label

var SIG_FIGS = 1000; //this means round all calculations to 3 decimal places
var MONTHLY_BUDGET = 0; // we will set this later

function main() {
MONTHLY_BUDGET = _pull_budget_data_from_spreadsheet();
var tot_cost_mtd = _get_total_cost();
var is_first_of_the_month = ((new Date()).getDate() == 1);
is_first_of_the_month = (is_first_of_the_month && ((new Date()).getHours() == 0));
Logger.log("Total cost: " + tot_cost_mtd + ", Monthly budget:" + MONTHLY_BUDGET);

if(is_first_of_the_month) {
_reset_budgets();
} else {
_adjust_campaign_budget(tot_cost_mtd);
}

}

// Returns the total cost for the set TIMEFRAME
function _get_total_cost() {
var camp_iter = (LABEL == "") ? AdWordsApp.campaigns().get() :
AdWordsApp.campaigns()
.withCondition("LabelNames CONTAINS_ANY ['"+LABEL+"']")
.get();

var tot_cost = 0;
while(camp_iter.hasNext()) {
tot_cost += camp_iter.next().getStatsFor(TIMEFRAME).getCost();
}
return tot_cost;
}

// Calculates run rate and adjusts campaign bids as needed.
function _adjust_campaign_budget(my_tot_cost) {
var today = new Date();
// Accounting for December
var eom = (today.getMonth() == 11) ? new Date(today.getFullYear()+1,0,1) :
new Date(today.getFullYear(),today.getMonth()+1,1);
var days_left = Math.round((eom-today)/1000/60/60/24);
var days_spent = today.getDate();
var run_rate = Math.round(my_tot_cost/days_spent*SIG_FIGS)/SIG_FIGS;
var projected_total = my_tot_cost + (run_rate * days_left);
var perc_over = Math.round(((MONTHLY_BUDGET-projected_total)/projected_total)*SIG_FIGS)/SIG_FIGS;
_change_spend(perc_over,my_tot_cost);
}

//Adjusts the budget for a given campaign based on percentage of total spend
//Note: if the cost of a campaign is $0 mtd, the budget is not changed.
function _change_spend(perc_to_change,my_tot_cost) {
var camp_iter = (LABEL == '') ? AdWordsApp.campaigns()
.withCondition("Status = ENABLED")
.get() :
AdWordsApp.campaigns()
.withCondition("Status = ENABLED")
.withCondition("LabelNames CONTAINS_ANY ['"+LABEL+"']")
.get();

while(camp_iter.hasNext()) {
var camp = camp_iter.next();
var camp_cost = camp.getStatsFor(TIMEFRAME).getCost();
var perc_of_total = Math.round(camp_cost/my_tot_cost*SIG_FIGS)/SIG_FIGS;
//If there is no cost for the campaign, let's not change it.
var to_change = (perc_of_total) ? (perc_of_total*perc_to_change) : 0;
camp.setBudget(camp.getBudget()*(1+to_change));
}
}

// Resets the budget unevenly
function _reset_budgets() {
var camp_budget_map = _pull_campaign_data_from_spreadsheet();
var camp_iter = (LABEL == '') ? AdWordsApp.campaigns()
.withCondition("Status = ENABLED")
.get() :
AdWordsApp.campaigns()
.withCondition("Status = ENABLED")
.withCondition("LabelNames CONTAINS_ANY ['"+LABEL+"']")
.get();
while(camp_iter.hasNext()) {
var camp = camp_iter.next();
if(camp_budget_map[camp.getName()]) {
camp.setBudget(camp_budget_map[camp.getName()]/30.5);
} else {
camp.setBudget(DEFAULT_BUDGET);
}
}
}

function _pull_campaign_data_from_spreadsheet() {
var spreadsheet = getSpreadsheet(SPREADSHEET_URL);
var sheet = spreadsheet.getActiveSheet();
var data = sheet.getRange("A:B").getValues();
if(data[0][0] == "") {
//This means this is the first run and we should populate the data.
_populate_spreadsheet(sheet);
data = sheet.getRange("A:B").getValues();
}
var campaign_budget_map = {};
for(var i in data) {
if(i == 0) { continue; } //ignore the header
if(data[i][0] == "") { break; } //stop when there is no more data
campaign_budget_map[data[i][0]] = parseFloat(data[i][1]);
}
return campaign_budget_map;
}

function _pull_budget_data_from_spreadsheet() {
var spreadsheet = getSpreadsheet(SPREADSHEET_URL);
var sheet = spreadsheet.getActiveSheet();
var data = sheet.getRange("A:B").getValues();
if(data[0][0] == "") {
//This means this is the first run and we should populate the data.
_populate_spreadsheet(sheet);
data = sheet.getRange("A:B").getValues();
}
var tot_budget = 0;
for(var i in data) {
if(i == 0) { continue; } //ignore the header
if(data[i][1] == "") { break; } //stop when there is no more data
tot_budget += parseFloat(data[i][1]);
}
return tot_budget;
}

function _populate_spreadsheet(sheet) {
sheet.clear();
sheet.appendRow(['Campaign Name','Monthly Budget']);
var camp_iter = (LABEL == '') ? AdWordsApp.campaigns()
.withCondition("Status = ENABLED")
.get() :
AdWordsApp.campaigns()
.withCondition("Status = ENABLED")
.withCondition("LabelNames CONTAINS_ANY ['"+LABEL+"']")
.get();
while(camp_iter.hasNext()) {
var camp = camp_iter.next();
sheet.appendRow([camp.getName(),(camp.getBudget()*30.5)]);
}
}

function getSpreadsheet(spreadsheetUrl) {
return SpreadsheetApp.openByUrl(spreadsheetUrl);
}

 

8. Aumentar os lances em palavras-chaves com custo/coversão baixo – O script permite que palavras-chave que geram conversão a um custo barato tenham seus lances aumentados.

 

function main() {
//For keywords with less than $5 CPC, let's pump those bids up by 35%
var AMAZING_COST_PER_CONV = 5;
var AMAZING_BID_INCREASE_AMOUNT = .35;

//For keywords with between $5 and $8 CPCs, we will only increase the bids by 20%
var GREAT_COST_PER_CONV = 8;
var GREAT_BID_INCREASE_AMOUNT = .20;

var kw_iter = AdWordsApp.keywords()
.withCondition("Status = ENABLED")
.get();

while(kw_iter.hasNext()) {
var kw = kw_iter.next();
var kw_stats = kw.getStatsFor("LAST_30_DAYS");
var cost = kw_stats.getCost();
var conversions = kw_stats.getConversions();
if(conversions > 0) {
var cost_per_conversion = (cost/(conversions*1.0));

if(cost_per_conversion <= AMAZING_COST_PER_CONV) {
kw.setMaxCpc(kw.getMaxCpc() * (1+AMAZING_BID_INCREASE_AMOUNT));
}
else if(cost_per_conversion <= GREAT_COST_PER_CONV) {
kw.setMaxCpc(kw.getMaxCpc() * (1+GREAT_BID_INCREASE_AMOUNT));
}
}else{
//no conversions on this keyword
//we will deal with that later
continue;
}
}
}