Перейти к содержимому
Socialift
Руководство

Рекламная кампания через Meta Marketing API

В Marketing API реклама собирается из четырёх уровней: кампания (цель, например OUTCOME_TRAFFIC), группа объявлений (аудитория, бюджет, расписание), креатив (изображение, текст, ссылка) и объявление. Бюджет передаётся целым числом в минимальных единицах валюты, special_ad_categories обязателен для каждой кампании, а безопасный путь — создавать всё в PAUSED и включать после проверки.

Обновлено:

Коротко: как создать кампанию через API

Порядок жёсткий: выбираете рекламный кабинет (act_...), ищете и бесплатно оцениваете аудиторию, затем POST /act_{id}/campaigns (цель и special_ad_categories), /adsets (таргетинг, бюджет, оптимизация), /adimages и /adcreatives (изображение и текст) и в конце /ads. Всё создаётся в PAUSED, а после проверки все три уровня переводятся в ACTIVE.

Разрешения: для отчётов — ads_read, для создания и управления — ads_management. Чтобы работать с кабинетами других компаний, для ads_management нужен Advanced Access, то есть App Review.

Иерархия объектов: что где задаётся

Иерархия объектов: что где задаётся — Таблица возможностей по платформам
УровеньЧто определяетEndpointМетод SDK
Рекламный кабинетВалюта, оплата, доступыact_{id}ads.ad_accounts
КампанияОдна цель (objective), special_ad_categories, опционально общий бюджетPOST /act_{id}/campaignscreate_campaign
Группа объявлений (ad set)Аудитория, бюджет, расписание, оптимизация и событие оплатыPOST /act_{id}/adsetscreate_adset
Изображениеhash для креативаPOST /act_{id}/adimagesupload_image
КреативИзображение или видео, текст, ссылка, CTA; после создания не меняетсяPOST /act_{id}/adcreativescreate_creative
ОбъявлениеСвязывает ad set и креативPOST /act_{id}/adscreate_ad

Все объявления в одной группе делят аудиторию и цель оптимизации. Креатив изменить нельзя — создаёте новый и привязываете к объявлению.

Цели кампании (objective)

Начиная с Marketing API v17.0 новые кампании создаются только с упрощёнными целями OUTCOME.

Цели кампании (objective) — Таблица возможностей по платформам
ObjectiveКогда выбирать
OUTCOME_AWARENESSПоказать рекламу как можно большему числу людей, узнаваемость
OUTCOME_TRAFFICПереходы на сайт, в приложение или профиль
OUTCOME_ENGAGEMENTВовлечённость в пост, просмотры видео, сообщения
OUTCOME_LEADSЛид-формы и другие заявки
OUTCOME_SALESПродажи и конверсии
OUTCOME_APP_PROMOTIONУстановки приложения и действия в нём

Создать новую кампанию со старыми целями вроде LINK_CLICKS, CONVERSIONS или REACH нельзя; ранее созданные кампании продолжают работать.

В каких единицах передаётся бюджет

daily_budget и lifetime_budget — целое число в валюте кабинета, в минимальных единицах (Meta называет это offset). Для валют с offset 100 (USD, EUR, RUB и др.) 20 долларов в день передаются как 2000. Для валют с offset 1 (JPY, KRW, IDR, VND, CLP, COP, CRC, HUF, ISK, PYG, TWD) значение указывается в основной единице.

Узбекского сума (UZS) нет в списке валют Meta, поэтому всегда считайте бюджет в валюте самого кабинета (account.currency).

Бюджет задаётся либо на уровне кампании (Meta сама распределяет его по группам), либо на уровне группы объявлений — но не на обоих сразу. С lifetime_budget обязателен end_time; daily_budget — для групп длительностью больше 24 часов.

В SDK Socialift daily_budget_major=20 умножается на CURRENCY_OFFSET (100) и уходит как 2000. Это верно для валют с offset 100; если валюта кабинета с offset 1, делите значение на 100.

special_ad_categories: обязательно для каждой кампании

Meta требует явно указывать для каждой новой или изменённой кампании, относится ли она к особой категории. Для обычной рекламы передаётся пустой список ([]) — метод create_campaign в SDK делает это по умолчанию.

Категории: HOUSING (жильё), EMPLOYMENT (вакансии), FINANCIAL_PRODUCTS_SERVICES (финансовые продукты; заменила старое значение CREDIT) и ISSUES_ELECTIONS_POLITICS (социальные темы, выборы, политика). При выборе категории обязателен и special_ad_category_country.

Таргетинг в этих категориях ограничен: например, для рекламы жилья, вакансий и финансов в США, Канаде и Европе возраст обычно фиксируется на 18–65+, пол выбрать нельзя, радиус местоположения — не меньше 25 км, похожие аудитории недоступны.

Запуск кампании с нуля: 8 шагов

  1. Выберите кабинет

    ads.ad_accounts возвращает доступные пользователю кабинеты с идентификатором act_... и валютой. Бюджет считаете в этой валюте.

  2. Найдите интересы и местоположения

    search_interests (type=adinterest) — id, name, path и диапазон размера аудитории. search_locations (type=adgeolocation) — key для таргетинга. Храните ID, а не названия: Meta может переименовывать интересы.

  3. Соберите таргетинг

    Без Custom Audience нужна хотя бы одна страна. age_min не меньше 13, age_max не больше 65; genders: 1 — мужчины, 2 — женщины, без поля — все. Радиус вокруг города — 17–80 км.

  4. Оцените аудиторию без затрат

    GET /act_{id}/delivery_estimate отдаёт диапазон месячной аудитории (estimate_mau_lower_bound, estimate_mau_upper_bound) и estimate_dau. Если estimate_ready=false, повторите запрос чуть позже.

  5. Создайте кампанию

    Цель (OUTCOME_*), special_ad_categories и status=PAUSED.

  6. Создайте группу объявлений

    Таргетинг, бюджет, optimization_goal (например LINK_CLICKS), billing_event (например IMPRESSIONS) и снова PAUSED.

  7. Изображение, креатив и объявление

    Загружаете изображение в /adimages и получаете hash, в креативе указываете его внутри object_story_spec (страница, ссылка, текст, CTA), в объявлении — {"creative_id": ...}.

  8. Проверьте и включите

    Посмотрите превью, затем переведите кампанию, группу и объявление в ACTIVE. Объявление сначала проходит модерацию — следите за PENDING_REVIEW и DISAPPROVED в effective_status.

Python: поиск и оценка аудитории

Ничего не создаётся и деньги не тратятся — только поиск и оценка.

audience.py
import asyncio, os
from socialift import Ads

async def main() -> None:
    token = os.environ["META_USER_TOKEN"]
    async with Ads(app_secret=os.environ["FACEBOOK_APP_SECRET"]) as ads:
        account = (await ads.ad_accounts(token))[0]
        print(account.id, account.currency)

        interests = await ads.search_interests(token, "fitness", limit=5)
        cities = await ads.search_locations(token, "Almaty", country_code="KZ")
        print([c["key"] for c in cities])  # для cities=[...]

        targeting = ads.build_targeting(
            countries=["KZ"],
            age_min=18,
            interests=[{"id": i["id"], "name": i["name"]} for i in interests[:3]],
        )  # advantage_audience=True по умолчанию
        estimate = await ads.delivery_estimate(token, ad_account_id=account.id, targeting=targeting)
        print(estimate.get("estimate_mau_lower_bound"), estimate.get("estimate_mau_upper_bound"))

asyncio.run(main())

Интересы внутри interests объединяются через «ИЛИ». Для условия «A И B» используйте параметр flexible_spec в build_targeting.

Точного числа Meta не даёт — только диапазон. Если он слишком узкий, уберите часть интересов или оставьте Advantage+ audience включённым.

Python: кампания → группа → креатив → объявление

В SDK status по умолчанию PAUSED — ни один вызов сам не начинает тратить деньги.

launch.py
from socialift import Ads

async def launch(ads: Ads, token: str, account_id: str, page_id: str, targeting: dict) -> str:
    campaign = await ads.create_campaign(
        token, ad_account_id=account_id, name="Осенняя акция",
        objective="OUTCOME_TRAFFIC", special_ad_categories=[],
    )
    adset = await ads.create_adset(
        token, ad_account_id=account_id, name="KZ 18+", campaign_id=campaign["id"],
        targeting=targeting, optimization_goal="LINK_CLICKS", billing_event="IMPRESSIONS",
        daily_budget_major=20,  # кабинет в USD: уйдёт 2000 центов
    )
    with open("banner.jpg", "rb") as f:
        image = await ads.upload_image(token, ad_account_id=account_id, image=f.read(), filename="banner.jpg")
    creative = await ads.create_creative(
        token, ad_account_id=account_id, name="Баннер A", page_id=page_id,
        link="https://example.com", message="Осенние скидки", image_hash=image["hash"],
    )
    ad = await ads.create_ad(
        token, ad_account_id=account_id, name="Баннер A",
        adset_id=adset["id"], creative_id=creative["id"],
    )
    return ad["id"]

Чтобы объявление начало показываться, все три уровня — кампания, группа и объявление — должны быть ACTIVE: если родитель на паузе, effective_status объявления будет CAMPAIGN_PAUSED или ADSET_PAUSED. Включение: await ads.set_status(token, node_id, "ACTIVE") для каждого уровня.

Надёжнее всего останавливать на уровне кампании: при PAUSED у кампании не показывается ничего из того, что под ней.

Чтобы показывать рекламу от имени Instagram-аккаунта, передайте в create_creative параметр instagram_user_id — Meta требует его вместо устаревшего instagram_actor_id.

Advantage+ audience: с v23.0 указывается явно

Advantage+ audience разрешает системе показа Meta выходить за пределы заданной аудитории в поисках людей, которые дадут результат. В API это поле targeting.targeting_automation.advantage_audience: 1 — включено, 0 — выключено.

Начиная с Graph API v23.0 при создании новой группы объявлений значение по умолчанию равно 1 либо требуется явно передать 1 или 0. На обновление существующих групп это не влияет.

Во включённом режиме возраст — не жёсткое ограничение: age_min можно задать только в диапазоне 18–25, а age_max фиксирован на 65. Более узкий возраст передаётся как подсказка через age_range. Если нужен строгий контроль (например, юридические ограничения), вызывайте build_targeting(..., advantage_audience=False) и задавайте age_min/age_max как границы.

Разрешения и уровни доступа Marketing API

ads_read — отчёты по рекламе и Insights API. ads_management — чтение и управление кабинетом, создание кампаний; зависит от pages_read_engagement и pages_show_list и для чужих бизнесов требует Advanced Access. Tech provider, работающим с данными других компаний, нужна ещё и Access Verification.

У Marketing API свои уровни: Limited Access (бывший Standard) выдаётся автоматически при добавлении продукта, с жёсткими лимитами на каждый кабинет — для разработки. Full Access (бывший Advanced) — после App Review, лимиты мягче. Условие Meta: минимум 500 вызовов Marketing API за последние 15 дней и доля ошибок меньше 15% в последних 500 вызовах.

Чтение результатов: insights

/{object-id}/insights есть на каждом уровне: кабинет, кампания, группа и объявление.

report.py
summary = await ads.insights(token, campaign_id, since="2026-09-01", until="2026-09-16")
print(summary.spend, summary.impressions, summary.reach, summary.ctr)

rows = await ads.insights_rows(
    token, account_id, level="adset", date_preset="last_7d", breakdowns=["age", "gender"]
)
for row in rows:
    print(row.get("age"), row.get("gender"), row.get("spend"), row.get("cpc"))

Без дат insights возвращает сумму за весь период (date_preset=maximum); сама Meta на запрос без параметров обычно отдаёт последние 30 дней.

insights_rows возвращает сырые строки с разбивкой — здесь ответ на вопрос «в какой возрастной группе клик дешевле». Не все разбивки совместимы: при ошибке добавляйте их по одной.

Проверьте перед запуском

  • Известны валюта кабинета и её offset, бюджет пересчитан.
  • special_ad_categories задан явно (для обычной рекламы []).
  • В таргетинге есть хотя бы одна страна или Custom Audience.
  • Диапазон из delivery_estimate соответствует задаче.
  • Кампания, группа и объявление созданы в PAUSED и проверены.
  • Для запуска все три уровня ACTIVE, для остановки — PAUSED у кампании.
  • effective_status и расход отслеживаются регулярно.

← Назад в блог

Частые вопросы

Почему бюджет получился в 100 раз больше или меньше?

Marketing API ожидает бюджет в минимальных единицах валюты. В USD 20 долларов — это 2000, а в валюте с offset 1, например JPY, 2000 — это 2000 иен. Проверьте валюту кабинета и передавайте значение соответственно.

Можно ли использовать старую цель LINK_CLICKS?

Для новых кампаний — нет: с v17.0 принимаются только цели OUTCOME_*. LINK_CLICKS теперь используется как optimization_goal на уровне группы объявлений.

Можно ли узнать размер аудитории, не тратя деньги?

Да, endpoint delivery_estimate возвращает примерный диапазон месячной аудитории и дневных активных пользователей. Точного числа Meta не даёт, только диапазон.

Объявление создано, но не показывается — почему?

Чаще всего кампания или группа ещё в PAUSED, либо объявление на модерации (PENDING_REVIEW) или отклонено (DISAPPROVED). Смотрите поле effective_status объявления.

Нужен ли App Review для ads_management?

Для своих кабинетов и людей с ролями в приложении хватает Standard (Limited) Access. Чтобы управлять кабинетами других компаний, нужен Advanced Access — App Review и Business Verification.

Можно ли не передавать special_ad_categories?

Нет, поле обязательное. Для обычной рекламы передаётся пустой список; для тем жилья, вакансий, финансов или политики — соответствующая категория и special_ad_category_country.

Источники

  1. Meta: Ad Campaign reference
  2. Meta: Currencies
  3. Meta: Special Ad Categories
  4. Meta: Advantage+ audience
  5. Meta: Ad Account delivery estimate
  6. Meta: Marketing API authorization

Связанные страницы