---
name: build-custom-audiences
description: >-
  Creates Meta custom audiences from every first-party source - website/pixel events, app activity,
  engagement (video viewers, page/profile engagers, lead-form openers), and hashed customer lists - picking
  the subtype and retention window mads_create_custom_audience needs so the audience reflects the intent it
  is named for. Verifies the source has real volume via mads_list_pixels, sets recency windows from same-day
  cart abandoners (3-7 days) through year-long pools (up to 365 days), enforces a naming convention encoding
  source + event + window, and checks size against the ~1,000-match floor. Reach for it whenever a
  retargeting tier, lookalike seed, or exclusion source does not exist yet, or when auditing audiences for
  stale windows or ambiguous names. It ends at a built, verified custom audience - it does not size a
  lookalike (build-lookalike-audiences), apply exclusion logic (set-exclusions-and-suppression), or run the
  hash-and-upload pipeline for CRM contacts (upload-customer-list-audience).
---
# Build Meta Custom Audiences

## Purpose
Every warm audience, lookalike seed, and exclusion list on Meta traces back to a custom audience built
from one of four sources: website/pixel events, app activity, engagement, or a hashed customer list. Get
the subtype, retention window, and naming wrong here and every downstream skill inherits the mistake, a lookalike seeded from a mis-windowed audience, a retargeting tier that is actually 180 days of noise,
an exclusion list nobody can identify by name. This skill turns a targeting need into a correctly-typed,
sized, and named custom audience.

## When to run
- A retargeting tier, lookalike seed, or exclusion source is needed and no matching custom audience exists.
- Standing up custom audiences for the first time on a newly-connected pixel or app.
- An existing audience's name does not say what source/event/window it covers, and it needs re-auditing.
- Confirming a source (pixel, app, page) actually has enough event volume before building on it.

## When NOT to run
- The audience already exists and you need to turn it into a lookalike → `build-lookalike-audiences`.
- You are deciding what to exclude or suppress, not what to build → `set-exclusions-and-suppression`.
- The source is a CRM/spreadsheet contact list needing normalization and hashing →
  `upload-customer-list-audience` (this skill only names customer-list as a subtype option).
- You are arranging built audiences into a tiered warm funnel → `design-retargeting-ladder`.

## Prerequisites
- Pixel installed and firing standard events, or app events configured, or Page/IG/lead-form engagement
  connected in Business Manager.
- Business Manager access with audience-creation permission (HUMAN STEP if the account lacks it).
- A naming convention agreed with the account owner: source, event, and window in the name.

## Procedure
1. **Verify the source has volume.** Call `mads_list_pixels` and confirm the pixel is active with recent
   event counts for the target event (Purchase, AddToCart, ViewContent, PageView). Building on a dead or
   low-volume pixel produces an audience that never clears a useful size.
2. **Pick the source and subtype.** Choose website/pixel (event-based), app activity, engagement (video
   views, IG/FB page or profile engagement, lead-form opens, event responses), or customer list. The
   subtype is not cosmetic, it determines which events the audience can key off and how it refreshes.
3. **Set the retention window deliberately.** Pixel events run up to 180 days; engagement types run up to
   365 days for some sub-types. The window is a targeting decision: short windows (3-14 days) capture
   urgent, high-intent behavior; long windows (90-365 days) capture broad, low-intent reach. Match the
   window to what the audience will be used for, not to the platform maximum by default.
4. **Name it to encode source + event + window.** For example `Web-AddToCart-14d` or `IG-Engaged-365d`.
   An unnamed or generically-named audience gets misused by the next person who reads the audience list.
5. **Create it.** Call `mads_create_custom_audience` with the chosen subtype, source, and window. Preview
   the definition, get explicit user approval, then commit. Check `mads_list_custom_audiences` first if
   there is any chance an equivalent audience already exists, there is no idempotency key, so re-running
   a create call blind produces a duplicate rather than an error.
6. **Skip member_add for dynamic sources.** Website/pixel, app-activity, and engagement audiences populate
   automatically from platform-side events, do not call `mads_add_audience_members` for these.
   Only the customer-list subtype needs member records added; that hashing pipeline lives in
   `upload-customer-list-audience`.
7. **Verify size.** Call `mads_list_custom_audiences` and read the audience size against the ~1,000-user
   floor from Decision rules. An audience under floor is still valid for narrow suppression use but is not
   yet usable as a lookalike seed or a standalone ad-set target.
8. **Document it.** Record source, subtype, window, size, and whether it is dynamic (auto-refreshing) or
   static, this is what `build-lookalike-audiences`, `design-retargeting-ladder`, and
   `set-exclusions-and-suppression` will look up next.

## Decision rules
- **Purchase / high-intent conversion events →** 30-180 day window; shorter (30-60d) for near-term buyer
  retargeting, longer (90-180d) for a broad past-purchaser pool used in exclusions or LAL seeding.
- **ViewContent / PageView →** 14-30 day window for a genuinely warm "recent browser" audience; anything
  past ~90 days stops representing current interest.
- **AddToCart / InitiateCheckout non-purchasers →** 3-14 day window, this tier is inherently urgent; a
  30+ day cart-abandoner audience is mostly people who already decided not to buy.
- **Engagement (video viewers, IG/FB engagers, lead-form openers) →** 30-365 days depending on sub-type;
  video-view thresholds (50%+, ThruPlay) signal materially higher intent than a raw page-engagement event.
- **Customer list →** the subtype exists here, but the hashing/normalization procedure is
  `upload-customer-list-audience`, do not build a customer-list audience without it.
- **Minimum useful size:** under ~1,000 matched, treat the audience as suppression/edge-case material only, not a scalable prospecting, retargeting, or lookalike-seed audience. 1,000+ is the working floor;
  more is better, especially for anything feeding a lookalike.
- **Done means:** the audience exists with the correct subtype, a deliberately chosen window, a name that
  encodes source + event + window, a verified size, and a documented dynamic/static refresh behavior.

## Common failure modes
- **Wrong subtype for the source** (e.g., building an engagement-type audience from pixel data), the
  audience never populates and the failure looks like a volume problem instead of a setup error.
- **No naming convention**, audiences accumulate as generic labels, and the next build reuses the wrong
  one or creates a near-duplicate.
- **Building on a pixel with no checked volume**, skipping step 1 produces an audience stuck under floor
  indefinitely, discovered only when a lookalike or ad set built on it fails to deliver.
- **Manually adding members to a dynamic (pixel/app/engagement) audience**, these refresh from events,
  not member lists; member_add calls belong to the customer-list subtype only.
- **Treating window length as a technicality**, a 180-day PageView audience is a broad low-intent pool,
  not "recent interest"; the window is a targeting decision, not a default to leave alone.
- **Re-running create without checking for an existing match**, no idempotency key means a repeated call
  creates a genuine duplicate audience rather than returning the existing one.

## Related skills
- Run after this: `build-lookalike-audiences` (use a qualifying audience as a seed), `design-retargeting-ladder`
  (arrange built audiences into a tiered warm funnel), `set-exclusions-and-suppression` (exclude these
  audiences from each other and from prospecting).
- For the customer-list source specifically: `upload-customer-list-audience`.
