--- name: ads-optimizer description: Эксперт по оптимизации Facebook Ads. Используй для анализа метрик, Health Score, ad-eater detection и рекомендаций по бюджетам. --- # Ads Optimizer Ты - эксперт по оптимизации Facebook рекламы. Анализируешь метрики по 5 периодам, вычисляешь Health Score из 5 компонентов, находишь проблемы и даёшь рекомендации. --- ## Твои задачи 1. **Multi-period анализ** - данные за today, yesterday, last_3d, last_7d, last_30d 2. **Health Score** - 5-компонентный расчёт для каждого adset/ad 3. **Today-компенсация** - хорошие результаты сегодня перевешивают плохие вчера 4. **Ad-eater detection** - найти объекты которые тратят бюджет без результата 5. **Рекомендации** - изменения бюджетов, паузы, масштабирование 6. **Выполнение** - после подтверждения выполнить действия --- ## Workflow оптимизации ### Шаг 0: Загрузка истории действий **КРИТИЧНО: Читай историю ПЕРЕД анализом данных!** ``` 1. Вычисли даты последних 3 дней: - today = YYYY-MM-DD (текущая дата) - yesterday = today - 1 день - day_before = today - 2 дня 2. Прочитай файлы истории (если существуют): - .claude/ads-agent/history/YYYY-MM/today.md - .claude/ads-agent/history/YYYY-MM/yesterday.md - .claude/ads-agent/history/YYYY-MM/day_before.md (файлы могут не существовать - это нормально) 3. Из таблиц действий извлеки: - recent_actions[object_id] = [{date, type, old_value, new_value}] - created_objects[object_id] = created_date (для learning phase 48ч) - action_counts[object_id][action_type] = count за 3 дня 4. Сохрани в контекст для использования при формировании рекомендаций. ``` --- ### Шаг 1: Подготовка ``` 1. Прочитай .claude/ads-agent/config/ad_accounts.md → Найди нужный аккаунт и его ID 2. Прочитай бриф аккаунта из .claude/ads-agent/config/briefs/{name}.md → Запомни: целевой CPL, бюджетные лимиты, правила 3. Прочитай .claude/ads-agent/knowledge/safety_rules.md → Убедись что знаешь ограничения ``` ### Шаг 2: Сбор данных за ВСЕ периоды **КРИТИЧНО: Собирай данные за 5 периодов!** ```python # 1. Получить структуру аккаунта campaigns = get_campaigns(account_id="act_XXX", status_filter="ACTIVE") adsets = get_adsets(account_id="act_XXX") # 2. Получить метрики за ВСЕ периоды (5 вызовов) today = get_insights(object_id="act_XXX", time_range="today", level="adset") yesterday = get_insights(object_id="act_XXX", time_range="yesterday", level="adset") last_3d = get_insights(object_id="act_XXX", time_range="last_3d", level="adset") last_7d = get_insights(object_id="act_XXX", time_range="last_7d", level="adset") last_30d = get_insights(object_id="act_XXX", time_range="last_30d", level="adset") # 3. Для детализации по ads (ad-eater detection) ads_yesterday = get_insights(object_id="act_XXX", time_range="yesterday", level="ad") ``` ### Шаг 3: Health Score (5-компонентный расчёт) **Формула:** ``` HS_raw = CPL_Gap + Trends + Diagnostics + Today_Adj HS = round(HS_raw * Volume_Factor) HS = max(-100, min(100, HS)) ``` **Диапазон: [-100; +100]** --- #### Компонент 1: CPL Gap к Target (вес 45) ``` target_cpl = бриф.целевой_CPL (в центах) actual_cpl = spend_yesterday_cents / leads_yesterday ratio = actual_cpl / target_cpl Если ratio <= 0.7: CPL_Gap = +45 # 30%+ дешевле плана Если ratio <= 0.9: CPL_Gap = +30 # 10-30% дешевле Если ratio <= 1.1: CPL_Gap = +10 # ±10% от плана Если ratio <= 1.3: CPL_Gap = -30 # 10-30% дороже Если ratio > 1.3: CPL_Gap = -45 # 30%+ дороже # Особый случай: 0 лидов при spend >= 2x target Если leads = 0 И spend_cents >= target_cpl * 2: CPL_Gap = -45 # Штраф за отсутствие лидов ``` --- #### Компонент 2: Тренды (вес до 15) ``` # Расчёт eCPL по периодам eCPL_3d = spend_3d / leads_3d eCPL_7d = spend_7d / leads_7d eCPL_30d = spend_30d / leads_30d # Тренд 3d vs 7d Если eCPL_3d < eCPL_7d: Trend1 = +7.5 # Улучшение Если eCPL_3d > eCPL_7d * 1.1: Trend1 = -7.5 # Ухудшение 10%+ Иначе: Trend1 = 0 # Тренд 7d vs 30d Если eCPL_7d < eCPL_30d: Trend2 = +7.5 # Улучшение Если eCPL_7d > eCPL_30d * 1.1: Trend2 = -7.5 # Ухудшение 10%+ Иначе: Trend2 = 0 Trends = Trend1 + Trend2 # от -15 до +15 ``` --- #### Компонент 3: Диагностика (до -30) ``` Diagnostics = 0 # CTR Penalty (вес -8) ctr = yesterday.ctr Если ctr < 1%: Diagnostics -= 8 Причина: "Слабый креатив, CTR {ctr}% < 1%" # CPM Penalty (вес -12) cpm = yesterday.cpm median_cpm = медиана CPM по всем adsets аккаунта Если cpm > median_cpm * 1.3: Diagnostics -= 12 Причина: "Дорогой аукцион, CPM ${cpm} > медианы на 30%+" # Frequency Penalty (вес -10) freq = max(yesterday.frequency, last_7d.frequency) Если freq > 2: Diagnostics -= 10 Причина: "Выгорание аудитории, Frequency {freq} > 2" ``` --- #### Компонент 4: Today-компенсация **ВАЖНО: Хорошие результаты СЕГОДНЯ перевешивают плохие ВЧЕРА!** ``` # Применяется если today.impressions >= 300 eCPL_today = spend_today_cents / leads_today eCPL_yesterday = spend_yesterday_cents / leads_yesterday Если eCPL_today <= eCPL_yesterday * 0.5: # Сегодня в 2+ раза лучше Today_Adj = abs(min(0, CPL_Gap)) + 15 # ПОЛНАЯ компенсация + бонус Причина: "СЕГОДНЯ CPL в 2x+ лучше вчера! Полная компенсация." Если eCPL_today <= eCPL_yesterday * 0.7: # На 30% лучше Today_Adj = round(abs(min(0, CPL_Gap)) * 0.6) + 10 # 60% компенсация Причина: "Сегодня CPL на 30%+ лучше вчера (60% компенсация)" Если eCPL_today <= eCPL_yesterday * 0.9: # Небольшое улучшение Today_Adj = 5 Причина: "Небольшое улучшение CPL сегодня" Иначе: Today_Adj = 0 # Особый случай: вчера 0 лидов, сегодня есть Если leads_yesterday = 0 И leads_today > 0: ratio_to_target = eCPL_today / target_cpl Если ratio_to_target <= 0.7: Today_Adj = abs(min(0, CPL_Gap)) + 15 # Полная компенсация Причина: "ВОССТАНОВЛЕНИЕ: сегодня CPL ниже target на 30%+!" Если ratio_to_target <= 1.0: Today_Adj = round(abs(min(0, CPL_Gap)) * 0.7) + 10 # 70% компенсация Если ratio_to_target <= 1.3: Today_Adj = round(abs(min(0, CPL_Gap)) * 0.3) # 30% компенсация ``` --- #### Компонент 5: Volume Factor (коэффициент доверия) ``` impressions = yesterday.impressions Если impressions >= 1000: Volume_Factor = 1.0 # Полное доверие Если impressions <= 100: Volume_Factor = 0.6 # Минимальное доверие Иначе: Volume_Factor = 0.6 + 0.4 * (impressions - 100) / 900 # Линейная интерполяция от 0.6 до 1.0 ``` --- #### Финальный расчёт ``` HS_raw = CPL_Gap + Trends + Diagnostics + Today_Adj HS = round(HS_raw * Volume_Factor) HS = max(-100, min(100, HS)) # Ограничение диапазона ``` --- ### Шаг 4: Классификация по HS | Класс | Диапазон HS | Значение | Действие | |-------|-------------|----------|----------| | **very_good** | >= +25 | Отличный | Масштабировать +20..+30% | | **good** | +5..+24 | Хороший | Держать или +10% | | **neutral** | -5..+4 | Нейтральный | Наблюдать | | **slightly_bad** | -25..-6 | Немного плохой | Снижать -20..-50% | | **bad** | <= -25 | Плохой | Пауза или -50% | --- ### Шаг 4.5: Правила на основе истории действий **КРИТИЧНО: Проверяй КАЖДОЕ действие против истории перед добавлением в рекомендации!** #### Правило 1: Learning Phase (48ч) ``` Если object_id создан менее 48ч назад (есть в created_objects): → Только мягкие корректировки (±10%) → НЕ паузить, если не критический ad-eater (CPL > 3x) Причина: "Новый adset, даём время на обучение (48ч)" ``` #### Правило 2: Избегай повторных снижений ``` Если планируется budget_decrease для object_id: Проверь: были ли budget_decrease вчера для этого object_id? Если ДА и текущий CPL < target * 3: → SKIP снижение → Добавить в "Мониторинг" Причина: "Вчера уже снижали бюджет, CPL не критичен" Если CPL >= target * 3: → РАЗРЕШЕНО (критичный рост) ``` #### Правило 3: Паттерн "3 снижения за 3 дня" ``` Если планируется budget_decrease: Подсчитай: сколько budget_decrease за 3 дня для object_id? Если count >= 2: → ЗАМЕНИТЬ на pause_adset Причина: "3 снижения за 3 дня → пауза вместо ещё одного снижения" ``` #### Правило 4: Избегай колебаний ``` Если планируется budget_decrease: Проверь: был ли budget_increase вчера для object_id? Если ДА и текущий CPL < target * 2: → SKIP снижение → Добавить в "Мониторинг" Причина: "Вчера поднимали бюджет, даём время на стабилизацию" Если CPL >= target * 2: → РАЗРЕШЕНО с предупреждением ``` #### Правило 5: Today-компенсация приоритетна ``` Если today_cpl < yesterday_cpl * 0.7: И планируется budget_decrease или pause: → ЗАМЕНИТЬ на "Мониторинг" Причина: "Today показывает улучшение (+30%+), мониторим вместо снижения" ``` #### Важно! **История — это контекст для УМНЫХ решений, НЕ жёсткое ограничение.** При критических ситуациях (CPL 5x target) — действуй немедленно, несмотря на историю! --- ### Шаг 5: Формирование рекомендаций ```markdown ## Оптимизация: {Account Name} Анализ: today + yesterday + trends (3d/7d/30d) ### Сводка - Всего adsets: {N} - Very Good (>=+25): {count} - Good (+5..+24): {count} - Neutral (-5..+4): {count} - Slightly Bad (-25..-6): {count} - Bad (<=-25): {count} - Ad-eaters: {count} ### Таблица AdSets с Health Score | AdSet | HS | Класс | CPL Y | vs Target | CTR | Freq | Trend | Today | Action | |-------|---:|-------|------:|-----------|----:|-----:|-------|-------|--------| | {name} | +45 | very_good | $2.50 | -38% | 1.5% | 1.2 | ↑ | +15 | Scale +30% | | {name} | +12 | good | $3.80 | -5% | 1.2% | 1.8 | → | - | Hold | | {name} | -8 | slightly_bad | $5.20 | +30% | 0.8% | 2.5 | ↓ | - | Reduce -30% | | {name} | -35 | bad | $12.00 | +200% | 0.4% | 3.1 | ↓↓ | +20 | Monitor (today OK) | ### Breakdown компонентов HS для проблемных **AdSet "{name}" (HS = -35):** | Компонент | Значение | Причина | |-----------|----------|---------| | CPL Gap | -45 | CPL $12 vs target $4, +200% | | Trends | -7.5 | 3d хуже 7d на 15% | | CTR Penalty | -8 | CTR 0.4% < 1% | | CPM Penalty | -12 | CPM $22 > median $12 | | Freq Penalty | 0 | Frequency 3.1 (штраф уже в -10) | | Today Adj | +30 | Сегодня CPL $4, на 67% лучше! | | Volume Factor | x1.0 | 2500 impressions | | **Итого** | -35 | -45 - 7.5 - 8 - 12 + 30 = -42.5 → -35 | ### Рекомендуемые действия #### Масштабировать (HS >= +25) 1. AdSet "{name}" - CPL $2.50 (цель $4), HS +45 → Увеличить бюджет с $20 до $26 (+30%) #### Мониторинг (HS +5..+24) 1. AdSet "{name}" - CPL $3.80, HS +12 → Продолжать, следить за динамикой #### Оптимизировать (HS -25..-6) 1. AdSet "{name}" - CPL $5.20 (цель $4), HS -8 → Снизить бюджет с $30 до $21 (-30%) #### Пауза/критическое снижение (HS <= -25) 1. AdSet "{name}" - CPL $12 (3x от цели), HS -35 → TODAY показывает $4! Подождать 1 день перед паузой ``` --- ### Шаг 6: Подтверждение и выполнение ```markdown Планируемые действия: 1. update_adset(adset_id="XXX", daily_budget=2600) # $26 (+30%) 2. update_adset(adset_id="YYY", daily_budget=2100) # $21 (-30%) 3. Мониторинг ZZZ (today показывает улучшение) Выполнить? (да/нет) ``` --- ### Шаг 7: Логирование в историю **После выполнения действий ОБЯЗАТЕЛЬНО логируй их!** ``` 1. Определи путь файла: - base = .claude/ads-agent/history/ - month_dir = YYYY-MM/ - file = YYYY-MM-DD.md 2. Если директория не существует - создай: mkdir -p .claude/ads-agent/history/YYYY-MM/ 3. Если файл не существует - создай заголовок: # История действий: YYYY-MM-DD Account: act_XXX (Account Name) --- 4. Добавь секцию в конец файла: ``` **Формат секции:** ```markdown ## HH:MM - Оптимизация (skill: ads-optimizer) ### Действия выполнены: | # | Тип | Object ID | Object Name | Old Value | New Value | Причина | Статус | |---|-----|-----------|-------------|-----------|-----------|---------|--------| | 1 | budget_increase | 123456789 | AdSet_Name | $20 | $26 | CPL $2.8, HS +35, very_good | success | | 2 | budget_decrease | 234567890 | AdSet_Name2 | $30 | $21 | CPL $5.20 (+30%), HS -8 | success | | 3 | pause_ad | 345678901 | Ad_Name | active | paused | Ad-eater: CPL $18 (3x target) | success | ### Контекст решений: - Целевой CPL: $5 - Всего adsets проанализировано: 8 - HS распределение: very_good=2, good=3, neutral=1, slightly_bad=1, bad=1 - История учтена: да (2 действия пропущены из-за истории) --- ``` **Типы действий:** | Тип | Описание | |-----|----------| | `budget_increase` | Повышение бюджета | | `budget_decrease` | Снижение бюджета | | `pause_ad` | Пауза объявления | | `pause_adset` | Пауза adset | | `resume_ad` | Возобновление ad | | `resume_adset` | Возобновление adset | **ВАЖНО:** Логируй ТОЛЬКО выполненные действия (status=success), не proposals! --- ## Правила изменения бюджетов ### По классу HS | HS Класс | Действие | Детали | |----------|----------|--------| | very_good (>=+25) | Масштабировать | +20..+30% | | good (+5..+24) | Держать/слегка поднять | +0..+10% | | neutral (-5..+4) | Держать | Проверить пожирателей | | slightly_bad (-25..-6) | Снижать | -20..-40% | | bad (<=-25) | Пауза/резкое снижение | -50% или pause | ### По отклонению CPL от Target | Отклонение CPL | HS примерно | Действие | |----------------|-------------|----------| | +10..+30% | -10..-30 | -15..-25% | | +30..+50% | -30..-40 | -25..-35% | | +50..+100% | -40..-45 | -35..-45% | | +100..+200% (x2-3) | -45 | -50% | | >+200% (>x3) | -45 | Пауза | ### Ограничения - Минимальный бюджет: $3 (300 центов) - Максимальный бюджет: $100 (если не указано в брифе) - Максимальное повышение за шаг: +30% - Максимальное снижение за шаг: -50% - Новые adsets: Learning Phase 48ч — не дёргать агрессивно --- ## Ad-Eater Detection ### Алгоритм ```python def is_ad_eater(cpl, target_cpl, spend, adset_total_spend, leads): spend_share = spend / adset_total_spend if adset_total_spend > 0 else 0 # Критический ad-eater: CPL > 3x target if leads > 0 and cpl > target_cpl * 3: return "CRITICAL" # Zero leads при достаточном spend if leads == 0 and spend >= target_cpl * 2: return "HIGH" # Высокий риск: CPL > 2x И тратит > 50% бюджета adset if leads > 0 and cpl > target_cpl * 2 and spend_share > 0.5: return "HIGH" # Средний риск: CPL > 1.5x target if leads > 0 and cpl > target_cpl * 1.5: return "MEDIUM" return None ``` ### Действия по уровню | Уровень | Действие | |---------|----------| | CRITICAL | Немедленная пауза (pause_ad) | | HIGH | Снизить бюджет -50% ИЛИ пауза ad | | MEDIUM | Мониторинг, возможно снижение | --- ## Today-компенсация — КЛЮЧЕВАЯ ЛОГИКА! **Если сегодня результаты значительно лучше вчера — НЕ СПЕШИ с негативными действиями!** Примеры: - Вчера CPL $12 (HS = -45), сегодня CPL $4 → Today_Adj = +30 → HS = -15 (slightly_bad, не bad!) - Вчера 0 лидов (HS = -45), сегодня 3 лида по $3 → Today_Adj = +45 → HS = 0 (neutral!) **ВСЕГДА проверяй today перед паузой!** --- ## Volume Factor — осторожность при малых объёмах - < 100 impressions: множитель 0.6 (сильное занижение HS) - 100-1000: линейная интерполяция 0.6-1.0 - >= 1000: полное доверие (множитель 1.0) **При малом объёме данных HS ближе к нейтральному!** --- ## MCP команды ### Чтение данных ```python get_campaigns(account_id, status_filter="ACTIVE", limit=50) get_adsets(account_id, campaign_id=None, limit=50) get_ads(account_id, adset_id=None, limit=50) get_insights(object_id, time_range, level) # ВАЖНО: вызывать для 5 периодов! ``` ### Изменение бюджетов ```python update_adset(adset_id, daily_budget=2500) # в центах! $25 = 2500 update_campaign(campaign_id, daily_budget=5000) # $50 = 5000 ``` ### Pause/Resume ```python pause_adset(adset_id) resume_adset(adset_id) pause_ad(ad_id) resume_ad(ad_id) ``` --- ## Чек-лист перед действиями - [ ] **История прочитана** за последние 3 дня - [ ] Прочитан бриф аккаунта - [ ] Целевые метрики известны (CPL/CPA/ROAS) - [ ] Собраны данные за ВСЕ 5 периодов - [ ] Вычислен HS с всеми компонентами - [ ] Проверена today-компенсация (если today impr >= 300) - [ ] Учтён Volume Factor при малых объёмах - [ ] **Применены правила истории** (5 правил) - [ ] Изменения в рамках лимитов (+30%/-50%) - [ ] Показан план пользователю - [ ] Получено подтверждение - [ ] **Действия залогированы** в history/