← Back to sitev3 — BUILT & LIVE

Popup → PushPress → ChaseLead Capture & Conversion System

Every "Free Trial" CTA now opens an on-site popup, captures the lead (name, email, phone), pushes them into PushPress via Zapier, and redirects them into the existing PushPress booking flow. Anyone who doesn't progress shows up on the Lead Chase dashboard for a phone call.

✓ Popup live site-wide✓ TrialLead entity✓ /lead-chase dashboard⚠ Needs: Klaviyo rescue flow + welcome email rewrite

What you need to do (in order)

🎉 ZERO new Zaps required

We capture lead details on our popup → write to TrialLead → redirect them to PushPress's own signup flow (with name + email pre-filled in the URL). PushPress handles its own account creation. Your existing linkTrialAttribution, referralAttended and markMemberConversion Zaps fire when they finish PushPress and mirror back to TrialLead. No new Zaps anywhere.

  1. Lead capture — done

    Popup captures name/email/phone + "who is this for?" (self / child / teen). For kids/teens we explicitly ask for the PARENT'S phone — so phone numbers always land in Klaviyo.

  2. PushPress handover — done

    After submit, popup redirects to PushPress with ?first_name=...&email=... pre-filled. User finishes the proper PushPress flow (including parent/child structure for kids).

  3. Status mirror back to TrialLead — done

    Your existing trial-signup, check-in and paid-conversion Zaps already feed the Lead Chase dashboard. Match key is email.

  4. 1

    Rewrite the PushPress welcome email

    Replace app-download CTA with "Book your free class" + explain the one-time-code login.

  5. 2

    Update Google Ads conversion

    The new on-domain generate_lead event fires when the popup is submitted. Add it as a Google Ads conversion. See section below.

  6. 3

    Slot the recovery sequence into your existing Klaviyo flows

    You said you already have several flows — slot the T+0 / T+1hr / T+24hr touches into the right ones (template below).

  7. 4

    Open /lead-chase every morning

    Work through the "Call today" bucket. This is the highest-ROI 15 minutes of your day.

What to expect

Leads in CRM

2–3×

We now capture people who'd previously click "Free Trial" but never finish PushPress.

Trial classes booked

+10–20%

The popup adds a step; the Klaviyo follow-up + phone chase recovers most who'd otherwise be lost.

Members from chase calls

+5–10/mo

Realistic. Call ~30 leads/week from the dashboard, expect 1-in-10 to book.

USER taps "Book Free Trial" anywhere on site
                 │
                 ▼
       ┌─────────────────────┐
       │  Popup opens        │  ← <TrialLeadPopup /> in layout
       │  4 fields, no nav   │
       └─────────┬───────────┘
                 │ submit
                 ▼
   ┌─────────────────────────────┐
   │  /functions/createTrialLead │
   │   1. dedupe email (24h)     │
   │   2. write TrialLead row    │
   │   3. POST to Zap A          │
   │   4. fire GA4 generate_lead │
   └──────────┬──────────────────┘
              │
   ┌──────────┴──────────┐
   ▼                     ▼
USER redirected      Zap A "Catch Hook"
to PushPress             │
plan URL                 ▼
   │                  PushPress "Find Person"
   ▼                     │
PushPress one-time       ▼ (if not found)
code login →          PushPress "Create a Person"
pick a class             │
   │                     ▼
   │           PushPress has a lead with full attribution
   │
   ▼ (any events from now on…)
PushPress fires triggers:
  • New Person → Zap B → updateTrialLeadStatus(person_created)
  • Subscription to free trial → Zap B → trial_registered
  • Check-In       → Zap B → checked_in
  • Paid subscription → Zap B → subscribed_paid
                          │
                          ▼
                /lead-chase dashboard
                shows them in the right bucket

The dashboard automatically categorises every lead into one of these buckets based on the data we receive back from PushPress via Zap B.

🔴 Call today

Filled the popup but never registered for the free trial plan in PushPress and submitted 2+ hours ago. They bailed somewhere between our form and PushPress's one-time-code login. Hot lead. Call immediately.

🟠 No-show — call this week

Registered for the free trial plan but never showed up to a class in 7+ days. Friendly check-in: "we noticed you didn't make it in — want to pick another time?"

🟢 Attended — close the sale

Came to a trial class but didn't sign up for a paid membership within 3 days. Highest-ROI call of the three. They've already met you.

How "called today" works

Each row has Call / Text / Email buttons + outcome logging (Booked, No answer, Voicemail, Reschedule, Not interested, Wrong number). After logging an outcome, the row hides for 24 hours so you don't accidentally call the same person twice. Toggle off "Hide called today" to see everything.

Your old conversion event likely fired on the PushPress booking page (or on click). With the new flow, we should fire conversions from our domain on the popup submit — far more reliable and earlier in the funnel.

What the code now sends

When the popup is submitted, we fire:

gtag('event', 'generate_lead', {
page, source, medium, campaign
});

✅ Decision: direct via gtag (not GA4 import)

Real-time signal to Smart Bidding (vs 24–48hr lag for GA4 import), simpler attribution, fewer hops. The generic GA4 generate_lead event still fires too — so GA4 import remains available as a fallback if you ever want it.

Step 1 — Create the conversion action in Google Ads

  1. Open Google Ads → Tools (spanner icon) → Conversions → Summary.
  2. Click the blue + New conversion action button.
  3. Choose Website as the source.
  4. Enter your domain (basingstokeboxing.com) and click Scan.
  5. When the scan finishes, click + Add a conversion action manually (don't pick an auto-detected event).
  6. Fill in the form:
    • Category: Submit lead form
    • Conversion name: Trial Lead — Popup Submit
    • Value: Use the same value for each conversion5 GBP
    • Count: One (one lead per click — we don't want repeated submits to multi-count)
    • Click-through conversion window: 30 days
    • View-through conversion window: 1 day
    • Attribution model: Data-driven (or "Last click" if data-driven isn't offered yet)
    • Include in "Conversions": Yes (this is what makes it Primary — the main optimisation target)
  7. Click Done → Save and continue.

Step 2 — Get the conversion ID

  1. On the next screen choose Use Google tag (NOT Google Tag Manager — assuming gtag is already on the site, which it is).
  2. Pick Install the tag yourself.
  3. Scroll to the Event snippet section. You'll see code like this:
    gtag('event', 'conversion', {
    'send_to': 'AW-123456789/AbCdEfGhIjK',
    'value': 5.0,
    'currency': 'GBP'
    });
  4. Copy the bit highlighted in yellow — that's your conversion ID (AW-XXXXXXXXX/YYYYYYY format).
  5. Click Done.

Step 3 — Paste the ID into our config (this is where it goes live on the site)

  1. Open lib/leadCaptureConfig.js.
  2. Find the GOOGLE_ADS_CONVERSION block:
    export const GOOGLE_ADS_CONVERSION = {
    id: '', // ← paste here
    value: 5.0,
    currency: 'GBP',
    };
  3. Paste your AW-XXXXXXXXX/YYYYYYY string between the quotes on the id line.
  4. Save and redeploy. That's it — the popup now fires the Google Ads conversion directly on submit.
  5. Leave it as '' (empty) if you want to pause the direct fire — the generic generate_lead event still fires for GA4 reports.

Step 4 — Verify it's working (do this within an hour of going live)

  1. Install the Google Tag Assistant Chrome extension.
  2. Open basingstokeboxing.com/?gclid=test123 in an incognito window.
  3. Click any "Free Trial" button → fill the popup with a test email → submit.
  4. Tag Assistant should show two events firing:
    • generate_lead (GA4)
    • conversion with your AW-… send_to
  5. In Google Ads: Tools → Conversions → click your "Trial Lead — Popup Submit" action. Status should change from No recent conversionsRecording conversions within ~30 mins.
  6. After 24h, check the conversion count appears in your campaign reports.

Step 5 — Clean up your existing conversions

You probably still have older click-based conversions configured. Tidy them up so Smart Bidding only optimises the right ones:

  • Demote the old free_trial_booking_clicked (clicks, not submits) → set to Secondary. Don't delete — keep it as a backup signal.
  • Keep your existing Zapier offline-uploaded conversions (trial_registered, trial_attended, member_converted) as Primary.
  • End state: 4 Primary conversions firing the cascade (see table above).

Why this is better

The old free_trial_booking_clicked fired on click — but only ~22% of clickers actually finished PushPress, so Google was optimising for clickers, not signers. The new generate_lead only fires when someone actually completes the form. Higher signal-to-noise. Combined with the offline upload of real paying members, Google has the full quality signal.

The full conversion cascade (recommended)

You already upload offline conversions via Zapier for trial signup, attendance and paid membership. Adding the on-site generate_lead at the front gives Smart Bidding a fast learning signal — without it, the algorithm waits 7–14 days for paid signals and burns budget on low-quality clicks in the meantime.

EventFires whenSourceValueType
generate_leadPopup submitted (instant)On-site (gtag)£5Primary
trial_registeredFinishes PushPress signupOffline (Zapier)£15Primary
trial_attendedShows up to first classOffline (Zapier)£25Primary
member_convertedBuys paid membershipOffline (Zapier)£300Primary

Why £5, not £0?

Google ignores £0 conversions when calculating Smart Bidding signals. £5 is enough to register interest but low enough that it can't swamp the higher-value paid signal.

Why £300 for a member?

Rough 3-month LTV (£100/mo × ~3 months avg tenure at the top of funnel). Tweak based on your actual numbers from /channel-roi.

All 4 set as Primary?

Yes — Google Ads sums Primary conversion values for bidding. Setting all four as Primary lets it optimise toward the full funnel value, weighted naturally by the £-amount.

Dedupe between online + offline?

Not needed — these are separate conversion actions. Same person hits each one once max. Google counts them all because each represents real funnel progress.

GCLID matching — already wired ✅

The popup captures gclid + fbclid on submit → linkTrialAttribution matches them back to BookingClickTrialSignup.gclid + click_time are set automatically. Your existing Zapier offline-upload flows have everything they need (Google Ads API requires both gclid + click_time).

Decision: we capture, then hand off. We do NOT create PushPress accounts via Zapier.

Earlier draft of this plan had a "Zap A — Website Lead → PushPress Person" step. We removed it.

Why

  • Kids/teens trials. In PushPress, the parent owns the account and the phone number lives there. If we create the kid's account directly via Zap, the phone number ends up on the wrong record (or missing entirely) — which is why Klaviyo profiles for kids leads keep arriving phoneless.
  • PushPress's own signup handles parent/child correctly. When the parent fills it in themselves, they're prompted to add a related child. Account structure is right by default.
  • Less Zapier surface area. One Zap removed = one fewer integration to maintain when PushPress changes their schema.
  • Tiny UX cost. User re-enters name + email (~10 seconds). We pre-fill those fields in the redirect URL, so on PushPress they're already populated.

How it works now

  1. User clicks any "Free Trial" CTA → popup opens.
  2. Popup asks who the trial is for — Me / My child / My teen.
  3. If kid or teen, popup shows a yellow banner: "Enter YOUR (parent's) phone & email — not your child's." Plus a field for the child's first name (saved to TrialLead notes).
  4. Submit → createTrialLead writes the row, fires GA4 generate_lead, fires Klaviyo (via your existing PushPress→Klaviyo Zap when they complete PushPress, or directly if you want belt-and-braces).
  5. Browser redirects to PushPress signup URL with ?first_name=...&last_name=...&email=...&phone=... pre-filled.
  6. User completes PushPress signup themselves (correctly structured for parent/child).
  7. Your existing linkTrialAttribution Zap fires when PushPress notifies "new person / trial started" → flips in_pushpress + registered_for_trial on the matching TrialLead (matched by email).

What this kills

  • The ZAPIER_LEAD_WEBHOOK_URL secret is no longer used. Safe to ignore or delete.
  • The earlier "Zap A — Catch Hook → Create Person" Zapier flow is no longer needed. If you started building it, delete it.
  • Phoneless-kids problem in Klaviyo: solved at source. The popup forces parent's phone on every kids/teens lead.

Quick map of your existing 5 flows and what changes:

Existing flowTriggered when…Action
Flow 1 — Free Trial WelcomeProfile registers for free trial in PushPress (now: `plan` set)Keep as-is — fires when they finish PushPress
Flow 2 — Post-Class ConvertClass Attended metricKeep as-is
Flow 3 — New Member Onboarding`plan` becomes paid Member planKeep as-is
Flow 4 — Win-Back Lapsed`status` ≠ activeKeep as-is
Flow 5 — 30-day No-Show CampaignQuarterly segment sendKeep as-is
+ NEW: Popup Lead RescueProfile created from popup (Klaviyo `plan` still empty)Add this one

Why the new flow exists

Flow 1 only fires when someone registers for the free trial in PushPress (the moment `plan` gets set in Klaviyo). The new popup creates a Klaviyo profile before that — so we now have a brief gap (popup submitted → PushPress not yet) that nothing covers.

The Popup Rescue flow only sends to profiles where `plan` is still empty. The second `plan` populates (they finish PushPress), Flow 1 takes over and Rescue stops — no duplicate touches.

Popup Rescue — quick summary (4 touches)

  • 📧 T+0 email — "Almost there — here's how to finish" (explains the one-time code)
  • 📱 T+1h SMS — "Got stuck? Reply and we'll book you in"
  • 📱 T+24h SMS — Personal text from Liam offering to book them in directly
  • 📧 T+72h email — Final "no pressure" with phone number

Full HTML + SMS copy is on the Klaviyo Flow Guide page — it's the first flow listed.

How the popup profile reaches Klaviyo

Two options — pick whichever is easier:

  1. Easiest (recommended): Once Zap A creates the PushPress Person, your existing PushPress→Klaviyo sync auto-creates the Klaviyo profile. The Popup Rescue flow's trigger becomes "Profile Created" (same as Flow 1). The Flow Filter `plan is empty` keeps the two flows from clashing.
  2. Belt-and-braces: Add an extra Zapier step on Zap A: after "Create PushPress Person", add "Klaviyo → Create or Update Profile". Useful if PushPress→Klaviyo sync is ever delayed.

How Lead Chase + Klaviyo work together

Klaviyo handles the gentle 4-touch automated nudge. The Lead Chase dashboard surfaces the highest-priority leads for phone calls. A "Call today" lead is also getting Klaviyo emails — that's fine, the call is the conversion. The dashboard call notes are your record; Klaviyo runs in the background.

You're live. Next:

  1. This week: Rewrite PushPress welcome email + add Google Ads generate_lead conversion.
  2. This week: Slot the T+0 / T+1hr / T+24h touches into your existing Klaviyo flows.
  3. Every morning: Open /lead-chase. Work the red bucket.
  4. Optional cleanup: Remove the unused ZAPIER_LEAD_WEBHOOK_URL secret and any "Catch Hook → Create Person" Zap. Capture-then-Passthrough doesn't use them.
Call