# UGC Pipeline (/docs/concepts/ugc-pipeline)



The UGC pipeline turns creator posts on Instagram and TikTok into ad creative.
Here's the full flow.

## 1. Discovery (SIFT) [#1-discovery-sift]

Layers integrates with SIFT for creator and post discovery. On each cycle,
the sync program:

1. Reads the creator allowlist for your project.
2. Fetches the 50 most recent posts per creator.
3. Stores them in `platform_posts` (one row per post).
4. Refreshes post `content` on every sync (so updated metrics, new comments,
   etc. are captured).

Media URLs from SIFT are hosted on permanent media storage — they don't
expire like Instagram's CDN URLs.

## 2. Container creation [#2-container-creation]

Layers creates a `content_container` for each newly-synced post. Container
creation is idempotent — re-syncing the same post does not create a
duplicate.

## 3. Scoring [#3-scoring]

Scoring runs every 4 hours. For each UGC `ads_content` row, the scoring
step:

1. Reads the latest post metrics.
2. Computes percentiles across the project's UGC pool.
3. Scores using quality (45%), reach (25%), outperformance (30%) + freshness
   bonus (up to +1.5 within 90 days).
4. Updates `ads_content.organic_score`, `scored_at`, `scoring_version`.

Posts with fewer than 50 views are skipped, and scoring itself runs only
when the project has at least 3 posts in the pool.

## 4. Ad eligibility [#4-ad-eligibility]

Once `ads_content.organic_score >= 4.0` (or `override = 'include'`), the
post is eligible for ad selection. The creative-selection step pulls it
into adsets when the layer needs new creatives.

## 5. Whitelisting / dark posts [#5-whitelisting--dark-posts]

Before a creator's UGC can run as an ad on Meta or TikTok, the creator must
**whitelist** your business. This grants the platform permission to amplify
the creator's organic post as an ad from your brand handle.

For agency-mode setups this is handled via Business Center asset assignment.
For BYO setups, you coordinate the whitelist directly with the creator. See:

* [Whitelisting on Meta](/docs/ugc/licensing#meta-whitelisting)
* [Spark Ads on TikTok](/docs/ugc/licensing#tiktok-spark-ads)

## 6. Royalty and bonus tracking [#6-royalty-and-bonus-tracking]

If you're paying creators performance bonuses, Layers tracks ad spend
attributed to each UGC creative. The
[creator portal](/docs/ugc/creators) and per-creator reports show:

* Spend on this creator's content.
* Conversions attributed.
* Bonus payouts owed (per your payout config).

## Ownership of state [#ownership-of-state]

| Table                                | Purpose                                        | Write semantics                       |
| ------------------------------------ | ---------------------------------------------- | ------------------------------------- |
| `platform_posts`                     | Synced UGC posts from SIFT                     | UPSERT; refresh `content` on conflict |
| `content_containers`                 | Layers' wrapper around posts/generated content | INSERT-only, idempotent               |
| `ads_content`                        | Scoring/eligibility entity                     | UPDATE on each scoring cycle          |
| `project_ads_content`                | Per-project ads\_content with `override`       | INSERT/UPDATE for overrides           |
| `layer_meta_ads`, `layer_tiktok_ads` | Ads launched per layer                         | UPDATE on optimizer cycles            |

## Troubleshooting [#troubleshooting]

* **A creator's posts aren't syncing** — check SIFT integration health on the
  layer settings page; verify the creator is in the allowlist and their
  account is public/business.
* **Posts are syncing but aren't scoring** — they likely have \<50 views; check
  back after the post matures.
* **Scoring above threshold but not running as ads** — check that the creator
  has whitelisted your handle (Meta) or that you have the post's Spark code
  (TikTok). See [licensing](/docs/ugc/licensing).
