Skip to main content
When Gravity serves an ad, the response includes two tracking URLs:
  • impUrl — fired when the ad becomes visible (impression pixel)
  • clickUrl — navigated to when the user clicks the ad
By default these point to api.trygravity.ai. A tracking proxy lets you route them through your own domain instead, so you can log every impression and click on your own server before forwarding to Gravity. This is the same pass-through pattern advertisers use for first-party conversion tracking — applied to the publisher side.

Why proxy tracking?

  • First-party data — impressions and clicks hit your domain, so you can log them in your own analytics, data warehouse, or billing system.
  • Verification — independently verify the impression and click counts Gravity reports.
  • Latency visibility — monitor tracking endpoint performance from your own infrastructure.
  • No SDK changes required — the SDK fires whatever URL is on impUrl / clickUrl. You just rewrite them on your server before passing the ad to your client.

How it works

1

Set up a reverse proxy

Add a route on your server (e.g. /gravity/) that forwards requests to api.trygravity.ai.
2

Rewrite tracking URLs

On your server, after calling gravity.getAds(), replace the Gravity domain in impUrl and clickUrl with your own proxy domain.
3

Log on your side

Your proxy receives every impression and click request. Log whatever you need, then forward to Gravity.

1. Set up the reverse proxy

Nginx

Next.js (middleware or API route)

Express

Python (FastAPI)

2. Rewrite tracking URLs

After calling gravity.getAds() on your server, replace the Gravity domain in the ad response with your proxy path before sending to the client.

Node / TypeScript

Python

The encrypted ?p= token in each URL is opaque and tamper-proof. You’re only changing the domain prefix, so all billing and attribution still works exactly as before on Gravity’s side.

3. Log impressions and clicks

Your proxy server receives every tracking request. Here’s what each path tells you: The ?p= query parameter is an encrypted payload containing the click ID, campaign ID, publisher ID, ad ID, and price. You can’t decrypt it (it’s encrypted with Gravity’s key), but you can count requests, log timestamps, and correlate with your own session/user data from request headers.

Example: structured logging

Alternative: client-side callbacks

If you don’t need a full proxy, the React SDK has onImpression and onClick callbacks that fire client-side:
This is simpler but runs in the browser. The proxy approach gives you server-side visibility and works with any rendering method (not just the React SDK).

Important notes

  • Always forward X-Forwarded-For — Gravity uses the end user’s IP for geo-targeting and fraud detection. Without it, all impressions appear to come from your server’s IP.
  • Forward User-Agent — used for device-type classification and bot filtering.
  • Don’t cache — every impression and click request must reach Gravity. Impressions are deduplicated server-side, but a cached response would silently drop billing events.
  • Click redirects — the /track/click endpoint returns a 302 redirect to the advertiser’s landing page. Make sure your proxy passes through the redirect response (don’t follow it server-side).

Show ads

How impression and click tracking works in the SDK.

Payouts

How your tracked impressions translate to revenue.