RAW Chemistry — Meta ads: complete engagement record

Compiled 2026-08-30 UTC / 2026-08-29 evening PDT.

Written to be picked up cold by someone with no context. Everything is here: identifiers, every

ad day to the hour, every object and its state, every decision and its reasoning, every fix, every

mistake, every tool, every open question.

Companion docs (all in repo):

ADS-PLAN.md · LEARNINGS.md · sources/competitive-research/competitor-audit-2026-08-28/ ·

output/ufo-banner-2026-08-27/RECUT-NOTES.md · docs/META-ADS-MCP.md


PART 0 — TL;DR for someone picking this up right now

One campaign is live. V81, CBO, currently $175/day (raised from $100 at 02:20 PDT Aug-29

by an out-of-session MCP call — operator has not confirmed this was intentional).

Two ads running, both the same 30.1s UFO video. One shows the offer only on the end card

(control), one pins it on screen from 0.0s (banner). This is a one-variable test.

Three days of data. Thu $6.11/ATC → Fri $6.13/ATC → Sat $11.60/ATC. Saturday broke the

pattern, but two things changed at once: the budget and it being the first weekend day.

They cannot be separated from history.

Recommended immediate action, pending operator go: revert budget to $100. Saves ~$125.

Do not try to read Sunday. Monday vs Thu/Fri is the clean comparison.

Campaign to date: $387.45 spend → $536.80 revenue, ROAS 1.39, 7 purchases, CAC $55.35.
Blocked on four operator inputs: COGS, a true reason-why for the 70% offer, confirmation of

the budget change, and the go-forward budget.


PART 1 — Access, identifiers, credentials

1.1 Meta

itemvalue
Ad account928489503435693 — "Brett Ads"
Page107954045643337 — Raw Chemistry
Instagram user17841477912140752 — @rawchemistryus
Pixel622400256897443
Access routemcp__claude_ai_Meta__* MCP tools
TimezoneAmerica/Los_Angeles (PDT) — all "today" figures follow this, not UTC

instagram_user_id is mandatory on video ads under an all-placements ad set. Without it Meta

rejects with error 1772103. Statics do not need it.

1.2 Shopify

itemvalue
Storeraw-chemistry-store.myshopify.com
CurrencyUSD
MarketsUnited States (primary, localCurrencies:false) · International (localCurrencies:true)
Admin tokenpermanent offline shpat_ from own custom app
Custom app"Webbuildr 2", client ba66dfaf16713fd861fd4b70000ea92f
Credentials dir~/.config/admaker/credentials/ (mode 0600)
Health checknode tools/shopify-token-health.mjs → expect life OFFLINE

CAD warning. The operator browses from Canada and is served converted prices by the

International market. A discount shown as −$334.28 is the −$236.85 USD discount

(rate ≈ 1.4114). Convert before diagnosing any pricing "discrepancy". Our own checks run from a

US-routed host and always return USD — which is what the campaign actually transacts, since the ad

set is geo-US only.

1.3 Other

itemvalue
Competitor researchForeplay MCP (mcp__claude_ai_Foreplay__*)
Review hosthttp://15.204.83.60/ — static, read-only, mounts in /srv/www/_server/mounts.json
Repo/home/ubuntu/Documents/AdMaker
Ledgernode tools/history.mjs record / validate

PART 2 — Complete object inventory

2.1 Campaigns (13 total, 1 active)

campaignidstatus
**RAW \V81 Clean Test \UFO + LOOKUP + CUPID-R2 \save70 \Dark Posts**120249646488770611ACTIVE
RAW \V82 UFO Persistent-Offer \save70 \Dark Post120249669199670611PAUSED, never spent
RAW \V80 Single Test \3 Creatives \70% Arm120249645525260611PAUSED
RAW \V79 Video CBO \8 Creatives120249625544390611PAUSED
RAW \V79 Video ABO \4 Concepts x 2 Offers120249625270290611PAUSED
RAW \V77 ABO \6 Ad Sets x $10120249624812710611PAUSED
RAW \V77 Offer A/B \3 Concepts x 2 Offers120249615068040611PAUSED
RAW \V76 DCO Test \10 Concepts120249609686230611PAUSED
RAW \V76 Video \4 Creatives120249608591340611PAUSED
RAW \V76 Launch \6 Creatives120249599273780611PAUSED
RAW \Test120249424103750611PAUSED
RAW \Scale120249423872160611PAUSED
RAW \Prospecting \$100 Focused Test120249228401770611PAUSED
RAW \Prospecting \Main \7-Creative Portfolio120248830225130611PAUSED

2.2 The live ad set — 120249646492400611

Name: V81 | US 18-65 broad | FB+IG only | Purchase | no AN/WA/Threads


{"geo_locations": {"countries": ["US"], "location_types": ["frequently_in","home"]},
 "age_min": 18, "age_max": 65,
 "publisher_platforms": ["facebook","instagram"],
 "facebook_positions": ["feed","video_feeds","marketplace","story","search","facebook_reels","profile_feed"],
 "instagram_positions": ["stream","story","explore","reels","profile_feed","ig_search"],
 "device_platforms": ["mobile","desktop"],
 "targeting_automation": {"advantage_audience": 1}}
settingvalue
optimization_goalOFFSITE_CONVERSIONS
billing_eventIMPRESSIONS
destination / conversion locationWEBSITE
promoted_object{pixel_id: 622400256897443, custom_event_type: "PURCHASE"}
attribution7-day click + 1-day view
is_dynamic_creativefalse
bid strategyHighest volume (LOWEST_COST_WITHOUT_CAP), no cap

Meta narrows this further on its owneffective_facebook_positions routinely drops

video_feeds, and effective_instagram_positions drops explore. That is Meta's choice, not a

failed write. Compare effective_* against requested and report the delta rather than retrying.

2.3 All 14 ads in V81

adidcreativestatusspent
UFO control (end card)1202496542838806111356499863310834ACTIVE$220.48
UFO banner (offer @0.0s)1202496715034206111065147595893626ACTIVE$63.43
CUPID-R2 static save70 FINAL1202496542896406112138899159993629PAUSED$89.07
LOOKUP static save70 FINAL1202496542882906111068078835624142PAUSED$19.11
CUPID-R2 static save70 r21202496483130906111602876511241208PAUSED$0
UFO video b2g1120249646494080611953501277773660PAUSED$0
UFO video save70 r41202496485593406111570562491483849PAUSED$0
UFO video save701202496480219606111095709386226097PAUSED$0
LOOKUP static save70 r21202496483124706111389976239777840PAUSED$0
LOOKUP static save70120249648022840611949804804042637PAUSED$0
CUPID-R2 static save701202496480239506111810337963460700PAUSED$0
CUPID-R2 static b2g11202496473643906111783829736131871PAUSED$0
LOOKUP static b2g11202496464952306111037709372360910PAUSED$0
V47-05 static b2g11202496464961306111374909448090236PAUSED$0

Deleted: 120249662229150611 — duplicate of the banner ad, removed Aug-27 21:28 PDT.

2.4 V82 spare campaign

objectidstate
campaign120249669199670611PAUSED, $100/day configured, never spent
ad set120249669203280611PAUSED, Advantage+ Audience ON, mirrors V81 targeting
ad120249669207010611PAUSED, creative 1065147595893626 (same banner creative)

Built as a standalone home for the recut, then superseded by the decision to run the banner inside

V81 for a same-ad-set comparison. Retained as a spare.


PART 3 — The creative

3.1 What the live ads actually are

Both live ads are the same 30.1s video: UFO-V34, a "leaked interview" concept. A hooded,

unidentified source in a dark room describes building a pheromone blend as a skin-chemistry test;

intercut with Venice Beach footage of women turning to look as a man passes. Ends on the product.

Control — offer appears only on the end card, at ~26s (≈86% into the runtime).
Banner — a two-tone lockup, red 70% OFF + cream TODAY ONLY, **pinned from frame 0 to

frame 767 (25.57s)**, then fades as the end card takes over. Offer therefore on screen for the

entire runtime.

Both ship native 4:5 (1080×1350) and 9:16 (1080×1920) masters — separately rendered, never

derived. adapt_to_placement is OPT_OUT so Meta performs no reformatting; supplying both natives is

mandatory, not optional.

Masters: brands/raw-chemistry/output/ufo-banner-2026-08-27/masters-{4x5,9x16}/

Uploaded video IDs: 2005163350167527 (4:5) · 2170230443928592 (9:16)

Verification: 30.100s, 30fps, faststart confirmed by atom order (ftyp moov free mdat),

−14.46 LUFS, and decoded audio PCM sha256 identical to the control — proving the edit is

video-overlay-only.

3.2 Ad copy — verbatim, identical on both ads

Primary text:


Most cologne is built to smell good for an hour and then quietly quit on you.

RAW 27™ is pheromone-infused — the formula behind 500,000+ bottles since 2016.

★★★★★ 4.8/5 · 12,400+ reviews · Free shipping · 60-day guarantee
Get 70% off — today only.

Headline: Your Cologne Quit Two Hours Ago

Description: 70% off today only. Free shipping.

CTA: SHOP_NOW · Display link: RAWCHEMISTRY.COM

Destination: https://rawchemistry.com/pages/raw-pheromone-cologne

Copy was recovered by fetching the live ad's own preview iframe and parsing its payload — not

reconstructed from documentation. Docs drift; the served ad does not.

3.3 Creative configuration lock (every creative in this account)

• All 17 Advantage+ creative enhancements OPT_OUT via degrees_of_freedom_spec sent alone as

a JSON-encoded string: `image_touchups, text_optimizations, image_brightness_and_contrast,

image_templates, image_animation, image_uncrop, add_text_overlay, media_liquidity_animated_image,

adapt_to_placement, site_extensions, profile_card, enhance_cta, description_automation,

catalog_feed_tag, product_extensions, cv_transformation, inline_comment`

self_ai_disclosure omitted entirely — never OPT_IN, never OPT_OUT. Immutable after creation.
Dark posts via object_story_spec — nothing reaches the page timeline.
placement_videos: 4:5 as the unscoped fallback, 9:16 scoped to FB story/reels + IG story/reels.

Exactly one unscoped entry is required by the API.

Traps: music is not a valid feature name and rejects the whole call. standard_enhancements

is deprecated. Validation stops at the first bad name, so the accepted 17 are expensive to

re-derive — reuse the list.


PART 4 — Every ad day, to the hour

4.1 Campaign daily

daydowbudgetspendimprreachfreqCPMCPCATC$/ATCICpurchrevenueROASCAC
Aug-27Thu$100$134.489577231.32$141$3.3622$6.113$218.901.63$44.83
Aug-28Fri$100$104.274393151.39$238$2.6717$6.133$218.902.10$34.76
Aug-29Sat$175~$151+675+$266$3.0613$11.601$99.000.66$150+

Aug-29 was still running at time of writing (18:35 PDT, 77% elapsed, $147.48 at ad level).

Campaign lifetime: $387.45 · 50 ATC @ $7.75 · 10 IC · 7 purchases · $536.80 · ROAS 1.39 · CAC $55.35.

4.2 Aug-27 hourly (Thu, 3 ads, $100 budget)

hr PDTspendimprATCpurch
06$20.22941
07$17.88772
08$8.655131
09$16.63872
10$13.9210741
11$6.487641
12$5.90531
13$6.3155
14$5.50732
15$4.2038
16$9.08561
17$1.5640
18$2.8535
19$5.48512
20$5.3642
21$3.7221
22$0.741

Delivery began ~06:00. All 3 purchases landed 08:00-11:59. Spend spread broadly.

4.3 Aug-28 hourly (Fri, 2 ads, $100 budget)

hr PDTspendimprhr PDTspendimpr
00$1.851312$9.3724
01$1.88213$3.5122
02$0.08314$5.3129
03$0.06215$6.8323
04$0.47716$16.4137
05$2.391417$6.6340
06$2.22918$6.8227
07$7.771519$7.2820
08$3.481520$1.3718
09$0.761021$6.1333
10$1.57722$3.6727
11$4.901623$3.5126

Spend spread almost flat across 24h. Only $20.20 (19% of day) by 09:00.

Control-ad ATCs: 9 of 10 landed at or after 14:00. Biggest hour 16:00.

Why so slow in the morning: Aug-27 overdelivered to $134.48 (+34%). Meta balances across a

~weekly window, so Aug-28 was throttled early to repay it.

4.4 Aug-29 hourly (Sat, 2 ads, $175 budget) — through 14:59

hr PDTETspendCPMLPVATCpurch
0003$3.56$23721
0104$1.65$1832
0205$1.72$156
0306$5.43$3192
0407$9.96$255111
0508$9.62$19621
0609$21.62$30561
0710$15.04$30142
0811$11.50$35921
0912$6.45$19531
1013$8.57$2451
1114$3.16$316
1215$6.61$264
1316$2.30$121
1417$2.70$159

00:00-09:59 = $86.55 → 24 LPV, 8 ATC, 1 purchase.

10:00-14:59 = $23.34 → 1 LPV, 0 ATC, 0 purchase.

The 06:00-07:00 block took 51% of the day's early budget at the highest CPMs of the day

($305/$301 vs $121-196 later). That was not irrational: those are 09:00-11:00 Eastern, and the

morning produced every conversion. Meta optimises for predicted purchasers, not cheap impressions,

and paid a premium for the hours that convert.

Caution recorded: the 13:00-16:00 stretch looked like a dead zone and was then followed by

2 more control ATCs by 16:42. Dayparting cannot be judged intraday.

4.5 Per-ad lifetime

adstatusspendimprCTR$/LPVLPV$/ATCATCpurchrevenue
UFO controlACTIVE$220.489347.39%$3.8058$8.48265$377.85
UFO bannerACTIVE$63.433089.09%$3.7317$7.0591$59.95
CUPID-R2 staticPAUSED$89.077123.93%$4.0522$6.36141$99.00
LOOKUP staticPAUSED$19.111323.79%$4.784$6.3730

4.6 Per-format CPM (Aug-27, the only day all formats ran)

adformatspendimprCPM$/ATC
CUPID-R2static$89.07712$125$6.85
LOOKUPstatic$19.11132$145$6.37
UFOvideo$25.20110$229$4.20

Video costs ~1.8× static per impression. 84% of Aug-27's impressions came from statics, which

is why that day's blended CPM was $141 — the cheapest of the three despite the highest spend.

4.7 Every funnel order (price-matched, PDT)

ordertimestamp PDTamountproductday
#164595Aug-27 08:18$59.95singleThu
#164597Aug-27 10:06$99.003-packThu
#164598Aug-27 11:05$59.95singleThu
#164608Aug-28 15:23$59.95singleFri
#164610Aug-28 18:22$99.003-packFri
#164612Aug-28 22:34$59.95singleFri
#164613Aug-29 04:52$99.003-packSat
$536.80

10 consecutive exact reconciliations between Meta-reported revenue and paid Shopify orders.

Identify funnel orders by PRICE. Shopify reports **every one of these as `firstVisit: direct,

lastVisit: direct` with no UTM, because the funnel converts through shop.app / Shop Pay, which

strips the referrer**. Non-funnel orders on the same days ($71.00, $67.50, $36.50, $34.50, $36.75)

are other products/channels.

4.8 Historical: FREE vs honest offers (90-day, pre-V81)

FREE adshonest-offer ads
spend$425.32$139.57
impressions10,1591,059
CPM$41.87$131.79
cost/LPV$1.49$4.65
revenue$73.00$218.90
ROAS0.171.57
revenue per LPV$0.26$7.30

Honest offers cost 3.1× the CPM and returned 9.2× the revenue per dollar and **28× the

revenue per landing page view**.


PART 5 — Chronology: what happened, when, and why

Aug-26 and earlier — the pre-history

Eleven campaigns had run (V76-V80, Prospecting, Test, Scale) on a funnel later proven broken.

Symptoms: cost per ATC $14-114, several days with zero purchases, and a Shopify attribution report

showing "Facebook/Instagram 0" in the last 16 orders — which was later shown to be **Shop Pay

stripping the referrer**, not an absence of ad-driven sales. Everything was paused to reach one

clean test.

Aug-27

whenwhatwhy
~04:45V81 built: 3 ads (UFO video, LOOKUP static, CUPID-R2 static), CBO $100/day, save70 armClean single-variable test after the funnel fixes
~06:00Delivery begins
08:18 / 10:06 / 11:05Three purchases land — $59.95 / $99.00 / $59.95Reconciled exactly to Meta's $218.90
13:33Banner recut added to V81 ad set as 120249662229150611, pausedOperator: "add it to the campaign but keep it paused"
19:27-19:28V82 campaign + ad set + ad created, all pausedOperator: "put it into its own campaign"
19:49V82 ad set corrected: advantage_audience 0 → 1Operator corrected me — A+A must stay ON; "no AI flags" means creative AI
21:28Duplicate ad 120249662229150611 deletedSame creative existed twice after two instructions
21:34CUPID-R2 and LOOKUP statics PAUSEDCost-per-ATC: UFO $4.20 vs $6.85/$6.37. CUPID-R2 had taken 66% of spend on the worst CTR
21:34Banner ad 120249671503420611 created in V81 ad set, activated 21:35To run banner vs control in the same ad set — one variable
21:37Meta approves the banner ad
day close$134.48, 22 ATC @ $6.11, 3 purchases, ROAS 1.63

Aug-28

whenwhat
all dayTwo ads only: UFO control + UFO banner. Budget $100
morningVery slow — $20.20 by 09:00 (19% of day). Cause: repaying Aug-27's +34% overdelivery
15:23 / 18:22 / 22:34Three purchases — $59.95 / $99.00 / $59.95
9 of the control's 10 ATCs landed at or after 14:00
day close$104.27, 17 ATC @ $6.13, 3 purchases, ROAS 2.10 — best day of the three

Aug-29

whenwhat
02:20Campaign budget raised $100 → $175/day via ads MCP server, actor Brett Messinger. Not done in-session. Unconfirmed.
04:52One purchase, $99.00
06:00-07:5951% of early budget spent at the day's highest CPMs — but these hours produced the conversions
~10:00 onwardConversions stop; $23 spent 10:00-15:00 for 1 LPV
~16:00-16:42Two more control ATCs land — the "dead afternoon" read was premature
18:35$147.48 spent, 1 purchase, control ROAS 0.78 and falling
Operator identifies Aug-29 is a Saturday — a second variable
Operator rejects spending further to disambiguate; agreed to revert to $100

PART 6 — Everything paused, with reasoning and retrospective

whatwhenreasoning at the timeretrospective
CUPID-R2 staticAug-27 21:34$6.36/ATC vs UFO's $4.20; 66% of day-1 spend on the worst CTR (3.93%)Defensible on the chosen metric. But it was buying impressions at $125 CPM and never got worse than $6.36/ATC — the control later hit $15.90
LOOKUP staticAug-27 21:34$6.37/ATC, worst CTR, 0 purchases on $19.11Had briefly shown the account's best $/LPV ($3.55) at ~$14 spend, which inverted as the sample grew — a small-sample mirage I initially reported as promising
Duplicate banner ad 120249662229150611Aug-27 21:28Same creative in two placesCorrect; my own sequencing error created it
b2g1 arm (4 ads)pre-launchOperator selected the save70 armHeld as the week-2 arm test
r2/r4/superseded (6 ads)pre-launchEarlier renders replaced
11 older campaignsAug-26/27Reduce to one clean test
V82 campaignnever activatedBanner ran inside V81 instead for a same-ad-set comparisonCorrect — a separate campaign would have been a dirtier test and doubled spend

The consequential one. Pausing both statics left the campaign with two cuts of one video.

Blended CPM went $141 → $238 → $266 and impressions fell 957 → 439 → 269. Statics were the

cheap-reach layer. This did not, however, explain the Aug-29 spend pattern — see Part 8.


PART 7 — The funnel: every fix, with verification

#problemdetailfixverified
1Checkout hid the offerShopify mobile renders the order summary collapsed — a cold buyer saw only "Order summary" and a number. No product, no quantity, no discountAnchor prices + automatic discounts so the saving appears on the payment screenRendered checkout in a real mobile browser
2Anchor pricing3-pack 67395347546416 $335.85 → $99.00 (−$236.85); single 67395347513648 $99.00 → $59.95 (−$39.05)API readback + live checkout
3Quantity overchargeDiscounts were fixed-amount with appliesOnEachItem:false — discount subtracted once per order while the anchor multiplied per unit. 3-pack ×2 charged $434.85 instead of $198.00Set appliesOnEachItem: true on both6 cart shapes re-tested: 3-pack ×1/×2/×3 = $99.00/$198.00/$297.00; single ×1/×2 = $59.95/$119.90; mixed = $158.95. No customer was ever affected — all funnel orders qty 1, no qty selector on the page
4Internal name leaking to buyersCheckout displayed RAW REVEAL V110 - 3 BOTTLES + FREE ROLL-ON (-$236.85) — Shopify prints the discount title verbatimRenamed to 70% Off Today - 3 Bottles + Free Roll-On and Today's Price - Single Bottle; tools/raw-offer-pricing.mjs corrected so a revert can't reintroduce themOrder summary expanded in a real browser: v110/RAW Reveal absent
5Shipping label contradictionDrawer promised FREE EXPRESS; checkout said EconomyDelivery profile 132870603056, holding only the two funnel variants, rate named FREE Express Shipping (2–4 days)node tools/raw-shipping-label.mjs verify
6Stale offer badgesUP TO 70% OFF contradicted the flat 70% claimRemoved0 remaining; 8 CTAs read GET 70% OFF TODAY
7Pixel fired too latePageView only after 30s or interactionsendBeacon PageView at a fixed 2,500ms, eid dedup key, _fbp/_fbc set incl. fbclid capture. Original 30s runtime loader left intactReal headless browser: one PageView at 2.73s, no interaction, zero JS errors
8Page speed regressionA 3-second tracking timer shipped and crashed live PSI to 71 / TBT 1,540msReverted within minutesPSI mobile 99/100/100/100, TBT 0ms; desktop 100/100/100/100; Core Web Vitals field data PASSED (LCP 2s, INP 162ms, CLS 0.02)

Discount node IDs: 3-pack 1616747659568 · single 1616747692336. Both ACTIVE, no end date.

24 code discounts exist and do NOT stack on these automatics — verified.

Funnel state now: click → LP (PSI 99, pixel at 2.5s) → drawer (offer visible) → checkout

(discount visible, correct name, free express labelled) → Shop Pay.


PART 8 — The open question: Saturday vs budget

Aug-29 broke a two-day pattern. $/ATC $6.11 → $6.13 → $11.60. ROAS 1.63 → 2.10 → 0.66.

Two variables changed simultaneously:

1. Campaign budget $100 → $175 at 02:20 PDT
2. Thursday/Friday → Saturday — the campaign's first weekend day

What the data can and cannot say

Purchase count proves nothing. At the Aug-27/28 rate (2.33/day), P(observing ≤1 purchase on a

given day) = 32%. One-versus-three is unremarkable.

Cost-per-ATC is the real signal — 13 events, not 1 — and it roughly doubled.

A single ad DOES absorb budget linearly. Hour-matched, the control ad only, hours 00:00-10:59

on both days:

Aug-28 ($100)Aug-29 ($175)ratio
spend$8.98$85.499.5×
impressions323109.7×
CPM$281$2760.98× — flat
ATC06

So budget does not inherently inflate cost. That kills the simplest explanation.

No weekend baseline exists. The account's only prior Saturday is Aug-08: $5.43 spend, 1 ATC.

Everything material changed since — creative, offer, checkout fix, pixel. Pre-Aug-27 days ran

different creative on a broken funnel ($/ATC $14-114). Nothing to compare against.

Agreed plan

Revert budget $175 → $100. At 18:35 the campaign had spent $147.48, already past $100, so this

also halts remaining Saturday spend. Saves ~$40 tonight + ~$85 Sunday ≈ $125.

Do not read Sunday. It differs from Thu/Fri on both weekend and budget.
Monday Aug-31 at $100 vs Thursday/Friday at $100 is the clean like-for-like weekday read.
Re-test $175 later on a weekday, with a wider creative base.
Begin accumulating a day-of-week baseline — the account has never had one.

Rationale for not spending to disambiguate: the same answer is available later for the same money,

on a weekday, with better creative. Buying it now on a ROAS-0.66 day is paying a premium for a

tidier chart.


PART 9 — Banner vs control: where the test actually stands

control (end card)banner (offer @ 0.0s)
spend$220.48$63.43
impressions934308
CTR7.39%9.09%
$/LPV$3.80$3.73
$/ATC$8.48$7.05
ATC269
initiated checkout71
purchases51
revenue$377.85$59.95

Both cleared the 10-ATC gate cumulatively. The banner leads every cost metric; the control leads

purchases — but has had 3.5× the delivery, so the purchase gap partly reflects budget share.

Day by day the story flipped repeatedly:

Aug-28 $/ATCAug-29 $/ATC
control$6.36$15.90
banner$6.98$6.77

Not resolvable while Aug-29 is confounded. Carry into the Monday read.

What the competitor evidence predicted: short ads (≤35s) place the offer at a median 0.0s,

5/5 within five seconds; GODA's longest-running live ad pins its offer and a Buy 2, Get 1 FREE

badge from frame 0 and never removes them. That predicted the banner should win. **Our own money has

not confirmed it.**


PART 10 — Competitive intelligence (Foreplay, 2026-08-28)

Four brands, 250-ad newest-first samples, all creatives opened and measured.

brandactiveindexedVIDEOIMAGEDCOkill speed
Hypnosis by Cupids4523,24491%9%0%9.8h / 31h
Goda Perfume3878,9988%30%62%mixed
IM823214,49410%90%~0%slow
SALT & STONE82512,44014%23%62%barely kills — 93% still live

10.1 Findings

Two operating models, no middle. Specialists (Cupids video / IM8 static) or DCO operators.
Cupids: one concept, ten lengths. Their ten longest-running live ads share the identical

headline "Secret to Attention 👉" and are ten different files at **14.88, 38.19, 39.27, 39.83,

40.75, 46.53, 46.95, 60.67, 74.88, 91.9s. Live range spans 7.99s–93.18s**.

Cupids kills on a schedule, not a curve — dead ads cluster at exactly 9.8h and 31h, no

3/5/7-day tail. Survivors from the same day run 94h+.

Cupids launches in bursts — ~152 ads on Aug-26, 7 on Aug-27.
Polish is not the winning variable. Cupids' survivors are phone-shot UGC: car selfies,

"testing pheromone cologne on my sisters hot friend", club footage, a screenshot of a review

captioned "The 500,000+ positive reviews weren't LYING".

GODA: the copy carries the sale. Their DCO static is a flat offer card — cream circle,

wordmark, LAST CHANCE, 50% OFF, two clipart alarm clocks. No product, no model. Attached to

~600 words of first-person advertorial signed "Michelle D."

GODA's video uses AI-generated dolls with cracked porcelain skin as a literal metaphor for

crepey skin, smoothing over a day-1→60 arc. No model, no shoot, no likeness rights.

GODA gives the discount a reason-why. Their longest-running live ad: *"We Made Too Much Body

Oil / PLEASE HELP US EMPTY OUR WAREHOUSE" + "Buy 2, Get 1 FREE"*, both pinned from 0.0s, over a

spoken apology: "I told you that was the best price you'd ever get — and then we overproduced."

Ours asserts 70% OFF TODAY ONLY with nothing behind it.

GODA statics are blunt pain-first — "F\*CK BEING 'JUST FRIENDS'", "Need A Relationship Spark?",

"Do Not Try This IF you enjoy being the only one making an effort" — plus hard price anchoring

($78 → $14/bottle) and review badges.

Salt & Stone — clean product photography, press borrowing ("AS SEEN IN MARIE CLAIRE"),

scarcity ("Mini set. Big waitlist." / "SOLD OUT 3X").

IM8 — restrained editorial, research-led ("You're Allowed To Stop Taking 12 Supplements").
30 seconds — our only length — is the length neither leader leans on.

10.2 Companion pages — confirmed

brandmodelpages
Cupidsfake editorialGents Secrets (categorised Magazine), Hypnosis by Cupids (categorised Musician/band, no website, 452 active vs main page's 199)
GODAinvented personasEmily The Fragrance Girl, Steve The Perfumer, Over 40 & Fabulous
IM8real authoritiesDr. James DiNicolantonio, Tim Gray, David Beckham (blue-verified), New York Post, Athleats Nutrition — plus 4 legitimate own-brand pages
Salt & Stonesingle page

Satellite pages demonstrably outrun motherships. All three flavours are available options; the

choice is the operator's.

10.3 DCO — investigated and closed

Foreplay's display_format: DCO means **any multi-asset creative, including plain placement

customization**. Proven symmetrically:

• Salt & Stone "pools": 720×1280 + 720×900 pairs, 2 of 3 identical in duration to six decimals.
• GODA "pools": byte-identical duplicate cards across 4 opened ads.
Our own ads: 11 of the newest 25 carry the DCO label. The UFO ad's two cards measure

720×1280 and 720×900 at identical 30.164042s with identical audio sha256.

There is no DCO gap. We have shipped the mechanism since V76. Do not reopen without new

primary evidence.

Boards published:

http://15.204.83.60/raw-chemistry/competitor-creatives/ · /raw-chemistry/offer-timing/


PART 11 — Everything learned

Full text in LEARNINGS.md. Complete list, grouped.

11.1 Offer and price

1. "FREE" trains Meta to find people who want free things. See Part 4.8. Cheap CPM is a

warning, not a win — a proposed rule to kill ads above $120 CPM would have killed every

profitable ad and protected every unprofitable one.

2. Higher price changes what a "bad" CAC is. AOV $72.97. CAC $43 against $73 AOV is a different

business from CAC $20 against $30. But breakeven CAC is still unknown without COGS.

3. An offer with a reason behind it beats a naked number (GODA evidence, untested for us).

11.2 Funnel

4. The offer must be visible at the moment of payment. Caveat carried: the famous "3 of 3 vs

5.3%" comparison used a double-counted denominator — IC fired twice (drawer + Shopify).

Real Aug-24 funnel: 129 LPV → 9 buy-button clicks → 1 purchase. Direction holds, magnitude was

inflated.

5. Promise-to-page continuity is a conversion gate. Stale badges, contradictory shipping labels,

hidden discounts — all fixable in an afternoon and worth more than a new creative.

6. Tracking must be verified in a real browser. Three false-negative traps: waiting <31s without

interacting; parsing ev= from a query string when Meta posts URL-encoded bodies; comparing

against a non-deferred page.

7. A dev-theme performance pass is not a live-site gate.
8. Fixed-amount discounts multiply wrong — test qty 2 and mixed carts.
9. Anything named that reaches Shopify is buyer-visible — discounts, shipping rates, delivery

profiles. No versions, run IDs or codenames.

10. The operator browses in CAD; the store and campaign are USD. Convert before diagnosing.

11.3 Creative

11. Format is not the variable; the specific creative is. We were wrong in both directions —

"video beats statics" (wrong on the metric that matters: statics bought LPVs at $1.53 vs $2.91

over 90 days) and then the UFO video beat both statics in V81.

12. Put the offer on screen from second zero — frame-verified across 40 competitor breakdowns.

Being tested; our own money has not confirmed it.

13. One concept, many lengths — Cupids' ten survivors, 7.99s–93.18s.
14. Polish is not what wins.
15. The copy can carry the sale — GODA's flat offer plate + 600-word advertorial.
16. Pain-first, named explicitly.

11.4 Measurement and decision-making

17. Add-to-cart is the decision currency, not purchases. ~20 ATC/day vs ~3 purchases.
18. Small samples produce confident mirages — four times in one week: LOOKUP's $3.55/LPV; the

banner's 29.6% CTR on 27 impressions; a "dead afternoon" that revived; a "$16.49/ATC" alarm that

was a partial-day artifact.

19. Never compare a partial day to a full day. Cost-per-outcome inside a partial day is not a

rate — impressions land before conversions.

20. A token's prefix does not tell you its lifetime — trust expires_in, never shpat_.
21. Budget scales linearly for a single ad — 9.5× spend → 9.7× impressions, CPM flat.
22. The learning phase is unreachable at this budget (~17 purchases/wk vs ~50). Never argue

from it.

23. Meta overdelivers the daily budget (+34% observed) and repays across the week. Spend pacing

is a multi-day system.

24. Verify by readback; never trust the write response. updated_fields echoes the request.
25. Reconcile revenue against the store by price — Shopify says direct for everything.
26. Check the activity log before explaining any delivery change.
27. Narrowing a campaign raises blended CPM — but does not explain day-to-day pacing.

11.5 Platform mechanics

28. Advantage+ Audience ≠ Advantage+ Creative. Audience is a delivery control, stays ON.

Creative mutates the ad — all 17 OPT_OUT.

29. Enhancements default ON if degrees_of_freedom_spec is omitted.
30. Placements default to Advantage+, which delivered us to Audience Network rewarded video,

WhatsApp status, Threads, Messenger. Pin FB+IG explicitly.

31. advantage_audience: 1 demotes age limits to suggestions.
32. self_ai_disclosure is immutable after creation.
33. Numbers in documentation carry their original context — an age_min: 25 was lifted from a

doc describing a UI dropdown limitation and applied as strategy.

34. Foreplay's DCO label = multi-asset creative, including placement customization.

11.6 Research method

35. Longevity is a proxy for profitability, not a measurement. Foreplay exposes no ROAS.
36. Competitor ad counts are not creative output.
37. Model-generated timestamps need frame verification — Gemini writes end = runtime for

anything that reads persistent. One badge claimed 0.0→31.209s; pixels show it gone by 6.9s.


PART 12 — Mistakes made, and how each was caught

Recorded because the pattern repeats and recognising it early is worth more than any single finding.

#mistakehow it was caughtrule adopted
1Claimed the LP had no trackingRepo had already documented and corrected this oncePrimary source before assertion
2"Video beats statics 2:1"Inherited from a handoff; 90-day data inverted it on cost/LPVNever inherit an unmeasured claim
3Picked the wrong static set from filenamesOperator: "that's the old run"Folder names lie; sort by mtime
4age_min: 25 from a UI-limitation docOperator: "18-65 is fine why did you do 25"Read the surrounding sentence
5AI enhancements left defaulted ONOperator asked "no creative enhancements?"Set every field explicitly
6Swept advantage_audience to 0Operator corrected — A+A must stay on"No AI flags" = creative AI
7Proposed a CPM>$120 kill ruleOperator: "we aren't saying free anymore"CPM describes who, not how well
8Shipped a 3s tracking timer → PSI 71Live PSI re-measureDev-theme pass is not a live gate
9Prevalence-as-proof on DCO — twiceOperator asked "is it genuinely more effective?"Presence ≠ performance
10Said shpat_ = permanent, "revoked not expired"The exchange returned expires_in: 86353Trust expires_in, not the prefix
11Blamed sandbox for exit 144It was pkill -f matching its own shellNever pkill -f a pattern in your own argv
12"The CLI hangs on auth"app list doesn't exist in CLI 4.6.1 — subcommand error misreadVerify the command exists before diagnosing
13Blamed campaign narrowing for front-loaded spendOperator: "yesterday had no statics either"Verify the cause actually changed
14Blamed multi-day pacing for the same thingActivity log showed the budget had been raisedCheck the change log first
15"CPM rises with budget"Hour-matched data showed CPM flat at 9.5× spendNever compare partial vs full day
16Called the afternoon deadTwo ATCs landed an hour laterDayparts can't be judged intraday
17Wrote a decision rule ignoring the weekdayOperator: "it's also Saturday"Enumerate variables before committing a rule
18Proposed spending ~$85 to disambiguateOperator: "so just waste money lol"The same answer is often available later, cheaper

**The dominant pattern: reaching for a plausible mechanism instead of checking whether the

suspected variable actually changed.** Items 13, 14, 15 and 17 are all the same error.


PART 13 — Tools built (all in tools/, all runnable)

toolwhat it does
shopify-oauth-paste.mjsPKCE paste-back OAuth for a headless host. Defaults to our own app; --cli falls back. Writes a .meta.json sidecar with real expires_in
shopify-token-health.mjsStructure + liveness + granted scopes; reports hours remaining, warns <6h. life OFFLINE = permanent
shopify-token-receive.mjsOne-shot paste form for an Admin API token — random path, verifies before storing, exits after one success
shopify-admin.mjsGeneric Admin GraphQL runner
raw-offer-pricing.mjssnapshot / apply / revert anchor prices + automatic discounts. Titles are customer-facing
raw-shipping-label.mjsCreates/verifies the surgical delivery profile
raw-pixel-verify.mjsVerifies the Meta event sequence through the funnel
raw-funnel-walk.mjs · funnel-walk-audit.mjsFull instrumented walk at iPhone viewport
audit-page-tracking.mjsDoes the page actually fire tracking? Documents the 3 false-negative traps
raw-trust-signal-audit.mjsWhere does a given string actually appear on the live page?
shopify-theme-file.mjsRead theme files into a local directory
history.mjsThe append-only ledger — record / validate
brands/raw-chemistry/scripts/analyze_competitor_offer_timing.pyOffer-timing analysis over Gemini breakdowns
brands/raw-chemistry/scripts/render-ufo-banner-2026-08-27.shRenders a banner master through the house chain

Skills created

skillcovers
build-meta-ad-objectsEvery campaign/ad set/ad/creative build. The Advantage+ split, broad targeting, placement lock, dark posts, self_ai_disclosure, plus scripts/verify-ad-objects.mjs which asserts the whole config from readback JSON and exits non-zero on failure
connect-shopify-admin-apiPermanent tokens on a headless host: PKCE paste-back, why the CLI client gives 24h tokens, the empty redirect_urls trap, fixing app config via CLI deploy, plus references/traps.md indexed by error string

PART 14 — Blockers (all operator inputs)

1. COGS / fulfilment / payment fees / refund reserve. Without it there is no breakeven CAC.

At $72.97 AOV:

| contribution margin | breakeven CAC |

|---|---|

| 70% | $51.08 |

| 60% | $43.78 |

| 50% | $36.48 |

| 40% | $29.19 |

Measured CAC has run $34.76 → $150+. At 50% margin the account is roughly breakeven; at 40%

it is losing money; at 70% it has room. **This single number converts every scale decision from

opinion into arithmetic.**

2. A true reason-why for the 70% — overstock, batch sellthrough, packaging changeover, 3-pack

launch inventory. Must be genuinely true; it is checkable by customers.

3. Confirm the 02:20 Aug-29 budget change was intentional — made via MCP, not in-session.
4. Go-forward budget — hold $100, or a step plan.

PART 15 — Next actions, in order

1. Revert budget $175 → $100 (pending operator go — recommended tonight, saves ~$125).
2. Let Sunday run. Do not read it — confounded on both weekend and budget.
3. Monday Aug-31: full-day $/ATC vs the Thu/Fri $100 baseline. Answers budget-vs-weekend and

resolves the banner test.

4. Build width (ADS-PLAN.md Phase 1): UFO at 12s and 60s alongside 30s; revive a static.

Target 5-8 distinct live ads before any further budget increase.

5. Phase 2: long-form advertorial copy behind a cheap offer plate; reason-why offer variant;

pain-first sharpening of the next static batch.

6. Phase 3: repurpose V82 as a $50/day testing campaign, 5-7 new ads/week, promote at 10 ATCs.
7. Only then step budget +20-30%, 2-3 days per step, judged on full-day $/ATC.

PART 16 — Standing rules (do not relitigate)

Advantage+ Audience ON (advantage_audience: 1). Advantage+ Creative OFF (17 × OPT_OUT).
• Age 18-65, US, broad. No interests, behaviours, lookalikes, custom audiences.
FB + IG only — forced by adapt_to_placement: OPT_OUT and native-master authoring.
self_ai_disclosure omitted entirely, forever.
Dark posts only.
Verify by readback, never the create/update response.
Judge on cost-per-ATC; confirm on purchases later.
No kill/promote decision below ~10 ATCs per arm.
Never compare a partial day to a full day.
Risk/compliance analysis is pull-only — the operator will ask for it.
• Record every material change: node tools/history.mjs record --workstream ads.

Reproduction commands


node tools/shopify-token-health.mjs                    # expect: life OFFLINE
node tools/raw-shipping-label.mjs verify               # delivery profile 132870603056
node tools/history.mjs validate                        # ledger integrity
node ~/.codex/skills/build-meta-ad-objects/scripts/verify-ad-objects.mjs < readback.json
node tools/shopify-admin.mjs '{ shop { name currencyCode } }'

Published copy: http://15.204.83.60/raw-chemistry/handoff/

Source of truth: this file, in the repo.

⬇ .md