Guide

Automatic Data Pull (Zero Code) Pull Automatico de Datos (Cero Codigo)

RELO automatically pulls your data from AppsFlyer every hour. You provide credentials, we handle everything else. RELO jala tus datos de AppsFlyer cada hora automaticamente. Tu provees las credenciales, nosotros nos encargamos de todo lo demas.

How the Pull API Works Como Funciona la Pull API

The RELO Go service on Hetzner runs a scheduled job that calls the AppsFlyer Pull API every 60 minutes. It downloads in-app event reports, extracts purchase data, runs attribution matching, and populates your dashboard. El servicio Go de RELO en Hetzner ejecuta un job programado que llama a la AppsFlyer Pull API cada 60 minutos. Descarga reportes de eventos in-app, extrae datos de compra, corre matching de atribucion, y llena tu dashboard.

// Every 60 minutes, the Go service runs:

1. Download reports from AppsFlyer
   GET https://hq1.appsflyer.com/api/raw-data/export/app/{app_id}/
       in_app_events_report/v5
   ?from=2026-03-18&to=2026-03-18
   &event_name=af_purchase
   &additional_fields=is_primary_attribution,...

2. Filter by Primary Attribution
   Only rows where Is Primary Attribution = "true" are processed.
   This prevents double-counting when the same order appears in
   both UA and RT reports.

3. Extract products from Event Value JSON
   Parse af_content_id, af_price, af_quantity, items, awin_cg

4. Calculate correct revenue
   Priority: awin_cg > Event Revenue proportional > af_price

5. Run attribution matching
   Match campaign field against partner rules (exact/contains/etc.)

6. Classify products into segments
   MX, VD, DA, HA, IT, NW, TAB based on product name/category

7. Write to ClickHouse + Supabase (dual-write)
   Deduplication via sale_hash = SHA256(order_id|product_id|qty)

Reports Pulled Reportes Descargados

ReportReporte FrequencyFrecuencia EventsEventos PlatformsPlataformas
UA in-app eventsEventos in-app UA Every 60 minCada 60 min af_purchase iOS + Android
RT (Retargeting) in-app eventsEventos in-app RT (Retargeting) Every 60 minCada 60 min af_purchase iOS + Android
InstallsInstalaciones Daily at 4 AM MXDiario a las 4 AM MX install iOS + Android
Fraud reportsReportes de fraude Daily at 4 AM MXDiario a las 4 AM MX Blocked installs/eventsInstalaciones/eventos bloqueados iOS + Android

Primary Attribution Filter Filtro de Atribucion Primaria

When retargeting campaigns are active, AppsFlyer exports the same purchase in both UA and RT reports. The Is Primary Attribution field indicates which source is the winner. Cuando las campanas de retargeting estan activas, AppsFlyer exporta la misma compra en ambos reportes UA y RT. El campo Is Primary Attribution indica cual fuente es la ganadora.

// Example: Order MX251215-75414612 appears in BOTH reports

UA Report:
  Campaign: ...sub3... (Paddlewaver)
  Touch Time: 2025-12-14 17:48:54
  Is Primary Attribution: FALSE  // Not the winner

RT Report:
  Campaign: ...sub1... (Mobupps)
  Touch Time: 2025-12-14 17:50:15
  Is Primary Attribution: TRUE   // This is the winner

// RELO only processes rows where Is Primary Attribution = "true"
// This prevents double-counting and respects AppsFlyer's attribution decision
Without this filter: The first CSV imported would "win" regardless of actual attribution, leading to incorrect partner attribution and commission calculations. Sin este filtro: El primer CSV importado "ganaria" sin importar la atribucion real, llevando a atribucion incorrecta de partners y calculos de comisiones erroneos.

Revenue Calculation Calculo de Revenue

AppsFlyer provides multiple price fields. RELO uses a priority chain to get the actual revenue (after discounts), not the list price: AppsFlyer provee multiples campos de precio. RELO usa una cadena de prioridad para obtener el revenue real (despues de descuentos), no el precio de lista:

// Revenue priority chain (highest accuracy first):

Priority 1: awin_cg (per-product breakdown)
  "Mobile_Smartphone:16984.30|Mobile_Wearable:719.10"
  -> Product 1 revenue: $16,984.30
  -> Product 2 revenue: $719.10
  -> Validates: sum must equal Event Revenue

Priority 2: Event Revenue (distributed proportionally)
  Event Revenue: $17,703.40
  af_price: [$41,998.99, $5,999.00]
  -> Product 1: $17,703.40 * (41998.99 / 47997.99) = $15,501.25
  -> Product 2: $17,703.40 * (5999.00 / 47997.99) = $2,202.15

Priority 3: af_price (list price fallback)
  Only used when neither awin_cg nor Event Revenue is available.
  WARNING: This is the list price BEFORE discounts.
Why this matters: Using af_price directly can overstate revenue by 40-60% due to promotional discounts. awin_cg gives the exact per-product revenue after discounts. Por que importa: Usar af_price directamente puede sobreestimar el revenue en 40-60% por descuentos promocionales. awin_cg da el revenue exacto por producto despues de descuentos.

Product Segment Classification Clasificacion de Segmento de Producto

Each product is automatically classified into a segment for commission calculation: Cada producto se clasifica automaticamente en un segmento para el calculo de comisiones:

SegmentSegmento NameNombre KeywordsPalabras Clave
MXMobilegalaxy s, galaxy z, buds, watch, sm-
VDVisual Displaytv, qled, oled, soundbar, monitor
DADigital Appliancesrefrigerador, lavadora, horno, bespoke
HAHome Appliancesaire, microondas, aspiradora
ITComputinglaptop, tablet, galaxy book, tab s
NWNetworkrouter, mesh, wifi, switch
TABTabletstab (word boundary match only)tab (solo match de palabra completa)

Setup: Providing Credentials Configuracion: Proveyendo Credenciales

1

Get your AppsFlyer Pull API token Obtiene tu token de Pull API de AppsFlyer

In AppsFlyer, go to Settings → API Tokens. Copy the Pull API v2.0 token. This is NOT the same as the V1 token or the Admin API token. En AppsFlyer, ve a Settings → API Tokens. Copia el token de Pull API v2.0. Este NO es el mismo que el token V1 o el token de Admin API.

2

Share your app IDs Comparte tus app IDs

Provide your iOS app ID (e.g., id123456789) and Android package name (e.g., com.samsung.shop.mx). RELO pulls data for both platforms. Provee tu app ID de iOS (ej: id123456789) y el package name de Android (ej: com.samsung.shop.mx). RELO jala datos de ambas plataformas.

3

Send credentials to your RELO account manager Envia las credenciales a tu account manager de RELO

We configure the Pull API on our Hetzner backbone. Within 1 hour, your first data pull runs automatically and your dashboard starts populating. Nosotros configuramos la Pull API en nuestro backbone de Hetzner. En 1 hora, tu primer pull de datos corre automaticamente y tu dashboard empieza a llenarse.

Manual Trigger Trigger Manual

Admins can trigger an immediate data pull via the API (useful after configuration changes or to debug missing data): Los admins pueden disparar un pull de datos inmediato via la API (util despues de cambios de configuracion o para debuggear datos faltantes):

POST https://ingest.relo.mx/pull/trigger
Authorization: Bearer ADMIN_TOKEN
Content-Type: application/json

{
  "client_id": 3,
  "date": "2026-03-18",
  "reports": ["ua_purchase", "rt_purchase"]
}

// Response 200:
{
  "status": "started",
  "message": "Pull triggered for client 3, date 2026-03-18",
  "reports": ["ua_purchase", "rt_purchase"]
}

Data Freshness Frescura de Datos

You can check when data was last pulled via the data freshness endpoint: Puedes verificar cuando fue la ultima vez que se jalaron datos via el endpoint de frescura de datos:

GET https://ingest.relo.mx/system/data-freshness

// Response 200:
{
  "clients": [
    {
      "client_id": 3,
      "client_name": "Samsung",
      "last_pull": "2026-03-18T15:00:00Z",
      "minutes_ago": 32,
      "status": "fresh",
      "orders_today": 145,
      "orders_yesterday": 312
    }
  ]
}
Freshness status: fresh = pulled within 90 minutes. stale = 90-180 minutes since last pull. critical = more than 180 minutes. The admin dashboard shows a warning banner when data is stale. Estado de frescura: fresh = jalado en los ultimos 90 minutos. stale = 90-180 minutos desde el ultimo pull. critical = mas de 180 minutos. El dashboard de admin muestra un banner de warning cuando los datos estan desactualizados.