Календарь обратного отсчета для распродаж

Скрипт таймера обратного отсчета позволяет ежечасно обновлять параметры объявления, чтобы показывать время, оставшееся до завершения одной определенной распродажи. С помощью календаря обратного отсчета можно управлять несколькими мероприятиями. Для этого необходимо связать со скриптом календарь и использовать модификаторы объявлений.

Обзор

Допустим, вы владелец магазина бытовой техники, в котором продаются стационарные миксеры разных брендов. Для двух из них у вас есть кампании AdWords.

Название продукта Название кампании
Стационарный миксер ProWhip prowhip
Стационарный миксер WhipMaster whipmaster

Вы планируете распродажу этих моделей миксеров.

Название продукта Дата начала Дата окончания
Стационарный миксер ProWhip 23 декабря 2014 г. 26 декабря 2014 г.
Стационарный миксер WhipMaster 23 декабря 2014 г. 29 декабря 2014 г.

Вы хотите, чтобы в период распродажи (например, 24 декабря) пользователи, которые ищут ваши товары в Google, видели следующие объявления:

Товар Объявление
Стационарный миксер ProWhip
Стационарный миксер WhipMaster

Скрипт извлекает из календаря список запланированных мероприятий, выбирает источник для модификатора объявлений, находит для каждого мероприятия соответствующую кампанию и применяет к ним необходимые объекты из модификатора.

Настройка кампаний

Необходимо настроить объявления c использованием функции модификаторов COUNTDOWN. В данном примере объявления выглядят следующим образом:

Название кампании Пример объявления
prowhip Стационарный миксер ProWhip
www.example.com
Стационарный миксер объемом 5 л.
$199 – распродажа закончится через {=COUNTDOWN(SalesCountdown.EndDate)}.
Стационарный миксер WhipMaster Профессиональный стационарный миксер WhipMaster
www.example.com
Стационарный миксер с откидывающимся блоком объемом 5 л.
$219 – распродажа закончится через {=COUNTDOWN(SalesCountdown.EndDate)}.

Настройка календаря обратного отсчета

Выполните следующие действия.

1. Создайте новый календарь Google

Нажмите на раскрывающееся меню рядом с пунктом меню Мои Календари и выберите Создать календарь.

Введите название календаря и нажмите кнопку Создать календарь.

2. Получите Идентификатор календаря

Нажмите на раскрывающееся меню рядом с названием созданного календаря и выберите Настройки календаря.

В нижней части страницы вы найдете идентификатор календаря. Он понадобится вам для настройки скрипта.

3. Создайте записи

Вам нужно создать в календаре мероприятия для каждой распродажи. Нажмите на календарь в любом месте, чтобы открыть страницу создания нового мероприятия.

Далее следуйте приведенным ниже рекомендациям:

  • Снимите флажок Весь день и укажите время начала и окончания мероприятия.
  • Убедитесь, что выбран правильный календарь.
  • Дайте мероприятию информативное название. В скрипте этот параметр будет использоваться для идентификации распродажи.
  • В поле "Описание" введите Campaign=CAMPAIGN_NAME, где CAMPAIGN_NAME – название рекламной кампании, к которой относится распродажа.

Нажмите кнопку "Сохранить".

Принцип работы скрипта

Скрипт считывает мероприятия из календаря с помощью API Calendar.

function listAllEvents() {
  var calendarEvents = Calendar.Events.list(calendarId, {
    singleEvents: true,
    orderBy: 'startTime'
  });

  var retval = [];

  for (var i = 0; i < calendarEvents.items.length; i++) {
    var event = calendarEvents.items[i];
    if (event.start.date || event.end.date) {
      throw ('All day events are not supported. Set a start and end time.');
    }
    var startDate = parseDate(event.start.dateTime);
    var endDate = parseDate(event.end.dateTime);

    retval.push({
      'Name': event.summary,
      'Campaign': getCampaignName(event.description),
      'StartDate': startDate,
      'EndDate': endDate
    });
  }
  return retval;
}

Затем при необходимости задается источник модификатора объявлений.

function createAdCustomizerSource() {
  var operation = AdWordsApp.newAdCustomizerSourceBuilder()
    .addAttribute('StartDate', 'date')
    .addAttribute('EndDate', 'date')
    .addAttribute('EventName', 'text')
    .withName(CUSTOMIZER_NAME)
    .build();
  return operation.getResult();
}

Для каждого мероприятия в календаре создается запись модификатора объявлений.

function addCustomizerItem(adCustomizerSource, eventName, startDate, endDate,
                           campaignName) {
  var operation = adCustomizerSource.adCustomizerItemBuilder()
    .withAttributeValue('StartDate', formatDate(startDate))
    .withAttributeValue('EndDate', formatDate(endDate))
    .withAttributeValue('EventName', eventName)
    .withTargetCampaign(campaignName)
    .build();
  return operation.getResult();
}

Если в кампаниях правильно настроено использование модификаторов, в объявлениях появится таймер обратного отсчета.

Настройка скрипта

  • Включите API Calendar в диалоговом окне "Расширенные API". Подробнее...
  • В начале скрипта в переменной CALENDAR_IDукажите идентификатор созданного календаря.
  • В начале скрипта в переменных EMAIL and EMAIL_CC укажите адреса электронной почты, на которые будут высылаться сообщения о том, что скрипт календаря обратного отсчета синхронизировался с мероприятием в календаре. Если вы не хотите получать такие сообщения, оставьте это поле пустым.

Планирование

Запланируйте ежечасное выполнение скрипта. При запуске скрипт будет проверять наличие изменений в календаре и вносить соответствующие изменения в аккаунт.

Исходный код

// 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 Sales Countdown Calendar
 *
 * @overview The Sales Countdown Calendar script allows you to update ads in
 *     your account to count down to multiple sales events by integrating a
 *     calendar to the script, and using ad customizers. See
 *     https://developers.google.com/adwords/scripts/docs/solutions/sales-countdown-calendar
 *     for more details.
 *
 * @author AdWords Scripts Team [adwords-scripts@googlegroups.com]
 *
 * @version 1.0
 *
 * @changelog
 * - version 1.0
 *   - Released initial version.
 */

// Set this value to your calendar's ID.
var CALENDAR_ID = 'INSERT_CALENDAR_ID';

// Name of the ad customizer source created by this script. If you change this
// value, you should also change your ads to refer to the new customizer name.
var CUSTOMIZER_NAME = 'SalesCountdown';

// Set this value to receive an email whenever the script updates ad
// customizers in your account.
var EMAIL = 'email@example.com';

// Set this value to the list of users who should get updates whenever the
// script updates ad customizers in your account.
var EMAIL_CC = ['email@example.com', 'email@example.com'];

function main() {
  var events = listAllEvents();
  var now = new Date();
  var customizer = getAdCustomizerSource();
  if (!customizer) {
    customizer = createAdCustomizerSource();
  }

  var logs = [];

  for (var i = 0; i < events.length; i++) {
    var event = events[i];
    if (event.Campaign) {
      var customizerItem = getCustomizerItem(customizer, event.Name);

      if (customizerItem) {
        if (event.EndDate > now) {
          if (customizerItem.getAttributeValue('EndDate') !=
              formatDate(event.EndDate) ||
              customizerItem.getTargetCampaignName() != event.Campaign) {
            setCustomizerItem(customizerItem, event.StartDate,
                              event.EndDate, event.Campaign);

            logs.push(Utilities.formatString('Updated countdown entry ' +
                'for %s. New end date: %s, associated campaign: %s.',
                event.Name, event.EndDate, event.Campaign));
          }
        } else {
          removeCustomizerItem(customizerItem);
          logs.push(Utilities.formatString('Removed countdown entry for ' +
              'expired event: %s.', event.Name));
        }
      } else {
        if (event.EndDate > now) {
          addCustomizerItem(customizer, event.Name, event.StartDate,
              event.EndDate, event.Campaign);
          logs.push(Utilities.formatString('Added countdown entry for %s. ' +
                    'End date: %s, associated campaign: %s.', event.Name,
                    event.EndDate, event.Campaign));
        }
      }
    }
  }

  if (logs.length > 0) {
    var htmlBody = [];
    htmlBody.push('The Sales countdown calendar script made the following ' +
                  'changes to Customer ID: ' +
                  AdWordsApp.currentAccount().getCustomerId() +
                  '<br>');
    htmlBody.push('<ul>');
    for (var i = 0; i < logs.length; i++) {
      htmlBody.push('<li>' + logs[i] + '</li>' + '<br>');
    }
    htmlBody.push('</ul>');
    MailApp.sendEmail({
      to: EMAIL,
      cc: EMAIL_CC.join(','),
      subject: 'Sales countdown calendar',
      htmlBody: htmlBody.join('\n')
    });
  }
}

/**
 * Gets the campaign name associated with an event.
 *
 * @param {string} eventDescription The event description.
 *
 * @return {?(string )} Name of the campaign associated with this event,
 *     or null if the event description doesn't specify one.
 */
function getCampaignName(eventDescription) {
  var parts = eventDescription.split('\n');
  for (var i = 0; i < parts.length; i++) {
    var subparts = parts[i].split('=');
    if (subparts.length == 2 && subparts[0].toLowerCase() == 'campaign') {
      return subparts[1];
    }
  }
  return null;
}

/**
 * Removes an ad customizer item.
 *
 * @param {AdCustomizerItem} customizerItem The item to be removed.
 */
function removeCustomizerItem(customizerItem) {
  customizerItem.remove();
}

/**
 * Retrieves an ad customizer item by its event name.
 *
 * @param {AdCustomizerSource} adCustomizerSource The ad customizer source to
 *     search for the item.
 * @param {string} eventName The event name.
 *
 * @return {?(AdCustomizerItem )} The ad customizer item if it exists,
 *     null otherwise.
 */
function getCustomizerItem(adCustomizerSource, eventName) {
  var items = adCustomizerSource.items().get();

  while (items.hasNext()) {
    var item = items.next();
    if (item.getAttributeValue('EventName') == eventName) {
      return item;
    }
  }
  return null;
}

/**
 * Updates an ad customizer item with new event details.
 *
 * @param {AdCustomizerItem} customizerItem The ad customizer item to
 *     be updated.
 * @param {Date} startDate The event start date.
 * @param {Date} endDate The event end date.
 * @param {string} campaignName The name of the campaign this event is
 *     associated with.
 */
function setCustomizerItem(customizerItem, startDate, endDate, campaignName) {
  customizerItem.setAttributeValue('StartDate', formatDate(startDate));
  customizerItem.setAttributeValue('EndDate', formatDate(endDate));
  customizerItem.setTargetCampaign(campaignName);
}

/**
 * Adds an ad customizer item.
 *
 * @param {AdCustomizerSource} adCustomizerSource The ad customizer source to
 *     which the new item is added.
 * @param {string} eventName The event name.
 * @param {Date} startDate The event start date.
 * @param {Date} endDate The event end date.
 * @param {string} campaignName The name of the campaign this event is
 *     associated with.
 *
 * @return {AdCustomizerItem} The ad customizer item.
 */
function addCustomizerItem(adCustomizerSource, eventName, startDate, endDate,
                           campaignName) {
  var operation = adCustomizerSource.adCustomizerItemBuilder()
    .withAttributeValue('StartDate', formatDate(startDate))
    .withAttributeValue('EndDate', formatDate(endDate))
    .withAttributeValue('EventName', eventName)
    .withTargetCampaign(campaignName)
    .build();
  return operation.getResult();
}

/**
 * Formats a date for creating a ad customizer item.
 *
 * @param {string} date The date to be formatted.
 *
 * @return {string} The formatted date.
 */
function formatDate(date) {
  return Utilities.formatDate(date, AdWordsApp.currentAccount().getTimeZone(),
                              'yyyyMMdd HHmmss');
}

/**
 * Create a new ad customizer source for this script.
 *
 * @return {(AdCustomizerSource)} The new ad customizer source.
 */
function createAdCustomizerSource() {
  var operation = AdWordsApp.newAdCustomizerSourceBuilder()
    .addAttribute('StartDate', 'date')
    .addAttribute('EndDate', 'date')
    .addAttribute('EventName', 'text')
    .withName(CUSTOMIZER_NAME)
    .build();
  return operation.getResult();
}

/**
 * Gets the ad customizer source for this script.
 *
 * @return {?(AdCustomizerSource )} An ad customizer source,
 *     if it exists, null otherwise.
 */
function getAdCustomizerSource() {
  var customizers = AdWordsApp.adCustomizerSources().get();
  while (customizers.hasNext()) {
    var customizer = customizers.next();
    if (customizer.getName() == CUSTOMIZER_NAME) {
      return customizer;
    }
  }
  return null;
}

/**
 * Gets the calendar's timezone.
 *
 * @return {string} The calendar's timezone.
 */
function getCalendarTimezone() {
  var calendar = Calendar.Calendars.get(CALENDAR_ID);
  return calendar.timeZone;
}

/**
 * Lists all events on the calendar.
 *
 * @return {Array.<Object>} An array of event details.
 */
function listAllEvents() {
  var calendarEvents = Calendar.Events.list(CALENDAR_ID, {
    singleEvents: true,
    orderBy: 'startTime'
  });

  var retval = [];

  for (var i = 0; i < calendarEvents.items.length; i++) {
    var event = calendarEvents.items[i];
    if (event.start.date || event.end.date) {
      throw ('All day events are not supported. Set a start and end time.');
    }
    var startDate = parseDate(event.start.dateTime);
    var endDate = parseDate(event.end.dateTime);

    retval.push({
      'Name': event.summary,
      'Campaign': getCampaignName(event.description),
      'StartDate': startDate,
      'EndDate': endDate
    });
  }
  return retval;
}

/**
 * Parses a date from Google Calendar.
 *
 * @param {string} dateText The date as a string.
 *
 * @return {Date} the parsed date.
 */
function parseDate(dateText) {
  // Date format is yyyy-mm-ddTHH:mm:ss±HH:mm.
  var dateFormat = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})([+-]\d{2}):(\d{2})$/;
  var parts = dateText.match(dateFormat);

  var year = parts[1];
  var month = parts[2];
  var day = parts[3];
  var hour = parts[4];
  var minute = parts[5];
  var second = parts[6];
  var tzHour = parseInt(parts[7]);
  var tzMin = parseInt(parts[8]);

  // Change the sign of tzMin if tzHour is negative. This way, -05:30
  // is interpreted as -05:00 -00:30 instead of -05:00 -00:30
  if (tzHour < 0) {
    tzMin = -tzMin;
  }
  var tzOffset = new Date().getTimezoneOffset() + tzHour * 60 + tzMin;

  return new Date(year, month - 1, day, hour, minute - tzOffset, second, 0);
}

Оставить отзыв о...

Текущей странице
Скрипты AdWords
Скрипты AdWords