Как бесплатно настроить автоматический импорт расходов на Facebook Ads в Google Analytics



Подписчики моего Telegram-канала по веб-аналитике часто спрашивают про бесплатные сервисы по импорту расходов из рекламных систем в Google Analytics. В этой статье я решил показать как сделать такой сервис самостоятельно используя исключительно бесплатные ресурсы и язык программирования Python. Случайный образом я нашел PythonAnywhere  — простой облачный сервис, который позволяет запускать Python-код, в том числе по расписанию, делать веб-приложения (например, Flask) и вебхуки. У этого сервиса есть бесплатный тариф, и он нам подходит для решения задачи. Итак, будем настраивать импорт данных о расходах на Facebook рекламу в Google Analytics. Чтобы это сделать нужно:
  1. Зарегистрироваться в сервисе PythonAnywhere и войти в него.
  2. Открыть вкладку Consoles, нажать на ссылку Bash рядом с Other. 
  3. В открывшемся окне нужно установить дополнительные пакеты для работы — для этого поочередно выполните такие команды:

    1) pip3 install --user facebook_business
    2) pip3 install --user facebookads
    3) pip3 install --user --upgrade google-api-python-client
  4. Перейти на вкладку Files, в поле возле кнопки New file ввести название «fb_cost_to_ga.py» и нажать саму кнопку для создания нового файла. В открывшемся окне нужно вставить этот код и нажать Save.
  5. В только что созданном файле нужно заменить значения на свои, а именно:
    1. MY_APP_ID —ID приложения, через которое осуществляется работа с Facebook API.
    2. MY_APP_SECRET — secret приложения, через которое осуществляется работа с Facebook API.
    3. MY_LONG_LIVED_ACCESS_TOKEN — долгосрочный токен доступа, через который будут получаться данные о расходах из рекламного аккаунта.
    4. AD_ACCOUNT_ID — ID рекламного аккаунта в Facebook
    5. PATH_TO_SERVICE_ACCOUNT_KEY — путь к JSON-ключу сервисного аккаунта Google Cloud (создать проект GCP, создать сервисный аккаунт, включить GA API)
    6. GA_PROPERTY_ID — ID ресурса GA, в который надо загружать расходы
    7. GA_DATA_SET_ID — ID набора данных, в который будут загружаться расходы
    8. FB_CSV_FILEPATH — любое название файла .csv (например, fb_cost_data.csv). Именно с таким названием будет создаваться файл с последними данными о расходах, которые будут загружаться в GA.
  6. Если вам понятно, где взять все эти конфигурации — можете переходить к пункту 19 этой инструкции. Чтобы получить MY_APP_ID и MY_APP_SECRET нужно перейти на страницу https://developers.facebook.com/apps/ и создать приложение.
  7. После того, как вы создадите приложение нужно в боковом меню зайти на вкладку Settings -> Basic. На этой вкладке находится App ID и App Secret соответственно. Чтобы увидеть App Secret — нужно нажать кнопку Show.

  8. После этого нужно получить MY_LONG_LIVED_ACCESS_TOKEN. Для этого нужно нажать кнопку «+» возле пункта Products бокового меню. Найти блок Marketing API и нажать в нем кнопку Set Up.
  9. После этого в боковом меню нужно перейти на вкладку Marketing API->Tools, поставить галочку возле пункта ads_read и нажать кнопку Get Token. Вы получите обычный TOKEN, который надо обменять на долгосрочный.
  10. Для этого нужно подставить в эту ссылку свои значения (все они получены на предыдущих шагах) и перейти по этой ссылке:

    https://graph.facebook.com/v5.0/oauth/access_token?grant_type=fb_exchange_token&client_id={MY_APP_ID}&client_secret={MY_APP_SECRET}&fb_exchange_token={TOKEN}

    Подробнее об этом способе получения долгосрочного токена можно прочитать здесь.
  11. Если вы правильно составили ссылку, то перейдя по ней увидите access_token. Значение в кавычках рядом с этим ключом и есть MY_LONG_LIVED_ACCESS_TOKEN, который нужно указать в конфигурациях кода.

  12. AD_ACCOUNT_ID можно найти в ссылке, при работе с рекламным аккаунтом Facebook. Он находится в URL-параметре act. Или в выпадающем списке рекламных аккаунтов (см. скриншот).
  13. Дальше нужно создать проект в Google Cloud. Для этого нужно перейти по ссылке: https://console.cloud.google.com/projectcreate .
  14. Потом в боковом меню перейти на вкладку «APIs & Services», нажать кнопку « + ENABLE APIS AND SERVICES», найти блок Google Analytics API, перейти в него и нажать кнопку ENABLE.
  15. После этого осталось создать сервисный аккаунт. Для этого в боковом меню нужно перейти в пункт IAM & admin -> Service accounts. Потом нужно нажать кнопку «+ CREATE SERVICE ACCOUNT». На первом шаге указать имя (например «fb_cost_to_ga») и нажать кнопку Create. На втором шаге указать роль Project -> Viewer и нажать Continue. На третьем шаге нажать «+ CREATE KEY», выбрать Key Type JSON и нажать Create. Скачается файл ключа сервисного аккаунта. После этого нужно нажать кнопку Done, скопировать Email сервисного аккаунта и добавить этот имейл в качестве пользователя с правами на изменение на уровне ресурса Google Analytics, в который нужно импортировать расходы.
  16. Скачанный файл с предыдущего шага нужно загрузить в PythonAnywhere. Для этого нужно в этом сервисе перейти на вкладку Files, нажать кнопку «Upload a file», найти скачанный ранее файл и загрузить его. После этого осталось скопировать название этого файла, вместе с расширением .json и указать в качестве PATH_TO_SERVICE_ACCOUNT_KEY конфигураций скрипта (например, rare-lattice-258910-c92131d52661.json).
  17. GA_PROPERTY_ID — идентификатор отслеживания Google Analytics, который можно найти на вкладе Property Settings, админ панели GA. На этом же уровне настроек ресурса нужно было добавить email сервисного аккаунта в список пользователей GA.
  18.  GA_DATA_SET_ID нужно скопировать из интерфейса GA, предварительно создать набор данных для импорта. Инструкция по созданию есть здесь.
  19. Заменив все конфигурации на свои, нужно выполнить код мануально, чтобы убедиться что он работает и в нем нет ошибок. Для этого откройте свой файл и нажмите синюю кнопку Run.
  20. Если скрипт сработал без ошибок — вы увидите результат загрузки файла в GA.
  21. Осталось поставить скрипт на автоматическое выполнение. Для этого откройте вкладку Tasks, укажите время запуска скрипта (обратите внимание, строчкой выше отображается часовой пояс сервера, именно по этому времени будет запускаться скрипт) и путь к файлу вашего скрипта. Если вы создавали его в корневой папке, путь будет таким: /home/<ВАШ_ЛОГИН>/fb_cost_to_ga.py . После этого остается только нажать кнопку Create.
Все, наконец-то, готово. Результат загрузки файлов можно будет наблюдать здесь, перейдя по кнопке Manage Uploads, в списке наборов данных GA:


Это решение имеет ряд недостатков:

  • PythonAnywhere в бесплатной версии имеет много ограничений. Например, можно выполнять код максимум 100 секунд и хранить файлов не более чем на 500 мб. Этих ограничений достаточно, чтобы любому маленькому и среднему бизнесу решать задачу по импорту своих расходов. Если все таки ограничения этого сервиса не позволяют решить эту задачу — можно сделать аналогичное решение на базе Google Cloud.
  • Tasks в PythonAnywhere работают три месяца, с момента их создания. Для продливания этого времени нужно хотя бы раз в 3 месяца заходить на эту вкладку и нажимать кнопку Extend Expiry.
  • Long-Lived Access Token Facebook API живет 60 дней. Поэтому раз в 2 месяца, нужно заходить и проходить пункты 8, 9, 10 еще раз, обновляя MY_LONG_LIVED_ACCESS_TOKEN.
  • Так же, сами рекламные сервисы, в данном случае Facebook, может пересчитывать данных по расходам ретроспективно. Из-за этого расходы в GA могут отличаться от тех, которые будет показывать Facebook в рекламном кабинете. Но этого можно избежать, если переделать алгоритм загрузки расходов в GA прямо в коде fb_cost_to_ga.py.
  • Данные импортируются в той валюте, в которой они отображаются в Facebook. Но можно найти бесплатный API (например, этот), чтобы получать данные о курсах валют и конвертировать их перед импортом. 
  • Это решение импортирует расходы только на уровень источника (facebook), канала (cpc) и кампании. При чем для правильного матчинга данных названия Facebook Ads кампаний должны совпадать со значениями, которые передаются в параметр utm_campaign для ссылок из этих кампаний. 



Комментарии

  1. Добрый день, подскажите пожалуйста, можно ли как то реализовать, например, чтобы в в гугл таблицу выводить название аккаунта с бизнес менеджера, его лимит затрат и сумму расходов?

    ОтветитьУдалить
  2. Дмитрий, здравствуйте, спасибо за инструкцию! всё получилось, файл с расходами появился в разделе импорта данных, но эти данные не отразились в отчете Кампании=>Анализ расходов. Для этого нужно что-то дополнительно сделать или это и не предполагается? Если нет, в чем-то тогда практический смысл такой выгрузки?)

    ОтветитьУдалить
  3. Обратите внимание на сервис garpun feeds там бесплатно и без питона можно

    ОтветитьУдалить
    Ответы
    1. Круто, спасибо) Не знал о существовании такого сервиса)

      Удалить
    2. Но вроде бы загрузка расходов в Google Analytics не поддерживается в Free пакете: https://garpun.com/planes

      Удалить
    3. Фиг знает, я настроил )))) Там правда через BigQuery, но он у меня есть. Итоговая схема следующая - заливаете данные рекламных кабинетов в BQ (тоже потоками), а оттуда уже потоком BQ -> GA загружаете данные. Может не супер удобно может показаться, зато кастомизировать можно очень просто под клиентов, так как utm можно на этапе запроса в BQ поменять

      Удалить
    4. Прикольно) Спасибо за информацию!

      Удалить
    5. Пожалста! Вообще у них там много прикольного из фич, можете саппорт попытать - они быстро отвечают, может даже помогут донастроить что-то

      Удалить
  4. Something wrong... argument should be integer or bytes-like object, not 'str'
    ____
    pythonanywhere выдает такую ошибку) где я мог сделать ошибку?)

    ОтветитьУдалить
    Ответы
    1. Поэтому я люблю сервисы, где кто-то решает за меня такие проблемы и я экономлю время =)

      Удалить
    2. Только что проверил код — все ок)

      Может быть у вас нет данных о расходах за вчерашний день, может где-то что-то сделали «не по инструкции»)

      Удалить
    3. Denys, не получилось разобраться, в чем ошибка?

      У меня все то же самое, argument should be integer or bytes-like object, not 'str'

      Но эта ошибка возникает, только если запускать через сервис. Тот же код на десктопном питоне прекрасно работает. Файл расходов формируется и через сервис, ошибку выдает функция build. Только как это исправить, не понимаю. И идеи закончились

      Удалить
    4. Привет, тоже столкнулся с этой ошибкой "should be integer or bytes-like object, not 'str' " , Дмитрий, вы упомянули возможную проблему в отсутствии расходов, в моем случае это так, но расходы есть за прошлый месяц, возможно ли в этом скрипте задать определенные даты, чтобы проверить эту гипотезу?

      Удалить
    5. Вы можете попробовать вытащить расходы за какую-то определенную дату, для этого нужно эту строку:

      yesterday = yesterday.strftime('%Y-%m-%d')

      переписать так:

      yesterday = '2019-11-25'

      , где 2019-11-25 — дата, за которую вы хотите загрузить данные о расходах в GA

      Удалить
  5. Доброго дня! Вот такую ошибку выдает на шаге 19 (данные в GA не загружает):
    Traceback (most recent call last):
    File "/home/marketingprobusiness/fb_cost_to_ga.py", line 13, in
    import numpy as np
    File "/usr/lib/python3.8/site-packages/numpy/__init__.py", line 142, in
    from . import core
    File "/usr/lib/python3.8/site-packages/numpy/core/__init__.py", line 17, in
    from . import multiarray
    File "/usr/lib/python3.8/site-packages/numpy/core/multiarray.py", line 14, in
    from . import overrides
    File "/usr/lib/python3.8/site-packages/numpy/core/overrides.py", line 16, in
    add_docstring(
    RuntimeError: implement_array_function method already has a docstring
    >>>

    Как это можно исправить?

    ОтветитьУдалить
    Ответы
    1. Могу ошибаться, но кажется у вас не установлен пакет numpy. Попробуйте установить пакет в терминале (консоли) командой:

      pip install numpy

      или в случае Python 3:

      pip3 install numpy

      Удалить
  6. Код отлично работает из Пайчарма, но с этого сайта отрабатывать отказывается.

    Ошибки:
    argument should be integer or bytes-like object, not 'str'

    и

    RuntimeError: implement_array_function method already has a docstring

    ОтветитьУдалить

Отправка комментария

Популярные сообщения из этого блога

Настройка Server-Side API для Facebook Pixel