Quote Seguros — Pixel Integration Case Study

Real-world reference for integrating the Relo Pixel into a Next.js lead-gen site. Every step, file, and event described here is live in production at quote.miami.

Why this matters. Quote is a lead-gen funnel (not e-commerce, not mobile app). It proves the same pixel that tracks purchases on Samsung can track form submissions on a static Next.js site. The same infra serves both verticals without code changes — only pixel configuration differs.

1. The stack at a glance

ComponentTechPurpose
SiteNext.js 15 on Cloudflare PagesStatic + SPA navigation, 30+ city landing pages (EN + ES)
Pixelp.relo.mx/r.jsLoaded once in root layout via ReloPixel component
Lead captureMulti-step React formFires relo('lead', ...) on successful submit
City pagesCityViewTracker componentFires view_product on each city landing
Attributiont.relo.mx/c/demoquotePartner click wrapper → Redis → resolved on lead_submit
AnalyticsRelo admin + partner portal/c/quote/leads, /p/quote/leads

2. Files that matter

components/ReloPixel.tsx

Single file that owns pixel lifecycle. Three exports:

Critical: effect ordering. React runs child effects before parent effects. Without the ensureReloQueue() shim in ReloPixel.tsx, a CityViewTracker mounted inside a page would try to call window.relo(...) before the root layout's <ReloPixel /> has initialized the runtime. The shim pushes calls to a queue that the async r.js runtime drains once loaded.

components/CityViewTracker.tsx

'use client'
import { useEffect } from 'react'
import { trackCityView } from './ReloPixel'

export default function CityViewTracker({ city, language = 'en' }) {
  useEffect(() => { trackCityView(city, language) }, [city, language])
  return null
}

Mount on every city landing page:

<main>
  <CityViewTracker city="Aventura" language="es" />
  <StructuredData ... />
  ...
</main>

components/MultiStepForm.tsx

Fires trackReloLead in two spots:

trackReloLead({
  zip: data.zip,
  locale,
  sessionId: sessionIdRef.current,
  timeOnPageSeconds: timeOnPage,
  formStartToSubmitSeconds: formTime,
  stepsCompleted: Array.from(stepsCompletedRef.current).sort().join(','),
  abVariant,
})

app/layout.tsx

Root layout imports + mounts <ReloPixel /> — this covers every route including SPA navigations (pixel listens for pathname changes and fires page automatically).

3. Event map

EventFires whenProps captured
page_viewRoute change (auto)path, title, utm, ref
view_productCity landing page mountproduct (city), product_category, city, language
form_startFirst form focus (auto)form_id
form_submitForm submit event (auto)form_id, field count
form_abandonpagehide with dirty form (auto)form_id, fields filled
lead_submitSuccessful API responseproduct, form_id, stage, lead_value, currency, x_zip, x_locale, x_session_id, x_ab_variant, eh, ph
lead_stage_updateClient-side stage change (rare)new_stage, form_id

Plus ~50 auto-captured UX + bot signals: scroll, click, rage_click, copy, autofill_detected, keystroke_rate, net_quality, battery_state, web_vitals, etc.

4. Backend configuration

Supabase state

-- clients
id=5, name='Quote', slug='quote', tracking_type='pixel'

-- client_pixel_config (client_id=5)
allowed_domains=['quote.miami', 'www.quote.miami']
consent_required=false
jurisdiction='mx'
consent_defaults=15  (bits 0-3: analytics, personalization, dsp, cross-client)

-- partner_clients
partner_id=30 (Quote Demo Partner), client_id=5, status='active'

-- campaigns
id=8, name='Quote Auto Insurance - Demo', client_id=5, tracking_type='pixel'
slug='quote-auto-demo', status='active'

Click wrapper KV (Cloudflare)

-- Namespace: 0b04030f85724c3e8d118e3a9efbe2ee (SHORT_URLS)
-- Key: demoquote
-- Value:
{
  "url": "https://quote.miami?utm_source=relo-demo",
  "pid": 30,   // partner_id
  "cid": 5,    // client_id
  "aid": 8     // campaign_id
}

Tracking link: https://t.relo.mx/c/demoquote → 302 to quote.miami with _relo_cid cookie set. On lead_submit Go backbone reads the cookie, looks up Redis click cache, populates partner_id + campaign_id server-side.

5. Configure a new pixel partner via admin UI

  1. Open /c/quote/partners
  2. Click "Add Pixel Partner"
  3. Fill in the 3-section modal:
    • Partner — create new or link existing, enter company name
    • Campaign — create new or pick existing, enter slug
    • Tracking URL — short code + destination URL
  4. Submit. Atomically creates: partner + partner_clients + campaign + partner_campaigns + KV entry.
  5. Partner receives the t.relo.mx/c/XXXXXX link to promote.

6. Commission rates per conversion

For lead-gen clients, commission is per-event (not per-revenue). Configure via PartnerLeadRatesModal:

Specificity: stage-specific rules beat generic ones. Older rates remain in DB for historical commission calculations.

7. Reporting views

RoleURLShows
Admin/c/quote/dashboardSessions, conversions, funnel, cities, campaigns
Admin/c/quote/leadsAll conversions, CSV export, stage + product filters
Admin/c/quote/auditLive events stream, event type breakdown, heatmap
Client user/client/quoteSessions, conversions, funnel — no partner/commission info
Partner/p/quotePer-campaign sessions, leads with hash prefixes, CSV export

8. Verification commands

# Confirm client config
curl "$SUPABASE_URL/rest/v1/clients?id=eq.5&select=id,name,slug,tracking_type" \
  -H "apikey: $SUPABASE_KEY"

# Confirm pixel events flowing
ssh root@178.156.195.219 "clickhouse-client -d relo -q \\
  \"SELECT event_name, count() FROM events \\
    WHERE client_id=5 AND event_time >= now() - INTERVAL 1 DAY \\
    GROUP BY event_name ORDER BY count() DESC\""

# Confirm click wrapper entry exists
curl "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/storage/kv/namespaces/$KV_ID/values/demoquote" \
  -H "Authorization: Bearer $CF_TOKEN"

# Test end-to-end: visit via partner link, submit form, check event landed
curl -I https://t.relo.mx/c/demoquote
# → 302 Location: https://quote.miami?...

9. Gotchas we hit in production

10. Operational runbook

Deploy pixel changes

cd backbone/workers/pixel && npx wrangler deploy

Deploy Quote site changes

cd ~/seguros && bash scripts/deploy-cloudflare.sh

Deploy Go batch.go changes

cd backbone && GOOS=linux GOARCH=amd64 go build -o relo-ingest-new ./cmd/ingest/
scp relo-ingest-new root@178.156.195.219:/opt/relo/relo-ingest-new
ssh root@178.156.195.219 "systemctl stop relo-ingest && \\
  cp /opt/relo/relo-ingest-new /opt/relo-ingest/relo-ingest && \\
  chmod +x /opt/relo-ingest/relo-ingest && systemctl start relo-ingest"

Check live events

ssh root@178.156.195.219 "clickhouse-client -d relo -q \\
  \"SELECT event_name, event_properties, event_time \\
    FROM events WHERE client_id=5 \\
    AND event_time >= now() - INTERVAL 5 MINUTE \\
    ORDER BY event_time DESC LIMIT 10 FORMAT Vertical\""

11. See also