How It Works
Technical overview of GoPayLocal's architecture and request flow.
GoPayLocal is built on Cloudflare’s edge network to deliver PPP discounts with minimal latency and zero impact on your page load.
Request Flow
Section titled “Request Flow”When a visitor loads your page with the GoPayLocal script, here is what happens:
-
Browser loads the script
The
<script>tag loads asynchronously (~5KB, 1.5KB gzipped). It does not block page rendering. -
Cloudflare Worker detects the country
The script makes a request to
api.gopaylocal.com. Because the API runs on Cloudflare Workers, the visitor’s country is available instantly from theCF-IPCountryheader — no external geolocation API needed.Cost: $0. Latency: 0ms (it’s a request header, not a lookup).
-
PPP tier and discount lookup from KV
The Worker reads the campaign configuration and parity group data from Cloudflare KV (edge key-value store). This lookup happens at the nearest edge location to the visitor.
Latency: < 10ms (data is cached at 300+ edge locations worldwide).
-
VPN/proxy check
The Worker checks the visitor’s IP against known VPN and proxy IP ranges using ASN (Autonomous System Number) data and open-source IP lists stored in a dedicated KV namespace.
If a VPN is detected, the discount is withheld to prevent abuse.
-
Personalized response
The Worker returns a JSON response containing:
- Whether to show a discount (
show: true/false) - Country code and name
- Discount percentage
- Coupon code (if using coupon-based delivery)
- Local currency code, symbol, and FX rate
- Banner configuration (position, colors, message template)
- Whether to show a discount (
-
Banner renders in Shadow DOM
The script creates a Shadow DOM element and renders the discount banner inside it. Shadow DOM ensures the banner’s styles are completely isolated from your site — no CSS conflicts, no layout shifts.
Architecture Diagram
Section titled “Architecture Diagram”┌─────────────────────────────────────────────────────┐│ Visitor's Browser ││ ││ ┌──────────┐ ┌────────────────────────────────┐ ││ │ Your App │ │ GoPayLocal Banner (Shadow DOM) │ ││ └──────────┘ └────────────────────────────────┘ ││ │ ▲ ││ │ │ Render ││ ▼ │ ││ ┌─────────────────────────────────┐ ││ │ Banner Script (5KB / 1.5KB gz) │ ││ └──────────┬──────────────────────┘ │└─────────────┼───────────────────────────────────────┘ │ fetch (async) ▼┌─────────────────────────────────────────────────────┐│ Cloudflare Edge (nearest PoP) ││ ││ ┌──────────────────┐ ┌────────────────────┐ ││ │ Hono API Worker │───▶│ Cloudflare KV │ ││ │ │ │ - Campaign config │ ││ │ 1. Read country │ │ - Parity groups │ ││ │ (CF header) │ │ - VPN IP lists │ ││ │ 2. Lookup PPP │ └────────────────────┘ ││ │ 3. Check VPN │ ││ │ 4. Return config│ ┌────────────────────┐ ││ │ 5. Log analytics│───▶│ Analytics Engine │ ││ └──────────────────┘ └────────────────────┘ │└─────────────────────────────────────────────────────┘Response Caching
Section titled “Response Caching”GoPayLocal uses multiple layers of caching for performance:
| Layer | What’s Cached | TTL |
|---|---|---|
| Cloudflare KV | Campaign configs, parity groups, FX rates | 5 minutes |
| Browser sessionStorage | PPP response per API key | 5 minutes |
| Cloudflare CDN | Banner script file | 1 hour |
The sessionStorage cache means repeat page views within the same session never make an additional API call.
Analytics Pipeline
Section titled “Analytics Pipeline”Events (impressions, clicks, copies, dismissals) are sent via navigator.sendBeacon() to the analytics endpoint. This ensures events are captured even when the user navigates away — without blocking page unload.
Events flow into Cloudflare’s Workers Analytics Engine, which provides real-time aggregation without a separate analytics database.
Security
Section titled “Security”- Shadow DOM isolation — The banner cannot access your page’s DOM or cookies
- XSS prevention — All dynamic content in the banner is inserted via
textContentor programmatic DOM APIs, never raw HTML - VPN detection — ASN + IP list based, upgradeable to paid services for higher accuracy
- API key scoping — Public keys (
gpl_pk_*) can only read banner configs; secret keys (gpl_sk_*) are required for management APIs - Domain allowlisting — Campaigns can be restricted to specific domains