marketing

Paid acquisition — action items & what to watch (2026-06-11)

TL;DR: The funnel is fixed and verified. Direct/organic visitors engage normally; paid clicks (YouTube + FB) do not consumeconsumed% ≈ 0 even now that the paywall is gone. The bottleneck is ad quality/intent, not the site. Everything below is what's left — almost all of it is in Ads Manager, not the code.

North-star metric: consumed% by source on the Paid acquisition dashboard. It is the % of sessions that actually pressed play / listen / read. Today it's ~0 on paid. The whole game now is getting that number off zero.


🔴 DO NOW — Ads Manager (highest leverage first)

  • Fix the Meta Pixel ID mismatch (the real reason it shows "no activity"). The site code fires pixel 1421912249452225 (NEXT_PUBLIC_FB_PIXEL_ID), but your ads + Events Manager dataset use 976627715239476. Different pixels, so the dataset never sees the site's events. The pixel base code IS installed (FacebookPixel.tsx, mounted in layout.tsx) — it's just pointed at the wrong ID. Don't use the "Set up Web Events" dialog or Conversions API; this is config, not installation.
    • Fix (Vercel → frontend env, then redeploy):
      NEXT_PUBLIC_FB_PIXEL_ID=976627715239476
      NEXT_PUBLIC_FB_PIXEL_HOSTNAME=graphene.fm
      
      The HOSTNAME gate fires the Graphene pixel only on graphene.fm (graphene.fm + hivejournal.com share one Vercel deploy), so Meta's lookalike is built from real Graphene listeners, not mixed HiveJournal traffic.
    • ⚠️ Confirm first: if hivejournal.com runs its own FB ads on 1421…, this change stops HJ's pixel (one deploy = one pixel env). If so, ask for per-host pixel mapping in code instead.
    • Verify: Events Manager → Test Events → enter https://www.graphene.fm → browse → confirm PageView fires for pixel 976….
    • Why it matters: without the right pixel firing, Meta optimizes for the cheapest click (your 3-second-bounce traffic). This is the single biggest FB lever on consumed%.
  • Switch YouTube objective from views/awareness to Traffic → "Landing page views" (or Conversions) so Google buys people who actually land and stay, not cheap impressions/clicks. Right now: 222 YouTube sessions → 0 consumed.
  • Exclude Audience Network placements on Meta (junk / accidental clicks).
  • Point ALL ads at the season page, not /listen or the homepage. Destination format (per show): https://www.graphene.fm/seasons/<SEASON_ID>
    • NYFB: https://www.graphene.fm/seasons/0f80c02a-1855-42bc-bd9b-6ee2d55a6b0e
    • The Offline ("Blackout Logs"): https://www.graphene.fm/seasons/40c7d47b-4102-4a21-95e1-7ae73aa61d26
  • Re-scrape the FB destination so the share-image fix (robots.txt, shipped) takes: Facebook Sharing Debugger → paste the season URL → Scrape Again → then re-publish the stuck ad (clears the "Image Wasn't Downloaded" error).
  • Watch 3–5 Session Replays of YouTube/FB landers (PostHog → Session replay). Confirm whether it's accidental clicks, an in-app-browser issue, or a creative→landing mismatch. Do this — it's the fastest "what's really happening" check.

UTM tagging for new/edited ads

Put this in Meta's ad-level "URL parameters" field (auto-fills per ad):

utm_source=fb&utm_medium=paid&utm_campaign={{campaign.name}}&utm_content={{ad.name}}&utm_term={{placement}}

YouTube equivalent: utm_source=youtube&utm_medium=paid&utm_campaign=...&utm_content=... Don't double-tag — UTMs go in either the URL params field or the destination URL, never both.


✅ DONE — verify still true

  • POSTHOG_KEY set on Railway backend — confirmed working (server-side signin_completed via oauth_callback is firing). Server-side conversions (subscription_active, episode_tip_paid) will now register when they happen.
    • Value: POSTHOG_KEY=phc_kntvSXmtrgmE2FgWfTiYqRBVV7sVZPQqhUJgtdidKZkU
    • POSTHOG_HOST=https://us.i.posthog.com
  • Spot-check actual paid revenue in Stripe / the subscriptions table — the earlier "0 subs" was a tracking blind spot; confirm whether real subs/tips exist that PostHog couldn't see before the key was set.

📊 WATCH — your scoreboard (PostHog project 378637)

How to read it / what "working" looks like:

  • consumed% on paid sources lifts off 0 → the ad changes are buying real listeners. ✅
  • paywalled% stays near 0 → the 3-free-chapters fix is holding (cold visitors not walled).
  • median_dwell_sec climbs above 0 → fewer instant bounces.
  • If consumed% stays ~0 after the pixel + objective changes → the creative or audience is the problem, not placement; iterate on hooks/targeting.

🎨 Brand assets for ad creative (CapCut / overlays)

Reusable hosted assets — drop straight into a video editor:

  • Logo lockup (hex + GRAPHENE + .fm), transparent PNG — the one to use for ad end-cards / watermarks: https://www.graphene.fm/api/brand/graphene-logo (1400×360, white wordmark + purple .fm, transparent bg — sits cleanly over dark footage. Route: api/brand/graphene-logo.)
  • Hex mark only — transparent SVG: https://www.graphene.fm/favicons/graphene.svg (or opaque 180×180 PNG app-tile at /api/icons/graphene — has a background box, so prefer the lockup or SVG for overlays).
  • Wordmark spec (if typing it in CapCut instead): GRAPHENE in Inter Bold, all caps, white, letter-spacing ~0.15em, with a smaller purple (#a78bfa) .fm.

🚢 SHIPPED THIS SESSION (code — already live, no action needed)

The whole downstream funnel was rebuilt and deployed. For the record:

PRFix
#531Cold-ad homepage hero no longer dead-ends + warns on dropped server events
#532First 3 chapters always free (cold visitors get a real taste before any wall)
#533Top Graphene+ perks surfaced on the locked-chapter card
#534/listen paid LP: poster is now a giant tap-to-play button
#535robots.txt allows /api/og/ so Meta/social can fetch share + ad images

Verified live: paywall stopped firing for cold traffic after deploy; direct/organic visitors consume normally on the same pages. The machine works — it needs better fuel.


🔮 LATER / optional

  • New trailer for the paused YouTube ad (or run it pointed at /seasons/<id> — the cold-ad hero falls back to the first free chapter's audio, so it doesn't strictly need a trailer).
  • If short paid seasons ever ship, add a "keep the last chapter walled" guard (today the 3-free pilot makes any ≤3-chapter season fully free).
  • Tune the free-pilot width (ALWAYS_FREE_THROUGH_EPISODE, currently 3) once there's real conversion data.

Generated from the 2026-06-11 funnel + PostHog analysis session. Re-pull anytime by asking to "re-pull PostHog" — the queries live in this session's history.

2026 06 11 Paid Acquisition Action Items — Docs | HiveJournal