# Cómo subimos info dinámica a Snov.io para las campañas

Guía de cómo pusimos un **link personalizado único por prospecto** en una campaña de
Snov.io (el creador de productos con IA, `?t=<token>`). Sirve como receta para futuras campañas.

---

## El problema

La campaña necesitaba que **cada prospecto recibiera SU propia URL** (con su token único
que le da acceso al creador con su cupo de diseños).

Snov.io tiene variables nativas (`{{first_name}}`, `{{company_name}}`, etc.) **pero NO tiene
una variable de email** ni una forma de meter una URL distinta por persona de fábrica.

La solución de Snov.io para esto son las **variables personalizadas** (custom fields): un campo
por prospecto que llenas con datos únicos, y se inserta en el correo como `{{nombre_del_campo}}`.

---

## La solución en 3 partes

1. **Token único por prospecto** → generado y guardado en Supabase (tabla `creator_tokens`,
   con `email`, `nombre`, `empresa`, `quota_total`, `campaign`).
2. **URL personalizada por prospecto** → `https://isharetone.com/es/crea-tu-producto?t=<token>`.
3. **Campo personalizado `creator_url` en Snov.io** con esa URL → se usa como `{{creator_url}}`
   en el cuerpo del correo.

---

## Cómo se sube la info dinámica (lo importante)

### Lo que NO funcionó: importar CSV con "Merge data"

Importamos un CSV (`email, first_name, company, creator_url`) a una lista nueva, mapeando
`creator_url` a un campo personalizado nuevo. El "Merge data" **creó el campo pero dejó los
valores VACÍOS** en los prospectos que ya existían en la cuenta (quirk de Snov al fusionar).
Resultado: el campo existía pero `{{creator_url}}` salía vacío.

### Lo que SÍ funcionó: la API v1 `add-prospect-to-list`

Llenamos el campo personalizado por prospecto llamando a la API directa de Snov.io,
en loop sobre los 278 contactos.

**1) Autenticación (OAuth2 client credentials)**

Las credenciales salen de Snov.io → Settings → API (`API User ID` + `API Secret`).

```js
const auth = await (await fetch('https://api.snov.io/v1/oauth/access_token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: `grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}`,
})).json();
const TOKEN = auth.access_token; // Bearer, válido 1 hora
```

**2) Llenar el campo personalizado por prospecto**

El endpoint `POST /v1/add-prospect-to-list` con `updateContact=true` **actualiza** un prospecto
existente (no lo duplica) y acepta `customFields[NombreDelCampo]`.

```js
const body = new URLSearchParams();
body.set('access_token', TOKEN);
body.set('email', prospecto.email);           // identifica al prospecto
body.set('listId', '40634779');               // id de la lista destino
body.set('updateContact', 'true');            // <- actualiza, no duplica
body.set('customFields[creator_url]', url);   // <- el valor dinámico (su URL única)
body.set('customFields[campaign]', 'Mexico Exhibition');

const r = await fetch('https://api.snov.io/v1/add-prospect-to-list', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body,
});
// respuesta: {"success":true,"added":true,"updated":true}
```

**3) En loop sobre todos los prospectos** (con un delay chico para no saturar la API):

```js
for (const p of prospectos) {
  const url = 'https://isharetone.com/es/crea-tu-producto?t=' + p.token;
  // ...armar body como arriba con p.email y url...
  await fetch('https://api.snov.io/v1/add-prospect-to-list', { method: 'POST', body });
  await new Promise(r => setTimeout(r, 120)); // ~120ms entre llamadas
}
```

Resultado: los 278 prospectos quedaron con su `creator_url` real. En el correo se inserta
`{{creator_url}}` (desde el menú Variable) y cada persona recibe su link único.

---

## Verificar que sí quedó lleno

Antes de lanzar, confirmar que el valor se guardó (no confiar solo en el Preview):

- Por API/MCP: leer un prospecto y revisar `customFields` → `creator_url` debe traer la URL.
- En la UI: abrir la ficha de un prospecto y ver el campo.
- En el editor del correo: **Preview** con un prospecto real muestra el link sustituido.

---

## Receta reutilizable para la próxima campaña

1. Generar un token por email (script → tabla `creator_tokens`, con tag `campaign`).
2. Crear/usar el campo personalizado `creator_url` en Snov.io (una vez; luego se reutiliza).
3. Meter los prospectos a una lista y **llenar `creator_url` por API** (`add-prospect-to-list`
   + `updateContact=true`) — NO confiar en el CSV import para poblar valores en prospectos existentes.
4. En el correo usar `{{creator_url}}` (y `{{first_name}}`), insertados del menú Variable.
5. Verificar con Preview + lanzar.

**Notas:**
- La API de Snov.io con estas credenciales **puede leer y actualizar prospectos**, pero
  **NO crear campañas** (devuelve 403). La secuencia/campaña se arma en la UI.
- El MCP de Snov.io (mcp.snov.io/mcp) opera prospectos/listas/CRM por lenguaje natural,
  pero tampoco expone la creación de campañas.
