From c586cb7b9fde27d6c4dfc1b8add97f91e2b1e450 Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 19 Aug 2026 12:11:10 +0300 Subject: [PATCH] Replace the Apple-vs-Adapty install gap with a standard metric set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The install comparison was noise that read like a finding. It put two numbers from different attribution models and different event definitions side by side, then disclaimed that the difference meant nothing and that nobody would investigate it — while occupying a headline section in both the weekly check-in and the account-health audit. Remove it from every skill, playbook, command, doc and translation. Each of the three workflow files now carries an explicit non-goal sentence instead, and lint-workflows forbids `adapty_installs`, `absolute_gap`, `relative_gap` and the attribution disclaimer so it cannot creep back. In its place, both reporting workflows report one fixed metric set: spend, impressions, taps, avg_cpt, total_installs, total_avg_cpi, cost_per_trial and cost_per_paid. The weekly review previously requested only four metrics; the rest ride the same single `metrics overview` call, so the four-call and three-call budgets are unchanged. The linter requires all eight names in both playbooks and in the /asa-review command. CPI is Apple's own `total_avg_cpi` field, read rather than computed. It counts redownloads, and the benchmarks skill publishes spend per download under the name CPA and forbids aliasing the two — both playbooks now warn against comparing them without checking the denominator. cost_per_trial is gated on a new required input: whether the app offers a free trial. When it does not, the row is dropped and the metric is not offered as a success metric. `asa-metrics.md` is untouched — it is generated, and `adapty_installs` remains a valid CLI metric. Only the workflow built on its difference from Apple's count is gone. Co-Authored-By: Claude Opus 5 (1M context) --- .claude-plugin/plugin.json | 2 +- README.md | 2 +- README.tr.md | 4 +- README.zh-CN.md | 4 +- commands/asa-audit.md | 4 +- commands/asa-review.md | 25 +++-- docs/IMPROVEMENT-IDEAS.md | 5 +- docs/playbooks/README.md | 2 +- docs/playbooks/README.tr.md | 2 +- docs/playbooks/README.zh-CN.md | 2 +- examples/prompts.md | 2 +- scripts/lint-workflows.mjs | 38 +++++-- skills/apple-ads-audit/SKILL.md | 23 ++-- skills/apple-ads-audit/references/INDEX.md | 2 +- .../references/playbooks/account-health.md | 66 +++++++----- .../references/playbooks/bid-optimization.md | 7 +- .../references/playbooks/weekly-review.md | 100 +++++++++++------- 17 files changed, 176 insertions(+), 114 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 517b78a..057ff0f 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "apple-ads", - "version": "0.2.1", + "version": "0.3.0", "description": "Run and audit Apple Ads from your agent — cohort bid reviews, Market Intelligence keyword opportunities, search-term harvesting, negatives, CPP routing, and read-only account diagnostics through the Adapty CLI.", "author": { "name": "Adapty", "email": "support@adapty.io" }, "homepage": "https://adapty.io/docs/developer-cli-ads-manager-skill", diff --git a/README.md b/README.md index 56db71f..426f090 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Settings → Capabilities → enable code execution → allow network egress → | | | |---|---| | **`apple-ads`** | The operator. Reads performance, changes bids and budgets, adds keywords and negatives, harvests search terms, launches and pauses campaigns — all through the CLI, with confirmation before anything that spends money. | -| **`apple-ads-audit`** | The read-only auditor. Checks account health, serving, live structure, traffic ownership, duplicate Exact keywords, and a simple same-window Apple-versus-Adapty install comparison. It never writes. | +| **`apple-ads-audit`** | The read-only auditor. Checks account health, serving, live structure, traffic ownership, duplicate Exact keywords, and a performance snapshot — spend, impressions, taps, avg CPT, installs, CPI, cost per trial and cost per paid. It never writes. | | **`apple-ads-strategy`** | The planner. **Needs no account, no CLI, no subscription.** Turns "I have a TV remote app, where do I start" into a full account structure, keyword taxonomy, starting budget and negative list. | | **Playbooks** | Weekly check-in · account health · structure audit · cohort ROAS · keyword bid review · Market Intelligence keyword opportunities · search-term harvesting · negative keyword mining · CPP routing · budget reallocation · campaign launch · runaway spend · automation rules. | | **Vertical guides** | Category-specific playbooks — demand profile, keyword taxonomy, account structure, starting economics and the failure modes specific to that category. | diff --git a/README.tr.md b/README.tr.md index dd505a8..6c2df25 100644 --- a/README.tr.md +++ b/README.tr.md @@ -1,4 +1,4 @@ - + [English](README.md) · [简体中文](README.zh-CN.md) · **Türkçe** @@ -73,7 +73,7 @@ Ayarlar → Capabilities → kod çalıştırmayı etkinleştirin → ağ çık | | | |---|---| | **`apple-ads`** | Uygulayıcı. Performansı okur, teklifleri ve bütçeleri değiştirir, anahtar kelime ve negatif ekler, arama terimlerini hasat eder, kampanyaları başlatır ve durdurur — hepsi CLI üzerinden ve para harcayan her işlemden önce onay alarak. | -| **`apple-ads-audit`** | Salt okunur denetçi. Hesap sağlığını, yayın durumunu, canlı yapıyı, trafik sahipliğini, yinelenen tam eşleşmeli anahtar kelimeleri ve aynı tarih aralığında Apple ile Adapty kurulumlarının basit karşılaştırmasını kontrol eder. Hiçbir şeyi değiştirmez. | +| **`apple-ads-audit`** | Salt okunur denetçi. Hesap sağlığını, yayın durumunu, canlı yapıyı, trafik sahipliğini, yinelenen tam eşleşmeli anahtar kelimeleri ve bir performans özetini — harcama, gösterim, dokunma, ortalama CPT, yükleme, CPI, deneme başına maliyet ve ödeme başına maliyet — kontrol eder. Hiçbir şeyi değiştirmez. | | **`apple-ads-strategy`** | Planlayıcı. **Hesap, CLI veya abonelik gerektirmez.** "Bir TV kumandası uygulamam var, nereden başlamalıyım" sorusunu eksiksiz bir hesap yapısına, anahtar kelime taksonomisine, başlangıç bütçesine ve negatif listesine dönüştürür. | | **Oyun kitapları** | Haftalık kontrol · hesap sağlığı · yapı denetimi · kohort ROAS · anahtar kelime teklif incelemesi · Market Intelligence fırsatları · arama terimi hasadı · negatif anahtar kelime madenciliği · CPP yönlendirme · bütçe yeniden dağıtımı · kampanya başlatma · kontrolsüz harcama · otomasyon kuralları. | | **Dikey rehberler** | Kategoriye özel oyun kitapları — talep profili, anahtar kelime taksonomisi, hesap yapısı, başlangıç ekonomisi ve o kategoriye özgü başarısızlık biçimleri. | diff --git a/README.zh-CN.md b/README.zh-CN.md index 3ff5722..05475b2 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,4 +1,4 @@ - + [English](README.md) · **简体中文** · [Türkçe](README.tr.md) @@ -73,7 +73,7 @@ Cowork 在沙箱中执行命令,只能访问白名单域名。安装前请** | | | |---|---| | **`apple-ads`** | 执行层。读取投放表现、调整出价与预算、添加关键词与否定词、收割搜索词、启动与暂停广告系列 —— 全部通过 CLI 完成,任何花钱的操作前都会先确认。 | -| **`apple-ads-audit`** | 只读审计层。检查账户健康、投放状态、线上结构、流量归属、重复的精确匹配关键词,并在同一时间范围内简单比较 Apple 与 Adapty 的安装量。绝不执行写操作。 | +| **`apple-ads-audit`** | 只读审计层。检查账户健康、投放状态、线上结构、流量归属、重复的精确匹配关键词,并给出一份性能快照——花费、展示、点击、平均 CPT、安装量、CPI、单次试用成本和单次付费成本。绝不执行写操作。 | | **`apple-ads-strategy`** | 规划层。**不需要账号、不需要 CLI、不需要订阅。** 把「我有一个电视遥控器 App,该从哪儿开始」变成完整的账户结构、关键词分类、启动预算和否定词清单。 | | **操作手册** | 每周检查 · 账户健康 · 结构审计 · 同期群 ROAS · 关键词出价审查 · Market Intelligence 关键词机会 · 搜索词收割 · 否定关键词挖掘 · CPP 路由 · 预算再分配 · 广告系列启动 · 超支应急 · 自动化规则。 | | **垂类指南** | 分品类的操作手册 —— 需求画像、关键词分类、账户结构、启动期经济模型,以及该品类特有的失败模式。 | diff --git a/commands/asa-audit.md b/commands/asa-audit.md index d59436a..9cf6ac8 100644 --- a/commands/asa-audit.md +++ b/commands/asa-audit.md @@ -4,8 +4,8 @@ description: Read-only Apple Ads account health or live structure audit Audit my connected Apple Ads account without changing anything. -Use the `apple-ads-audit` skill and run its preflight. Route a broad health, serving, performance, -or Apple-versus-Adapty installs question to `references/playbooks/account-health.md`. Route live +Use the `apple-ads-audit` skill and run its preflight. Route a broad health, serving, or performance +question to `references/playbooks/account-health.md`. Route live structure, duplicate Exact ownership, or missing cross-negatives to `references/playbooks/structure-audit.md`. Read one primary playbook, return evidence and confidence, and stop before every mutation. diff --git a/commands/asa-review.md b/commands/asa-review.md index cad8cf0..afee3f9 100644 --- a/commands/asa-review.md +++ b/commands/asa-review.md @@ -1,22 +1,27 @@ --- -description: Weekly Apple Ads check-in — direction, install comparison, outliers, and one action +description: Weekly Apple Ads check-in — the standard metric set, outliers, and one action --- Run the weekly check-in for my Apple Ads account. Use the `apple-ads` skill. Start with `references/playbooks/preflight.md`, then follow `references/playbooks/weekly-review.md` exactly — including its call budget. Ask me for the date -range if I did not give one and whether I want a comparison. If I did not name a success metric, -offer these choices in this exact order: +range if I did not give one and whether I want a comparison. Ask whether the app offers a free trial +before you offer a success metric. If I did not name a success metric, offer these choices in this +exact order: 1. Cost per paid 2. Cost per trial 3. Net ROAS at day X -Ask for my numeric target or guardrail after the metric is selected. Always use net values for -revenue-family metrics; never offer gross or proceeds. Ask for a cohort day only when the selected -metric is `revenue`, `roas`, `arpu`, `arppu`, `arpas`, or `roi`. Never ask for a cohort window, pass -`--by-days` / `--order-by-day`, or label a result `day-X` for `cost_per_paid`, `cost_per_trial`, or -any other non-cohort metric. Include the same-window Apple total installs versus Adapty installs -comparison, up to two positive changes, up to two concerns, and one primary action. Do not -investigate attribution and do not write. +Skip choice 2 when I said the app has no free trial. Ask for my numeric target or guardrail after the +metric is selected. Always use net values for revenue-family metrics; never offer gross or proceeds. +Ask for a cohort day only when the selected metric is `revenue`, `roas`, `arpu`, `arppu`, `arpas`, or +`roi`. Never ask for a cohort window, pass `--by-days` / `--order-by-day`, or label a result `day-X` +for `cost_per_paid`, `cost_per_trial`, or any other non-cohort metric. + +Report the playbook's standard metric set for the requested window — `spend`, `impressions`, `taps`, +`avg_cpt`, `total_installs`, `total_avg_cpi`, `cost_per_trial` when the app has a trial, and +`cost_per_paid` — with the prior value and signed delta per row when I asked for a comparison. Then +give up to two positive changes, up to two concerns, and one primary action. Do not investigate +attribution and do not write. diff --git a/docs/IMPROVEMENT-IDEAS.md b/docs/IMPROVEMENT-IDEAS.md index ccc5277..ea3d59c 100644 --- a/docs/IMPROVEMENT-IDEAS.md +++ b/docs/IMPROVEMENT-IDEAS.md @@ -40,8 +40,8 @@ Minimum case set: - one successful case for each of the eight flagship workflows; - one insufficient-data case for each workflow; - audit versus operator versus strategy routing conflicts; -- Apple installs equal to zero; -- missing Adapty installs; +- a metric missing from a `metrics overview` response; +- `cost_per_trial` requested for an app with no free trial; - Market Intelligence response without `byApps`; - more than five competitor App Store ids; - an opportunity already present as an active keyword; @@ -298,6 +298,7 @@ Do not add these until a concrete product need changes the decision: - more top-level skills; - a Maximize readiness workflow; +- any comparison between Apple install counts and Adapty install counts; - deep attribution reconciliation; - a universal account health score; - universal CPA, ROAS, or bid-change percentages; diff --git a/docs/playbooks/README.md b/docs/playbooks/README.md index 4bd2b82..40adcae 100644 --- a/docs/playbooks/README.md +++ b/docs/playbooks/README.md @@ -10,7 +10,7 @@ The authoritative copies live under `skills/`, and these are generated from them | Account health | what needs attention in a live account, without changing it | [`account-health.md`](../../skills/apple-ads-audit/references/playbooks/account-health.md) | | Structure audit | duplicate ownership, cross-negatives and live hierarchy conflicts | [`structure-audit.md`](../../skills/apple-ads-audit/references/playbooks/structure-audit.md) | | Cohort ROAS | which keywords actually pay back, by renewal window | [`cohort-roas.md`](../../skills/apple-ads/references/playbooks/cohort-roas.md) | -| Weekly check-in | direction, install comparison, outliers and one action in at most four analytics calls | [`weekly-review.md`](../../skills/apple-ads/references/playbooks/weekly-review.md) | +| Weekly check-in | direction on the standard metric set, outliers and one action in at most four analytics calls | [`weekly-review.md`](../../skills/apple-ads/references/playbooks/weekly-review.md) | | Keyword opportunities | per-app, per-country competitor terms from Market Intelligence | [`keyword-opportunity.md`](../../skills/apple-ads/references/playbooks/keyword-opportunity.md) | | Keyword bid review | evidence-based bid changes with cohort maturity gates | [`bid-optimization.md`](../../skills/apple-ads/references/playbooks/bid-optimization.md) | | Search-term harvesting | turn real queries into verified Exact owners and cross-negatives | [`search-term-harvesting.md`](../../skills/apple-ads/references/playbooks/search-term-harvesting.md) | diff --git a/docs/playbooks/README.tr.md b/docs/playbooks/README.tr.md index f932839..03ec348 100644 --- a/docs/playbooks/README.tr.md +++ b/docs/playbooks/README.tr.md @@ -10,7 +10,7 @@ Yetkili kopyalar `skills/` altındadır; bu sayfa onlardan üretilir. | Hesap sağlığı | canlı bir hesapta hiçbir şeyi değiştirmeden ilgilenilmesi gerekenleri bulma | [`account-health.md`](../../skills/apple-ads-audit/references/playbooks/account-health.md) | | Yapı denetimi | yinelenen sahiplik, çapraz negatifler ve canlı hiyerarşi çatışmaları | [`structure-audit.md`](../../skills/apple-ads-audit/references/playbooks/structure-audit.md) | | Kohort ROAS | hangi anahtar kelimelerin gerçekten kâr getirdiği, yenileme penceresine göre | [`cohort-roas.md`](../../skills/apple-ads/references/playbooks/cohort-roas.md) | -| Haftalık kontrol | en fazla dört analiz çağrısıyla yön, kurulum karşılaştırması, aykırı değerler ve tek eylem | [`weekly-review.md`](../../skills/apple-ads/references/playbooks/weekly-review.md) | +| Haftalık kontrol | en fazla dört analiz çağrısıyla standart metrik setinde yön, aykırı değerler ve tek eylem | [`weekly-review.md`](../../skills/apple-ads/references/playbooks/weekly-review.md) | | Anahtar kelime fırsatları | Market Intelligence'tan uygulama ve ülke bazında rakip terimleri | [`keyword-opportunity.md`](../../skills/apple-ads/references/playbooks/keyword-opportunity.md) | | Teklif incelemesi | kohort olgunluk kapılarıyla kanıta dayalı teklif değişiklikleri | [`bid-optimization.md`](../../skills/apple-ads/references/playbooks/bid-optimization.md) | | Arama terimi hasadı | gerçek sorguları doğrulanmış tam eşleşme sahiplerine ve çapraz negatiflere dönüştürme | [`search-term-harvesting.md`](../../skills/apple-ads/references/playbooks/search-term-harvesting.md) | diff --git a/docs/playbooks/README.zh-CN.md b/docs/playbooks/README.zh-CN.md index ef161ad..8b67d7d 100644 --- a/docs/playbooks/README.zh-CN.md +++ b/docs/playbooks/README.zh-CN.md @@ -10,7 +10,7 @@ | 账户健康 | 在不做任何修改的前提下找出线上账户需要关注的问题 | [`account-health.md`](../../skills/apple-ads-audit/references/playbooks/account-health.md) | | 结构审计 | 查找重复归属、交叉否定词和线上层级冲突 | [`structure-audit.md`](../../skills/apple-ads-audit/references/playbooks/structure-audit.md) | | 同期群 ROAS | 按续订窗口判断哪些关键词真正回本 | [`cohort-roas.md`](../../skills/apple-ads/references/playbooks/cohort-roas.md) | -| 每周检查 | 最多四次分析调用,给出趋势、安装量对比、异常项和一个行动 | [`weekly-review.md`](../../skills/apple-ads/references/playbooks/weekly-review.md) | +| 每周检查 | 最多四次分析调用,基于标准指标集给出趋势、异常项和一个行动 | [`weekly-review.md`](../../skills/apple-ads/references/playbooks/weekly-review.md) | | 关键词机会 | 从 Market Intelligence 获取按 App 和国家划分的竞品搜索词 | [`keyword-opportunity.md`](../../skills/apple-ads/references/playbooks/keyword-opportunity.md) | | 关键词出价审查 | 通过同期群成熟度门槛提出基于证据的出价调整 | [`bid-optimization.md`](../../skills/apple-ads/references/playbooks/bid-optimization.md) | | 搜索词收割 | 把真实查询变成已验证的精确匹配归属和交叉否定词 | [`search-term-harvesting.md`](../../skills/apple-ads/references/playbooks/search-term-harvesting.md) | diff --git a/examples/prompts.md b/examples/prompts.md index f69fa43..ebeffa9 100644 --- a/examples/prompts.md +++ b/examples/prompts.md @@ -16,7 +16,7 @@ Structure an account for a language-learning app selling annual subscriptions in ``` Audit this live Apple Ads account and show me what needs attention. Do not change anything. Which campaigns are confirmed not to be serving, and what evidence explains each one? -How far apart are Apple total installs and Adapty installs for the same dates? Keep it simple. +Give me spend, impressions, taps, avg CPT, installs, CPI and cost per paid for last week. Are Brand, Competitor, Discovery and Exact traffic separated correctly in this live account? Where do active Exact keywords have more than one owner? Which Discovery ad groups are missing cross-negatives for verified Exact owners? diff --git a/scripts/lint-workflows.mjs b/scripts/lint-workflows.mjs index addeb59..5076590 100644 --- a/scripts/lint-workflows.mjs +++ b/scripts/lint-workflows.mjs @@ -2,7 +2,7 @@ // Behavioral contracts for the flagship Apple Ads workflows. // // The playbook linter validates shape and command existence. This file protects the decisions that -// are easy to weaken accidentally: read-only audit boundaries, simple install comparison, Market +// are easy to weaken accidentally: read-only audit boundaries, the standard metric set, Market // Intelligence detail, and mutation ordering. import { existsSync, readFileSync, readdirSync } from 'node:fs' @@ -71,8 +71,6 @@ if (setupDescription.includes('402') || setupDescription.includes('ads_manager_s } requireText(auditSkill, 'This skill has no write', 'explicit read-only audit boundary') -requireText(auditSkill, 'relative_gap = absolute_gap / apple_installs', 'install-gap formula') -requireText(auditSkill, 'only when `apple_installs > 0`', 'zero-denominator guard') const WRITE_COMMAND = /asa\s+(?:campaigns|ad-groups|ads|keywords|negative-keywords|product-pages|automations)\s+(?:create|update|add|sync|run)/ for (const path of [accountHealth, structureAudit]) { @@ -82,11 +80,37 @@ for (const path of [accountHealth, structureAudit]) { if (WRITE_COMMAND.test(uses)) fail(path, `audit playbook declares a write command in uses: ${uses}`) } +// The standard metric set. Both reporting workflows request all of it in the single overview call +// they already make, so trimming a row saves nothing and only makes the report less decidable. +const STANDARD_METRICS = [ + 'spend', + 'impressions', + 'taps', + 'avg_cpt', + 'total_installs', + 'total_avg_cpi', + 'cost_per_trial', + 'cost_per_paid', +] +const NO_INSTALL_GAP = 'Never compare Apple install counts with Adapty install counts' +const GAP_REMNANTS = [ + 'adapty_installs', + 'absolute_gap', + 'relative_gap', + 'different attribution and event definitions', +] + +for (const path of [accountHealth, weekly, reviewCommand]) { + for (const metric of STANDARD_METRICS) requireText(path, `\`${metric}\``, `standard metric ${metric}`) +} +for (const path of [accountHealth, weekly, auditSkill, reviewCommand]) { + for (const remnant of GAP_REMNANTS) forbidText(path, remnant, `install-gap remnant: ${remnant}`) +} +for (const path of [accountHealth, weekly, auditSkill]) { + requireText(path, NO_INSTALL_GAP, 'explicit install-gap non-goal') +} for (const path of [accountHealth, weekly]) { - requireText(path, 'total_installs', 'Apple install metric') - requireText(path, 'adapty_installs', 'Adapty install metric') - requireText(path, 'only when', 'zero-safe percentage rule') - requireText(path, 'different attribution and event definitions', 'plain install-gap explanation') + requireText(path, 'whether the app offers a free trial', 'free-trial gate for cost_per_trial') } if (frontmatterValue(read(weekly), 'risk') !== 'read-only') fail(weekly, 'weekly check-in must stay read-only') diff --git a/skills/apple-ads-audit/SKILL.md b/skills/apple-ads-audit/SKILL.md index 769f1fe..2c3307d 100644 --- a/skills/apple-ads-audit/SKILL.md +++ b/skills/apple-ads-audit/SKILL.md @@ -1,6 +1,6 @@ --- name: apple-ads-audit -description: 'Use for read-only diagnostics of a connected Apple Ads account: account health, live campaign and ad-group structure, traffic ownership, duplicate exact keywords, missing cross-negatives, serving problems, spend without results, or a simple same-window comparison of Apple total installs and Adapty installs. Triggers on "audit my Apple Ads account", "what is broken", "which campaigns need attention", "is my live structure correct", or "why are Apple and Adapty installs different". Never use it to design a new account, run a weekly review, or make changes.' +description: 'Use for read-only diagnostics of a connected Apple Ads account: account health, live campaign and ad-group structure, traffic ownership, duplicate exact keywords, missing cross-negatives, serving problems, spend without results, or a standard performance snapshot of spend, impressions, taps, avg CPT, installs, CPI, cost per trial and cost per paid. Triggers on "audit my Apple Ads account", "what is broken", "which campaigns need attention", "is my live structure correct", or "which campaigns are wasting spend". Never use it to design a new account, run a weekly review, or make changes.' license: MIT --- @@ -33,7 +33,7 @@ Run `adapty asa whoami` first in every session. Open `references/INDEX.md` and read the one playbook it names. -- Overall health, serving, performance warnings, or Apple-versus-Adapty installs → +- Overall health, serving, performance warnings, or a performance snapshot → `references/playbooks/account-health.md`. - Live structure, duplicate targets, traffic ownership, or missing cross-negatives → `references/playbooks/structure-audit.md`. @@ -103,19 +103,16 @@ Use `critical` only for a confirmed serving failure or a user-defined limit that breached. Use `attention` for a supported concern without that proof. Never invent a numeric health score or universal threshold. -## Simple install comparison +## Standard performance snapshot -This is the entire attribution scope of this skill: +Every performance read in this skill reports one metric set for the requested scope and exact date +window: spend, impressions, taps, avg CPT, installs, CPI, cost per trial, and cost per paid. The +metric names, the free-trial gate on cost per trial, and the missing-value rule live in +`references/playbooks/account-health.md`. Use that set instead of picking metrics per question. -- Compare `total_installs` from Apple with `adapty_installs` from Adapty for the same scope and exact - date window. -- Show both values and `absolute_gap = apple_installs - adapty_installs`. -- Show `relative_gap = absolute_gap / apple_installs` only when `apple_installs > 0`. -- If either value is absent, mark the comparison `unknown`. If Apple installs are zero, say the - percentage is undefined. -- Explain plainly that the systems use different attribution and event definitions, so an exact - match is not expected. -- Do not diagnose attribution, assign fault, or claim a cause. +Attribution is not in scope. Never compare Apple install counts with Adapty install counts, never +report a gap or a percentage of Apple's count between them, and never offer an attribution +explanation for a difference between two systems. ## Evidence and confidence diff --git a/skills/apple-ads-audit/references/INDEX.md b/skills/apple-ads-audit/references/INDEX.md index f6e7e1f..082f272 100644 --- a/skills/apple-ads-audit/references/INDEX.md +++ b/skills/apple-ads-audit/references/INDEX.md @@ -5,7 +5,7 @@ and output contract. | The user is asking | Open | |---|---| -| Is the live account healthy; what is broken; which campaigns need attention; how far apart are Apple and Adapty installs | `playbooks/account-health.md` | +| Is the live account healthy; what is broken; which campaigns need attention; what did spend, taps, CPI and cost per paid do | `playbooks/account-health.md` | | Is the live structure correct; where do targets overlap; which exact owner or cross-negative is missing | `playbooks/structure-audit.md` | Do not use this skill for a weekly operating review, a future account design, or a mutation. diff --git a/skills/apple-ads-audit/references/playbooks/account-health.md b/skills/apple-ads-audit/references/playbooks/account-health.md index d2dd5a9..5c4eaf8 100644 --- a/skills/apple-ads-audit/references/playbooks/account-health.md +++ b/skills/apple-ads-audit/references/playbooks/account-health.md @@ -17,11 +17,13 @@ structure redesign, weekly ritual, or attribution investigation. - The user asks whether a connected account is healthy or what is broken. - Spend, installs, serving, or entity state looks suspicious. -- The user wants a simple same-window Apple-versus-Adapty install comparison. +- The user wants a performance snapshot for the account over a date window. - The user wants to know which campaigns deserve a deeper follow-up. ## Do not apply when +- The user asks about attribution. Never compare Apple install counts with Adapty install counts, + never report an install gap, and never explain a difference between the two systems. - The account does not exist yet → `apple-ads-strategy`. - The primary question is duplicate targeting or traffic ownership → `structure-audit.md`. - The user asks for a scheduled weekly report → `apple-ads` and `weekly-review.md`. @@ -33,6 +35,8 @@ Resolve or ask for: - company and app; - exact date window; +- whether the app offers a free trial — when the answer is no, drop the `cost_per_trial` row from the + snapshot; - the business success metric, and a cohort window only when that metric is `revenue`, `roas`, `arpu`, `arppu`, `arpas`, or `roi`, if the user wants value judgments; - any user-defined spend, CPA, or ROAS limits; @@ -47,10 +51,11 @@ bad, profitable, or unprofitable. 2. Resolve the app and requested campaign scope. 3. Read scoped campaign, ad-group, and ad counts and statuses. Use `--page-size 1` when only the count is needed. -4. Read one account overview for spend, Apple installs, Adapty installs, the requested cost metric, - and the requested cohort root. The time series supplies the trend; do not call once per period. +4. Read one account overview for the whole standard metric set below plus the requested cohort root. + The time series supplies the trend; do not call once per period. 5. Read one ranked campaign result only when the user asks which campaigns need attention. Use the - user's metric and direction, adding a cohort window only for a cohort root. + user's metric and direction, request the same standard metric set, and add a cohort window only + for a cohort root. 6. Drill into one suspicious level only when the broad evidence cannot answer the question. 7. Read `ads get` only for an ad whose serving state requires an explanation. 8. Read keyword, negative, product-page, or creative inventory only when the corresponding control @@ -76,11 +81,31 @@ drill-down question. Metadata reads do not justify unscoped lists. ### Performance +The snapshot is one fixed metric set, in this order, for the requested scope and window. All of it +comes back from the single overview call in step 4 — extra metrics on one call cost no extra calls. + +| Row | Metric | Notes | +|---|---|---| +| Spend | `spend` | use `local_spend` only when the user asks for account currency | +| Impressions | `impressions` | | +| Taps | `taps` | | +| Avg CPT | `avg_cpt` | | +| Installs | `total_installs` | Apple's own count, reported on its own | +| CPI | `total_avg_cpi` | Apple's average cost per install. It counts redownloads. Read the field; never recompute it as spend ÷ installs | +| Cost per trial | `cost_per_trial` | only when the user said the app has a free trial | +| Cost per paid | `cost_per_paid` | | + +- A metric absent from the response is `unknown`, never zero. +- `cost_per_trial` and `cost_per_paid` are values for the requested date window. Never pass + `--by-days` / `--order-by-day` for them and never attach a `day-X` label. - State the metric and date window before interpreting it. State a cohort window only for a cohort root, and always use net rather than asking the user to choose a revenue variant. - Keep immature cohorts in `unknown` or `insufficient evidence`. - Compare against the user's target or the account's own requested historical period. Do not invent - a universal threshold. + a universal threshold. `total_avg_cpi` is not the benchmarks skill's CPA — that figure is spend per + download, so check the denominator before placing them side by side. +- Never compare Apple install counts with Adapty install counts, and never report a gap or a + percentage of Apple's count between them. ### Inventory readiness @@ -89,21 +114,6 @@ drill-down question. Metadata reads do not justify unscoped lists. - Absence is not automatically a defect: mark a control `not_applicable` when the campaign type does not need that inventory. -### Apple versus Adapty installs - -Use values from the same overview response and exact date window: - -```text -apple_installs = total_installs -adapty_installs = adapty_installs -absolute_gap = apple_installs - adapty_installs -relative_gap = absolute_gap / apple_installs # only when apple_installs > 0 -``` - -Report the two values, the signed absolute gap, and the percentage only when defined. Add one plain -sentence: Apple and Adapty use different attribution and event definitions, so an exact match is not -expected. Do not investigate or assign fault. - ## Decision rules | Status | Use when | @@ -124,7 +134,7 @@ Return these sections in order: 2. **Critical findings** — confirmed failures only. 3. **Needs attention** — supported concerns and their impact. 4. **Healthy signals** — concise evidence, not reassurance. -5. **Apple vs Adapty installs** — same-window values and the limited explanation above. +5. **Performance snapshot** — the standard metric set above for the requested scope and window. 6. **Unknowns** — missing targets, maturity, metadata, or unsupported causes. 7. **Recommended actions** — one primary follow-up and an optional backlog. @@ -133,17 +143,17 @@ Every finding must include status, observation, evidence ids, confidence, limita ## Example ```text -ATTENTION — Campaign C-17 spent $420 in the selected window and Apple reported 96 installs. -Adapty reported 81 installs for the same dates: a gap of 15 installs (15.6% of Apple's count). -The systems use different attribution and event definitions, so this gap is a comparison signal, -not proof that either system is wrong. Evidence: E3. Confidence: high for the counts, low for cause. +ATTENTION — Campaign C-17 spent $420 in the selected window on 1,050 taps at an avg CPT of $0.40, +and produced 96 installs at a CPI of $4.38 — roughly double the account's $2.08. Cost per paid is +unknown for this campaign: the window returned no paid conversions. Evidence: E3. Confidence: high +for the counts, low for cause. Next step: check whether the ad group's keywords match intent. ``` ## Failure modes -- A mismatched window invalidates the install comparison; rerun one same-window overview. -- Apple installs equal to zero makes the percentage undefined; show no percentage. -- Missing Adapty installs makes the comparison `unknown`, not zero. +- A metric absent from the response is `unknown`; printing it as zero invents a result. +- Reporting `cost_per_trial` for an app with no free trial produces a meaningless row; ask first. +- `total_avg_cpi` read against a benchmark CPA compares two different denominators. - No change history means a timing relationship is not causation. - A category benchmark is optional context, not a substitute for the user's target. - Never finish this playbook by executing a recommended action. diff --git a/skills/apple-ads/references/playbooks/bid-optimization.md b/skills/apple-ads/references/playbooks/bid-optimization.md index 05ddba2..359fe01 100644 --- a/skills/apple-ads/references/playbooks/bid-optimization.md +++ b/skills/apple-ads/references/playbooks/bid-optimization.md @@ -49,9 +49,10 @@ policy, identify the bucket first and ask for the exact proposed amount before w 1. Read scoped active and paused keyword metadata to obtain ids, current bids, status, text, and match type. -2. Make one keyword metrics request for spend, Apple and Adapty installs, the selected cost/value - metrics, rank, search popularity, and impression midpoint. Only for a cohort root, include the - approved `--by-days` window and rank by the expanded `net_` metric. +2. Make one keyword metrics request for `spend`, `impressions`, `taps`, `avg_cpt`, `total_installs`, + `total_avg_cpi`, the selected cost/value metrics, rank, search popularity, and impression midpoint. + Only for a cohort root, include the approved `--by-days` window and rank by the expanded `net_` + metric. 3. Match metrics rows to the scoped ids. `metrics` has no scope filters; an account-wide row is not permission to act outside the requested scope. 4. Record coverage. If the full scoped set does not fit in the returned page, do not claim a complete diff --git a/skills/apple-ads/references/playbooks/weekly-review.md b/skills/apple-ads/references/playbooks/weekly-review.md index 78847ad..292da7d 100644 --- a/skills/apple-ads/references/playbooks/weekly-review.md +++ b/skills/apple-ads/references/playbooks/weekly-review.md @@ -23,7 +23,9 @@ recommend one action, but a separate playbook and a separate confirmation execut - The user wants a broad health or structure diagnosis → `apple-ads-audit`. - The user already chose a bid, negative, harvest, or CPP action → open that playbook. -- The user asks for a deep attribution investigation. This playbook only compares install counts. +- The user asks for an attribution investigation. Attribution is out of scope here and everywhere + else in this skill. Never compare Apple install counts with Adapty install counts, never report an + install gap, and never explain one away. ## Required inputs @@ -31,6 +33,9 @@ Ask for any missing decision-changing input: - exact report window; - whether to compare it with another period; +- whether the app offers a free trial — ask this before offering a success metric. When the answer is + no, drop the cost-per-trial row from the standard metric set and do not offer cost per trial as a + success metric; - the success metric; when offering choices, use this exact priority: `cost_per_paid`, `cost_per_trial`, then net `roas` at day X; - any user-defined target or guardrail; @@ -51,13 +56,14 @@ bad, profitable, or unprofitable. Do not add an unrequested period comparison. Use at most four analytics-family calls: -1. **Overview and trend.** One `metrics overview` call across the requested window. Request spend, - `total_installs`, `adapty_installs`, and the selected success metric. For a cohort root, request - its root and the approved `--by-days` window, then read the `net_` value. A per-period series - already contains the comparison; never call once per period. +1. **Overview and trend.** One `metrics overview` call across the requested window. Request the whole + standard metric set below plus the selected success metric. For a cohort root, request its root and + the approved `--by-days` window, then read the `net_` value. A per-period series already contains + the comparison; never call once per period. 2. **Campaign outliers.** One server-sorted campaign call using the user-approved metric, direction, - and, only for a cohort root, cohort window. Rank revenue-family metrics by their expanded `net_` - name. + and, only for a cohort root, cohort window. Request the same standard metric set on that call so + the outlier rows are readable against the account totals. Rank revenue-family metrics by their + expanded `net_` name. 3. **Keyword outliers.** One server-sorted keyword call only when the campaign result warrants that level or the user requested it. 4. **Search terms.** One scoped call only when the report is expected to end in growth or waste @@ -70,23 +76,32 @@ returned coverage and do not claim a global worst row. Counting entities is not an analytics call. A scoped list with `--page-size 1` already returns the count. -## Simple Apple versus Adapty install comparison - -Use values from the same overview response and date window: - -```text -apple_installs = total_installs -adapty_installs = adapty_installs -absolute_gap = apple_installs - adapty_installs -relative_gap = absolute_gap / apple_installs # only when apple_installs > 0 -``` - -- Show both values and the signed absolute gap. -- Show the percentage only when Apple installs are greater than zero. -- Treat a missing value as unknown, not zero. -- Explain in one sentence that Apple and Adapty use different attribution and event definitions, so - exact equality is not expected. -- Do not assign fault or investigate attribution. +## Standard metric set + +Every check-in reports these rows, in this order, for the requested window. All of them come back +from the one overview call in step 1 — adding metrics to a call costs no extra calls. + +| Row | Metric | Notes | +|---|---|---| +| Spend | `spend` | use `local_spend` only when the user asks for account currency | +| Impressions | `impressions` | | +| Taps | `taps` | | +| Avg CPT | `avg_cpt` | | +| Installs | `total_installs` | the denominator behind CPI; report it as Apple's own count | +| CPI | `total_avg_cpi` | Apple's average cost per install. It counts redownloads. Read the field; never recompute it as spend ÷ installs | +| Cost per trial | `cost_per_trial` | only when the user said the app has a free trial | +| Cost per paid | `cost_per_paid` | | + +- A metric the response did not return is `unknown`, never zero. +- With a comparison period, give each row its current value, its prior value, and the signed delta. + The per-period series in the same response supplies both sides. +- `cost_per_trial` and `cost_per_paid` are values for the requested date window. Never pass + `--by-days` / `--order-by-day` for them and never attach a `day-X` label. +- Call a row good, bad, profitable, or unprofitable only when the user gave a target for it. +- `total_avg_cpi` is not the benchmarks skill's CPA. That figure is spend per download; check the + denominator before putting the two side by side, and never rename one to the other. +- Never compare Apple install counts with Adapty install counts, and never report a gap, a + percentage of Apple's count, or an attribution explanation between them. ## Decision method @@ -105,30 +120,39 @@ one caused the other. Return these sections in order: -1. **Direction** — spend, Apple installs, Adapty installs, selected cost metric, and selected value - metric for the requested period or comparison. -2. **Apple vs Adapty installs** — the limited same-window comparison above. -3. **Two positive changes** — or fewer when evidence does not support two. -4. **Two concerns** — confirmed observations, not invented failures. -5. **Primary action** — one read-only recommendation and its operator playbook. -6. **Backlog** — optional later checks. -7. **Unknowns and confidence** — targets, maturity, scope, or unavailable causes. +1. **Direction** — the standard metric set for the requested period or comparison, plus the selected + value metric when it is not already one of those rows. +2. **Two positive changes** — or fewer when evidence does not support two. +3. **Two concerns** — confirmed observations, not invented failures. +4. **Primary action** — one read-only recommendation and its operator playbook. +5. **Backlog** — optional later checks. +6. **Unknowns and confidence** — targets, maturity, scope, or unavailable causes. Every finding names evidence ids, entities, metrics, windows, confidence, and limitations. ## Example ```text -Direction: spend rose 8% in the requested comparison while day-30 net ROAS was flat. -Apple vs Adapty installs: 540 vs 497, a gap of 43 (8.0% of Apple's count). The systems use -different attribution and event definitions, so this is a comparison signal, not proof of an -error. Primary action: review bids for the three mature keywords below the user's ROAS target. +Direction (Aug 10-16 vs Aug 3-9) +Spend $4,180 $3,870 +8.0% +Impressions 612,400 588,100 +4.1% +Taps 9,240 9,010 +2.6% +Avg CPT $0.45 $0.43 +4.7% +Installs 2,010 1,940 +3.6% +CPI $2.08 $1.99 +4.5% +Cost per trial $9.40 $8.85 +6.2% +Cost per paid $31.20 $29.60 +5.4% + +Spend rose 8% while taps rose 2.6%, so the whole increase landed in CPT. Cost per paid moved +with it and is $1.20 above the user's $30 guardrail. Primary action: review bids for the three +mature keywords carrying that CPT increase. ``` ## Failure modes -- Different install windows invalidate the comparison. -- Apple installs equal to zero makes the percentage undefined. +- Reporting `cost_per_trial` for an app with no free trial produces a meaningless row; ask first. +- `total_avg_cpi` read against a benchmark CPA compares two different denominators. +- A metric absent from the response is `unknown`; printing it as zero invents a result. - A monthly cohort read at day 7 is immature, not losing. - A server-sorted top page does not prove the global worst when more pages exist. - No user-defined target means no performance verdict and no mutation proposal.