---
name: set-existing-customer-budget-cap
description: >-
  Configures the existing-customer budget cap inside an Advantage+ Sales campaign: attaches an
  existing-customer list to the campaign's cap control and picks the percentage of budget Meta may spend
  re-engaging that list versus prospecting new customers. A low cap (~20-30%) biases toward acquisition; a
  higher cap lets more budget chase repeat purchases. Covers defining the existing-customer list via
  `mads_create_custom_audience` (CUSTOMER_LIST subtype) plus `mads_add_audience_members` with
  SHA-256-hashed, client-side-normalized PII, choosing the cap percentage from the account's
  acquisition-vs-retention goal, and reading the new-vs-existing customer split back out of reporting to
  confirm the cap holds. Reach for it whenever an Advantage+ Sales campaign needs new-customer growth
  protected from repeat-buyer cannibalization. It ends at a configured cap - it does not cover general
  customer-list build/refresh mechanics (upload-customer-list-audience, audiences domain).
---
# Set the Existing-Customer Budget Cap in Advantage+ Sales

## Purpose
Advantage+ Sales will happily spend efficient budget on people who were going to buy anyway, existing
customers are cheap, high-intent conversions that make CPA look great while doing nothing for growth. The
existing-customer budget cap is the one lever that protects new-customer acquisition inside an otherwise
fully automated campaign: it limits the *share* of budget Meta may spend on people in a defined
existing-customer list, forcing the rest toward prospecting.

## When to run
- Standing up a new Advantage+ Sales campaign for an account with repeat-purchase behavior
  (`launch-advantage-plus-shopping`).
- An Advantage+ Sales campaign's reporting shows most conversions coming from existing customers when the
  goal was growth.
- The business's acquisition-vs-retention priority changes, a growth push, or a deliberate shift to
  harvesting existing customers.
- The existing-customer list is stale and the cap is no longer enforced against the right people.

## When NOT to run
- Building or refreshing the customer list's raw membership mechanics in general →
  `upload-customer-list-audience`.
- Deciding on audience suggestions or broad-vs-constrained targeting generally →
  `configure-advantage-plus-audience`.
- Launching the Advantage+ Sales campaign itself → `launch-advantage-plus-shopping`.
- Building a lookalike or interest-based audience → `build-custom-audiences`.

## Prerequisites
- An existing or in-progress Advantage+ Sales campaign (OUTCOME_SALES + Advantage+ setup).
- Raw customer data (email/phone at minimum) for the existing-customer definition, CRM export via
  `hubspot_search_contacts`, `salesforce_soql_query`, or `sheets_get_values`. (HUMAN STEP for any CRM
  without a connector.)
- Documented consent for using this data in advertising. PII must be normalized and SHA-256 hashed
  client-side, with no third-party transfer. (HUMAN STEP to confirm consent coverage.)
- A stated acquisition-vs-retention goal from the business, the cap percentage is a direct translation of
  that goal, not a default to guess at.

## Procedure
1. **Define "existing customer" precisely.** Agree with the user: anyone with a past purchase, or purchases
   within a trailing window (e.g., last 365 days). Write it down, it drives the CRM pull.
2. **Build or refresh the existing-customer list.** Source records, normalize identifiers, create via
   `mads_create_custom_audience` (`subtype=CUSTOMER_LIST`) if it doesn't exist yet, and upload
   SHA-256-hashed members via `mads_add_audience_members`. (HUMAN STEP: confirm consent coverage for
   the records included.) Full normalization/refresh mechanics live in `upload-customer-list-audience`, this skill only needs the list to exist and be current. Preview and get approval before any create/upload.
3. **Attach the list to the campaign's existing-customer cap control.** On the Advantage+ Sales campaign/ad
   set, set this audience as the existing-customer definition via `mads_update_adset` so Meta can classify
   converters as existing vs new.
4. **Choose the cap percentage from the stated goal.** Use Decision rules. Default to a low cap (20-30%)
   unless the business has explicitly prioritized retention or repeat-purchase revenue over growth.
5. **Preview and confirm.** Show the user: list size, cap percentage, and the plain-English meaning, "at
   most X% of this campaign's budget may go to people on the existing-customer list; the rest is reserved
   for new-customer acquisition." Get explicit approval before commit (write-safety pattern).
6. **Commit the cap.** Apply via `mads_update_adset`/`mads_update_campaign` per the build's cap field.
   Re-query with `mads_get_campaign`/`mads_get_adset` to confirm it saved.
7. **Measure the new-vs-existing split.** Once the ad set clears ~50 optimization events/7 days, pull
   `mads_run_insights` + `mads_get_insights` (or `mads_get_insights`) segmented by
   new/existing customer to confirm actual spend share is tracking the cap's intent.
8. **Keep the list current.** Stale membership silently defeats the cap (see Common failure modes), hand
   the refresh cadence to `upload-customer-list-audience` and log the owner and cadence here.

## Decision rules
- **Growth-priority account (the common default) →** low cap, 20-30%, forcing the bulk of budget toward
  new customers.
- **Balanced growth-and-retention goal →** mid cap, roughly 30-50%.
- **Deliberate harvest/retention push** (loyalty promotion, re-engagement dressed as Advantage+ Sales)
  **→** higher cap, 50%+, or consider whether a dedicated retention campaign outside Advantage+ Sales is
  the cleaner tool.
- **No existing-customer list yet and no stated goal →** do not guess a cap; build the list and get the
  goal stated first. An uncapped Advantage+ Sales campaign defaults to whatever is cheapest, which usually
  means existing customers.
- **Measured spend share drifting well above the set cap →** the list is likely stale or the campaign is
  misclassifying; refresh the list before assuming the cap control itself failed.
- **Done means:** an existing-customer list built and attached, a cap percentage chosen and tied explicitly
  to the stated business goal, the cap committed and confirmed via re-query, and a refresh cadence with a
  named owner.

## Common failure modes
- **No cap set at all** on a mature e-commerce account, Advantage+ Sales quietly optimizes toward the
  cheapest conversions, which are repeat buyers, and acquisition starves.
- **Stale list undercounts existing customers.** Anyone who purchased since the last refresh is absent from
  the list and gets classified, and spent on, as new, inflating apparent new-customer growth while the
  cap fails to restrain real repeat-buyer spend. Refresh on the stated cadence (step 8).
- **Hashing un-normalized identifiers.** `SHA-256("John@X.com ")` matches nothing; normalize first, hash
  second, always.
- **Picking a cap number with no stated business goal behind it.** An arbitrary 20% or 50% is unfalsifiable, tie it to the acquisition-vs-retention decision explicitly.
- **Retrying `mads_create_custom_audience` after an unclear result.** No idempotency key exists; check
  `mads_list_custom_audiences` first rather than risk a duplicate list.
- **Echoing raw PII** in previews or logs instead of counts only, a compliance issue, not a style nit.

## Related skills
- Depends on: `upload-customer-list-audience` (audiences domain) for the customer-list build/refresh
  mechanics this cap attaches to.
- Run before/alongside: `launch-advantage-plus-shopping` (the campaign this cap configures).
- Related: `configure-advantage-plus-audience` (the broader targeting decision this cap complements),
  `build-custom-audiences` (audiences domain, for lookalike/interest audiences, a different mechanism).
