Рассказываю как создать огромную кампанию по ключевым словам конкурентов без ручного труда со сбором огромных массивов данных.

Для примера я возьму базу конкурентов собранную по методике описанной в другой моей статье — «Следим за конкурентами в Google Ads».

Плюсами такого подхода будут:

  • То что вы получите всех реальных конкурентов в поисковой рекламе, а не только тех которых вы сможете придумать\вспомнить.
  • То что у вас будут данные о масштабах пересечения ваших запросов, с запросами конкурентов — будет возможность отобрать самое релевантное.

Итак, данные лежат у меня в BigQuery. В таблицах нас интересуют вот эти поля:


Field name Type Mode
domain STRING NULLABLE
keyword STRING NULLABLE

Этого нам хватит чтобы создать структуру кампании.

В Advanced Apis нужно включить сервис BigQuery. Данные для скрипта мы получим с помощью вот такой функции:

function get_competitors() {
    var project_name = '**********', // название проекта
        dataset_name = '**********', // название датасета
        tables_mask = 'AU_IS_*';
    var queryRequest = BigQuery.newQueryRequest();
    queryRequest.query = 'SELECT COUNT(keyword) AS keys, domain ' +
        'FROM `' + project_name + '.' + dataset_name + '.AU_IS_*` ' +
        // даты впишите свои
        'WHERE SUBSTR(_TABLE_SUFFIX,-8) BETWEEN "20210121" AND "20210821" ' +
        'GROUP BY domain ' +
        'ORDER BY keys DESC ' +
        'LIMIT 500'; // топ-сколько конкурентов хотим взять?
    queryRequest.useLegacySql = false;
    var query = BigQuery.Jobs.query(queryRequest, project_name);
    var values = [];
    if (query.jobComplete) {
        for (var i = 0; i < query.rows.length; i++) {
            var row = query.rows[i];
            var domain = row.f[1].v;
            if (domain.indexOf('.') > -1) {
                values.push(domain);
            }
        }
    }
    return values;
}

Функция возвращает домены конкурентов по убыванию охвата ваших поисковых запросов. Логично предположить что чем больше конкурент охватывает ваши запросы, тем более он для вас релевантен, и тем интереснее для вас его запросы.

Если вы запускаете кампанию с нуля и у вас нет подобной истории данных, её можно съэмулировать, например, с помощью функции сбора объявлений конкурентов в Key Collector, или любом другом похожем по функционалу сервисе.

Далее, переходим к созданию структуры кампании. Заранее необходимо создать лишь пустую кампанию, которую мы наполним группами с помощью следующей функции:

function buildGroups() {
    var campaignSelector = AdsApp
        .campaigns()
        .withCondition('Name CONTAINS_IGNORE_CASE "Competitors"'); // выбираем эту кампанию
    var campaignIterator = campaignSelector.get();
    while (campaignIterator.hasNext()) {
        var campaign = campaignIterator.next();
        var competitors = get_competitors(); // получаем домены конкурентов из BigQuery
        for (var i = 0; i < competitors.length; i++) {
            var adGroupSelector = campaign
                .adGroups()
                .withCondition('Name CONTAINS_IGNORE_CASE "' + competitors[i] + '"');
            var adGroupIterator = adGroupSelector.get();
            if (!adGroupIterator.hasNext()) {
                var adGroupBuilder = campaign.newAdGroupBuilder();
                var adGroupOperation = adGroupBuilder
                   .withName(competitors[i])
                   .withStatus("PAUSED")
                   .build();
                // создаём группу по домену конкурента, если такой в кампании ранее не было
            }
        }
    }
}

Эту функцию можно запускать регулярно — она будет добавлять группы, если в базе будут появляться записи о новых конкурентах.

Теперь самое интересное — необходимо наполнить группы ключевыми словами конкурентов.

Я для этого взял данные сервиса API от SimilarWeb. У них есть подходящий метод (я использую Desktop Non-Branded Keywords), плюс их данные показались мне подходящими и качественно и количественно.

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

Вот функция для по получения фраз по домену:

function get_keys(domain) {
    var apiKey = '1234567890qwertyuiop'; // вписываем ключ API
    var MILLIS_PER_DAY = 1000 * 60 * 60 * 24,
        now = new Date(),
        fromDate = new Date(now.getTime() - 365 * MILLIS_PER_DAY),
        toDate = new Date(now.getTime() - 31 * MILLIS_PER_DAY),
        nowDate = new Date(now.getTime()),
        timeZone = AdsApp.currentAccount().getTimeZone(),
        fromformatDate = Utilities.formatDate(fromDate, timeZone, 'yyyy-MM'),
        toformatDate = Utilities.formatDate(toDate, timeZone, 'yyyy-MM');
    var url = 'https://api.similarweb.com/v1/website/' + domain +
        '/traffic-sources/nonbranded-search?api_key=' + apiKey +
        '&start_date=' + fromformatDate +
        '&end_date=' + toformatDate +
        '&country=world&limit=10000&main_domain_only=false&format=json';
    // Logger.log(url);
    var options = {
        muteHttpExceptions: true,
        method: 'GET',
        contentType: 'application/json'
    };
    var response = UrlFetchApp.fetch(url, options);
    var json = JSON.parse(response);
    if (!!json.meta.status) {
        if (json.meta.status == 'Error') {
            return null
        }
        if (json.meta.status == 'Success') {
            var keysArr = [];
            for (var k = 0; k < json.search.length; k++) {
                var key = json.search[k].search_term;
                if (key.split(' ').length < 5) {
                    // я решил брать только фразы короче 5 слов
                    keysArr.push(key);
                }
            }
            return keysArr;
        }
    }
}

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

Итак, функция получения ключей по домену у нас есть — давайте зальём их в группы.

Вот функция заполнения групп:

function buildKeys() {
    var campaignSelector = AdsApp
        .campaigns()
        .withCondition('Name CONTAINS_IGNORE_CASE "Competitors"');
    var campaignIterator = campaignSelector.get();
    while (campaignIterator.hasNext()) {
        var campaign = campaignIterator.next();
        var adGroupSelector = campaign
            .adGroups()
            .withCondition('Status = PAUSED')
            .withCondition('Name DOES_NOT_CONTAIN "_"')
            .orderBy('Name ASC');
        // Берем только всё ещё остановленные и не обработанные группы
        // При регулярном запуске скрипта это удобно
        // как только вы запустили группу - данные перестают обновляться
        var adGroupIterator = adGroupSelector.get();
        while (adGroupIterator.hasNext()) {
            var adGroup = adGroupIterator.next(),
                adGroupName = adGroup.getName();
            adGroup.setName('_' + adGroupName);
            // помечаем группу как обработанную
            var domain = adGroupName;
            Logger.log(domain);
            var keywordSelector = adGroup
                .keywords();
            var keywordIterator = keywordSelector.get();
            if (!keywordIterator.hasNext()) {
                var keys = get_keys(domain);
                // получаем фразы
                if ((!!keys) && (keys != null) && (keys.length > +0)) {
                    for (var n = 0; n < keys.length; n++) {
                        try {
                            var keywordOperation = adGroup.newKeywordBuilder()
                                .withText(keys[n])
                                .build();
                            // создаём фразу
                        } catch (e) {
                            Logger.log(e);
                        }
                    }
                }
            }
        }
    }
}

Тут есть особенности:

  1. Скрипт помечает группу как обработанную, даже если по домену не удалось получить фразы. Это нужно для случаев когда домен конкурента ещё новый и в spy-сервисе по нему еще не набралось данных.
  2. Для максимальной скорости ключи добавляются без какой либо трансформации и проверки успешности операции добавления.

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

С приведенными настройками, примерно за 3 дня авто-запуска скрипта у меня получилась кампания из 500 групп и ~800.000 фраз.

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

Ещё интересное


Добавить комментарий