📘 Conversiones Offline - Meta Ads

Guía completa para importar conversiones offline a Meta Ads (Facebook/Instagram) desde tu CRM usando el FBCLID capturado por Referrer Tracker.

✓ Beneficios:

  • Recupera conversiones bloqueadas por iOS 14.5+ y navegadores
  • Mejora el aprendizaje de tus campañas con datos reales
  • Optimiza para ventas offline, no solo leads online
  • Reduce el CPL/CPA hasta un 35%

Configuración en Meta Business Manager

Paso 1: Crear Conjunto de Eventos Offline

  1. Ve a Meta Business Manager → Fuentes de datos → Conjuntos de eventos offline
  2. Click en Crear conjunto de eventos offline
  3. Nombre: "Conversiones CRM" (o el que prefieras)
  4. Descripción: "Conversiones offline desde nuestro CRM"
  5. Click en Crear

Paso 2: Configurar Eventos Personalizados

Define los eventos que quieres trackear:

Eventos estándar de Meta: Usa eventos estándar cuando sea posible (Lead, Purchase, CompleteRegistration) para mejor optimización.

Formato del Archivo CSV

Meta Ads requiere un CSV con las siguientes columnas mínimas:

event_name,event_time,fbclid,value,currency
Lead,1705329000,fb.1.123456789.987654321,0,EUR
LeadQualified,1705415400,fb.1.123456789.987654321,100,EUR
Purchase,1706025000,fb.1.123456789.987654321,12000,EUR

Requisitos importantes:

  • event_time: Unix timestamp (segundos desde 1970)
  • fbclid: Debe ser válido y tener formato fb.1.timestamp.id
  • Ventana: Máximo 62 días desde el clic original
  • Límite: 1,000,000 eventos por archivo

Columnas Adicionales Recomendadas

event_name,event_time,fbclid,value,currency,email,phone,fn,ln,ct,st,country
Lead,1705329000,fb.1.123456789.987654321,0,EUR,juan@empresa.com,34600000000,juan,perez,madrid,madrid,es

Incluir datos de contacto (hasheados con SHA256) mejora el matching y la atribución.

Generar CSV desde tu CRM

Exportar desde HubSpot

Script Python con API de HubSpot

import requests
import csv
import hashlib
from datetime import datetime

# Configuración
HUBSPOT_API_KEY = "tu_api_key"
HUBSPOT_API_URL = "https://api.hubapi.com/crm/v3/objects/contacts"

# Función para hashear datos (requerido por Meta)
def hash_data(data):
    if not data:
        return ""
    return hashlib.sha256(data.lower().strip().encode()).hexdigest()

# Obtener contactos con FBCLID
params = {
    "properties": "fbclid,hs_lifecyclestage_lead_date,email,phone,firstname,lastname,city,state,country",
    "limit": 100
}
headers = {"Authorization": f"Bearer {HUBSPOT_API_KEY}"}

response = requests.get(HUBSPOT_API_URL, params=params, headers=headers)
contacts = response.json()["results"]

# Generar CSV para Meta Ads
with open('meta_ads_conversions.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(['event_name', 'event_time', 'fbclid', 'value', 'currency',
                     'email', 'phone', 'fn', 'ln', 'ct', 'st', 'country'])
    
    for contact in contacts:
        props = contact["properties"]
        fbclid = props.get("fbclid")
        date = props.get("hs_lifecyclestage_lead_date")
        
        if fbclid and date:
            # Convertir fecha a Unix timestamp
            dt = datetime.fromisoformat(date.replace('Z', '+00:00'))
            timestamp = int(dt.timestamp())
            
            # Hashear datos personales
            email = hash_data(props.get("email", ""))
            phone = hash_data(props.get("phone", "").replace("+", "").replace(" ", ""))
            fn = hash_data(props.get("firstname", ""))
            ln = hash_data(props.get("lastname", ""))
            ct = hash_data(props.get("city", ""))
            st = hash_data(props.get("state", ""))
            country = hash_data(props.get("country", ""))
            
            writer.writerow([
                'LeadQualified',
                timestamp,
                fbclid,
                100,
                'EUR',
                email,
                phone,
                fn,
                ln,
                ct,
                st,
                country
            ])

print("CSV generado: meta_ads_conversions.csv")

Exportar desde Salesforce

Script Python con API de Salesforce

from simple_salesforce import Salesforce
import csv
import hashlib
from datetime import datetime

# Función para hashear datos
def hash_data(data):
    if not data:
        return ""
    return hashlib.sha256(str(data).lower().strip().encode()).hexdigest()

# Conectar a Salesforce
sf = Salesforce(
    username='tu_usuario@empresa.com',
    password='tu_password',
    security_token='tu_token'
)

# Query SOQL
query = """
    SELECT FBCLID__c, StatusChangeDate, Email, Phone, FirstName, LastName, 
           City, State, Country
    FROM Lead
    WHERE Status = 'Qualified'
    AND FBCLID__c != null
    AND StatusChangeDate = LAST_N_DAYS:7
"""

results = sf.query(query)

# Generar CSV para Meta Ads
with open('meta_ads_conversions.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(['event_name', 'event_time', 'fbclid', 'value', 'currency',
                     'email', 'phone', 'fn', 'ln', 'ct', 'st', 'country'])
    
    for record in results['records']:
        fbclid = record['FBCLID__c']
        date = record['StatusChangeDate']
        
        # Convertir fecha a Unix timestamp
        dt = datetime.strptime(date, '%Y-%m-%dT%H:%M:%S.%f%z')
        timestamp = int(dt.timestamp())
        
        # Hashear datos personales
        email = hash_data(record.get('Email'))
        phone = hash_data(record.get('Phone', '').replace('+', '').replace(' ', ''))
        fn = hash_data(record.get('FirstName'))
        ln = hash_data(record.get('LastName'))
        ct = hash_data(record.get('City'))
        st = hash_data(record.get('State'))
        country = hash_data(record.get('Country'))
        
        writer.writerow([
            'LeadQualified',
            timestamp,
            fbclid,
            100,
            'EUR',
            email,
            phone,
            fn,
            ln,
            ct,
            st,
            country
        ])

print(f"CSV generado con {len(results['records'])} conversiones")

Exportar desde Zoho CRM

Script Python con API de Zoho

import requests
import csv
import hashlib
from datetime import datetime

# Función para hashear datos
def hash_data(data):
    if not data:
        return ""
    return hashlib.sha256(str(data).lower().strip().encode()).hexdigest()

# Configuración
ZOHO_ACCESS_TOKEN = "tu_access_token"
ZOHO_API_URL = "https://www.zohoapis.eu/crm/v2/Leads"

# Headers
headers = {"Authorization": f"Bearer {ZOHO_ACCESS_TOKEN}"}

# Parámetros de búsqueda
params = {
    "criteria": "(Lead_Status:equals:Qualified)and(FBCLID:is_not_empty)",
    "fields": "FBCLID,Modified_Time,Email,Phone,First_Name,Last_Name,City,State,Country",
    "per_page": 200
}

# Obtener leads
response = requests.get(ZOHO_API_URL, headers=headers, params=params)
leads = response.json()["data"]

# Generar CSV para Meta Ads
with open('meta_ads_conversions.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(['event_name', 'event_time', 'fbclid', 'value', 'currency',
                     'email', 'phone', 'fn', 'ln', 'ct', 'st', 'country'])
    
    for lead in leads:
        fbclid = lead.get("FBCLID")
        date = lead.get("Modified_Time")
        
        if fbclid and date:
            # Convertir fecha a Unix timestamp
            dt = datetime.fromisoformat(date.replace('Z', '+00:00'))
            timestamp = int(dt.timestamp())
            
            # Hashear datos personales
            email = hash_data(lead.get("Email"))
            phone = hash_data(lead.get("Phone", "").replace("+", "").replace(" ", ""))
            fn = hash_data(lead.get("First_Name"))
            ln = hash_data(lead.get("Last_Name"))
            ct = hash_data(lead.get("City"))
            st = hash_data(lead.get("State"))
            country = hash_data(lead.get("Country"))
            
            writer.writerow([
                'LeadQualified',
                timestamp,
                fbclid,
                100,
                'EUR',
                email,
                phone,
                fn,
                ln,
                ct,
                st,
                country
            ])

print(f"CSV generado con {len(leads)} conversiones")

Subir Conversiones a Meta Ads

Método 1: Subida Manual (CSV)

  1. Ve a Meta Business Manager → Fuentes de datos → Conjuntos de eventos offline
  2. Selecciona tu conjunto de eventos
  3. Click en Cargar eventos
  4. Selecciona Cargar archivo
  5. Sube tu CSV
  6. Mapea las columnas correctamente
  7. Click en Cargar eventos

✓ Procesamiento: Meta procesará los eventos en 1-2 horas. Verás los resultados en el Administrador de eventos.

Método 2: API de Conversiones (Automatizado)

// Script Python con Meta Conversions API
import requests
import hashlib
import time

# Configuración
ACCESS_TOKEN = "tu_access_token"
PIXEL_ID = "tu_pixel_id"
API_URL = f"https://graph.facebook.com/v18.0/{PIXEL_ID}/events"

# Función para hashear datos
def hash_data(data):
    if not data:
        return None
    return hashlib.sha256(data.lower().strip().encode()).hexdigest()

# Preparar evento
event_data = {
    "data": [{
        "event_name": "LeadQualified",
        "event_time": int(time.time()),
        "action_source": "website",
        "user_data": {
            "em": hash_data("juan@empresa.com"),
            "ph": hash_data("34600000000"),
            "fn": hash_data("juan"),
            "ln": hash_data("perez"),
            "ct": hash_data("madrid"),
            "st": hash_data("madrid"),
            "country": hash_data("es"),
            "fbp": "fb.1.123456789.987654321",  # FBCLID
            "fbc": "fb.1.123456789.987654321"   # FBCLID
        },
        "custom_data": {
            "value": 100,
            "currency": "EUR"
        }
    }],
    "access_token": ACCESS_TOKEN
}

# Enviar evento
response = requests.post(API_URL, json=event_data)

if response.status_code == 200:
    result = response.json()
    print(f"Eventos recibidos: {result['events_received']}")
else:
    print(f"Error: {response.text}")

Mejores Prácticas

📋 Recomendaciones:

  • Hashear datos: Siempre hashea datos personales con SHA256 antes de enviar
  • Incluir múltiples identificadores: Email + teléfono + FBCLID = mejor matching
  • Subir regularmente: Semanalmente o cuando tengas 50+ eventos
  • Ventana de 62 días: No esperes más de 62 días desde el clic
  • Usar eventos estándar: Lead, Purchase, etc. para mejor optimización
  • Incluir valores: Asigna valores monetarios realistas

Troubleshooting

Bajo porcentaje de matching

Causa: Faltan datos de contacto o están mal hasheados.

Solución: Incluye email, teléfono y FBCLID. Verifica que el hash sea SHA256 en minúsculas.

Eventos no aparecen en informes

Causa: Meta tarda 1-2 horas en procesar eventos offline.

Solución: Espera y verifica en Administrador de eventos → Actividad de eventos.

FBCLID inválido

Causa: El FBCLID no tiene el formato correcto o ha expirado.

Solución: Verifica que el formato sea fb.1.timestamp.id y que esté dentro de los 62 días.