Удержание позиции. Обновление. Быстрее вверх, медленней вниз
//Чтобы скрипт знал с какими компаниями работать, для них нужно добавить ярлык с именем 'SC' - script control
//Ярлык с именем "maxCPC15" укажет максимальное значение ставки. В данном случае ставка равна 15
//ярлык targetPosition2.4 указывает, что надо удерживать среднюю позиция 2.4
// Допустимое отклонение для средней позиции. Т.е. если допустимое отклонение = 0.1 а целевая позиция = 2, то скрипт не затронет ключи с позицией 1.9 и 2.1.
var TOLERANCE = 0.2;
// Множитель для изменения ставок. Т.е. если он равно 1.05 то ставки опустятся или поднимутся на 5%.
// На повышение обычно множитель больше, так как важнее быть выше, чем ниже
var BID_ADJUSTMENT_COEFFICIENT_up = 1.035;
var BID_ADJUSTMENT_COEFFICIENT_down = 1.025;
//не изменять ставку, если за выбранный период времени не было более IMPRESSIONS показов
var IMPRESSIONS = 2;
//Откуда брать максимальную цену
//1 - цена по умолчанию, задается ниже
//2 - цена из ярлыка
//3 - цена из группы
var cpcPlace = 2;
//максимально возможная ставка по умолчанию в валюте аккаунта
var maxCPC = 15.00;
// Повышающий коэффициент. Т.е. если он равен 1.05 то изменение составит 5%.
// задается на случай сильной волатильности стоимости клика
var COEFFICIENT = 1.15;
// Период, за который считаем статистику
// Если установить маленький промежуток времени, то у фраз с малым количеством показов будут возникать проблемы, когда одну неделю есть показы а другую нет
// 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 PERIOD = "LAST_7_DAYS";
function main() {
var campaignsWithPosition = AdWordsApp.campaigns().withCondition("LabelNames CONTAINS_ANY ['SC']").get();
while (campaignsWithPosition.hasNext()) {
var campaign = campaignsWithPosition.next();
if(campaign.isEnabled()){
var targetPositionLabel = campaign.labels().withCondition("LabelName STARTS_WITH_IGNORE_CASE 'targetPosition'").get().next().getName();
var targetPosition = parseFloat(targetPositionLabel.replace(/[^\d.-]/g, ''));
if(cpcPlace == 2){
var maxCpcLabel = campaign.labels().withCondition("LabelName STARTS_WITH_IGNORE_CASE 'maxCPC'").get().next().getName();
var maxCPC = parseFloat(maxCpcLabel.replace(/[^\d.-]/g, ''));
}
Logger.log(campaign.getName() + ' - target posinion: ' + targetPosition);
raiseKeywordBids(campaign, targetPosition, maxCPC);
lowerKeywordBids(campaign, targetPosition, maxCPC);
TopOfPageKeywordBids(campaign, maxCPC);
}
}
}
function raiseKeywordBids(campaign, targetPosition, maxCPC) {
var keywordsToRaise = campaign.keywords()
.withCondition("Status = ENABLED")
.withCondition("AdGroupStatus = ENABLED")
.withCondition("AveragePosition > " + (targetPosition + TOLERANCE))
//.withCondition("Impressions > " + IMPRESSIONS)
//.withCondition("Ctr > 0.01") //Note that Ctr is returned in 0..1 range, so 5% Ctr is represented as 0.05.
.orderBy("AveragePosition ASC")
.forDateRange(PERIOD)
.get();
while (keywordsToRaise.hasNext()) {
var keyword = keywordsToRaise.next();
if(cpcPlace == 3){
maxCPC = parseFloat(keyword.getAdGroup().bidding().getCpc());
}
var NewCost = keyword.getMaxCpc() * BID_ADJUSTMENT_COEFFICIENT_up;
//узнаем минимальную стоимость, чтобы показываться над результатами поиска
var TopOfPageCpc = keyword.getTopOfPageCpc();
//добавляем коэффециент
TopOfPageCpc = (TopOfPageCpc * COEFFICIENT);
//если расчетная ставка оказалась ниже необходимой для показа над поиском,
//то берем ставку необходимую для показа над поиском
if (NewCost < TopOfPageCpc){
NewCost = TopOfPageCpc;
}
//если конечная цена получается намного меньше максимальной цены, то повышаем цену.
//Например максимальная цена 80р, фактическая получается 2р, повышаем ее до 20, чтобы запас был.
//чтобы не мелочиться
if((maxCPC / NewCost) > 4){
NewCost = maxCPC / 4;
}
//ставка не должна быть больше заявленной нами
if (NewCost > maxCPC){
NewCost = maxCPC;
}
keyword.setMaxCpc(NewCost);
}
}
function lowerKeywordBids(campaign, targetPosition, maxCPC) {
var keywordsToLower = campaign.keywords()
//.withCondition("Ctr > 0.01")
.withCondition("AveragePosition < " + (targetPosition - TOLERANCE))
.withCondition("Status = ENABLED")
.withCondition("AdGroupStatus = ENABLED")
//.withCondition("Impressions > " + IMPRESSIONS)
.orderBy("AveragePosition DESC")
.forDateRange(PERIOD)
.get();
while (keywordsToLower.hasNext()) {
var keyword = keywordsToLower.next();
if(cpcPlace == 3){
maxCPC = parseFloat(keyword.getAdGroup().bidding().getCpc());
}
NewCost = (keyword.getMaxCpc() / BID_ADJUSTMENT_COEFFICIENT_down);
//узнаем минимальную стоимость, чтобы показываться над результатами поиска
var TopOfPageCpc = keyword.getTopOfPageCpc();
//добавляем защитный от скачков цены коэффециент
TopOfPageCpc = (TopOfPageCpc * COEFFICIENT);
//если расчетная ставка оказалась ниже необходимой для показа над поиском,
//то берем ставку необходимую для показа над поиском
if (NewCost < TopOfPageCpc){
NewCost = TopOfPageCpc;
}
//если конечная цена получается намного меньше максимальной цены, то повышаем цену.
//Например максимальная цена 80р, фактическая получается 2р, повышаем ее до 20, чтобы запас был.
if((maxCPC / NewCost) > 4){
NewCost = maxCPC / 4;
}
//ставка не должна быть больше заявленной нами
if (NewCost > maxCPC){
NewCost = maxCPC;
}
keyword.setMaxCpc(NewCost);
}
}
function TopOfPageKeywordBids(campaign, maxCPC) {
var keywordsToLower = campaign.keywords()
.withCondition("Impressions < 1")
.withCondition("Status = ENABLED")
.withCondition("AdGroupStatus = ENABLED")
.forDateRange(PERIOD)
.get();
while (keywordsToLower.hasNext()) {
var keyword = keywordsToLower.next();
if(cpcPlace == 3){
maxCPC = parseFloat(keyword.getAdGroup().bidding().getCpc());
}
//узнаем минимальную стоимость, чтобы показываться над результатами поиска
var TopOfPageCpc = keyword.getTopOfPageCpc();
//добавляем защитный от скачков цены коэффециент
TopOfPageCpc = (TopOfPageCpc * COEFFICIENT);
NewCost = TopOfPageCpc;
//если конечная цена получается намного меньше максимальной цены, то повышаем цену.
//Например максимальная цена 80р, фактическая получается 2р, повышаем ее до 20, чтобы запас был.
if((maxCPC / NewCost) > 4){
NewCost = maxCPC / 4;
}
//ставка не должна быть больше заявленной нами
if (NewCost > maxCPC){
NewCost = maxCPC;
}
keyword.setMaxCpc(NewCost);
}
}