VitUrzh
1/30/2017 - 6:06 AM

Удержание позиции 2018

Удержание позиции. Обновление. Быстрее вверх, медленней вниз

//Чтобы скрипт знал с какими компаниями работать, для них нужно добавить ярлык с именем '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);
  }
}