XOhan Ads is our in-house measurement pipeline. It receives app events from our SDK and measurement partners, validates and de-duplicates them, uploads verified conversions to our own Google Ads manager account, files adjustments when a partner restates an event, and keeps app remarketing audiences in sync.
Every upload is traceable to a source event, a validation decision and an API response. Nothing reaches our Google Ads account without passing the same checks, and every change of state is logged for internal audit.
Server-to-server reception of install, first-open, sign-up and in-app purchase events from our SDK and from measurement partners, normalised into one event schema.
Verified events are batched per app and per day, uploaded with a stable order identifier and a request id, so any conversion can be located or retracted later.
Refunds, chargebacks and partner restatements travel as conversion adjustments instead of duplicate conversions, keeping reported totals consistent with reality.
App-user segments computed from the same event stream are pushed on a daily schedule, with membership expiry so no user stays in an audience indefinitely.
Forwarded counts are compared with source counts per app each day; unexplained gaps raise an internal alert and block the next batch for that app.
Employee accounts only, role-based permissions, MFA at the identity provider and per-action audit records. There is no public sign-up on this product.
The pipeline is deliberately boring: a collector that accepts, a validator that decides, a forwarder that talks to the API, and a console that explains what happened.
HTTPS endpoint for SDK events and partner postbacks. Payloads are signed or token-authenticated and written to a durable queue.
Schema checks, event-id idempotency, consent and fraud filters. Events that fail stay in the queue with a reason instead of being dropped.
Batched uploads against the conversion action for that app, with partial-failure handling so one bad operation cannot block a batch.
Responses, request ids and daily source counts are stored together; retries and retractions are driven from that record.
We use the App Conversion Tracking & Remarketing API for the items below, and nothing else. Campaign creation, bidding and reporting run in the Google Ads interface.
| Capability | How it is handled | Scope |
|---|---|---|
| Install and in-app event upload | Batched upload per app and day, keyed by order id; duplicate event ids are ignored before the call. | Own apps only |
| Conversion adjustments | Retractions and restatements filed as adjustments, located by order id or click-time pair. | Own apps only |
| App remarketing audiences | Daily membership sync computed from the forwarded event stream, with automatic expiry. | Own accounts |
| Attribution identifiers | Click identifiers from partner postbacks; user identifiers hashed before storage or transmission. | Consented users only |
| Account access | Single manager account with the linked app accounts we own; OAuth refresh tokens held encrypted. | No third-party accounts |
| Data retention | Raw payloads 180 days for reconciliation, aggregated metrics 24 months, deletion on request. | Per privacy policy |
The forwarder speaks directly to the Google Ads REST endpoints with OAuth 2.0 user credentials and our developer token. Requests are small, idempotent where the API allows it, and always carry a stable order id so a later adjustment can find the original conversion.
// one batch, one app, one day POST /v{api_version}/customers/{customer_id}:uploadClickConversions Authorization: Bearer {access_token} developer-token: {developer_token} { "conversions": [{ "gclid": "EAIaIQobChMI7...", "conversionAction": "customers/0000000000/conversionActions/111111111", "conversionDateTime": "2026-06-11 14:32:08+00:00", "conversionValue": 24.99, "currencyCode": "USD", "orderId": "xo-order-88213" }], "partialFailure": true }
Identifiers are hashed before they are stored or transmitted, consent is checked at ingestion, and access is limited to a small named group of employees.
Named employee accounts, role-based permissions and MFA. The console has no public sign-up; the public demo runs on static sandbox data.
Email, phone and other user identifiers are SHA-256 hashed at ingestion. Raw values are never written to the analytics store or to logs.
Advertising identifiers are forwarded only where the app has collected the consent required by law and platform policy; otherwise the event is stored without them.
Raw payloads are purged after 180 days, aggregated metrics after 24 months, and a verified deletion request is honoured across the pipeline.
Employees of the company only. Accounts are provisioned by an administrator at the identity provider, protected by MFA and limited by role. Contractors and outsourced staff work under the same internal policy. There is no public sign-up and no client-facing instance.
Our own published apps. We forward install, first-open, sign-up, add-to-cart, view-item and in-app purchase events, plus the click identifiers returned by our measurement partners.
Click identifiers travel only inside the conversion upload. User identifiers are hashed at ingestion and used for matching and audience membership; raw PII is not persisted. Consent is evaluated before any identifier is forwarded.
The pipeline files a conversion adjustment rather than a second conversion, then records the API response and request id against the original event so the change is auditable.
No. Data is transmitted to our own Google Ads manager account and stored in our own infrastructure. It is not sold, licensed or shared for any other purpose.
Use the public demo account on the sign-in page. It opens a sandboxed console populated with static sample data; no Google Ads account is read or modified.
Sign in with the public demo account to walk through the event stream, the upload queue and the audience sync screens. Nothing you do there touches a live account.