Diil Docs
  1. Documentación
  2. El widget

Leads: los formularios de tu web, directos al CRM

Actualizado:

Un formulario de contacto que manda un email a alguien que está de vacaciones es el cementerio de los leads. Con Diil, cada formulario de tu web llega como una tarjeta al CRM: con teléfono o email, un estado y alguien responsable de devolver la llamada. Basta con un atributo en un <form>; si necesitas más control, tienes JavaScript y el servidor.

Tres formas de enviar un lead; elige la que mejor te encaje:

  • Un formulario con data-crm-lead: cero JavaScript. El widget intercepta el envío y se encarga del resto.
  • window.crmLead(): para React, Vue y cualquier formulario que controles tú.
  • POST /marketing/lead desde tu servidor: pedidos por teléfono, formularios procesados en el backend, integraciones con otros sistemas.

Cómo llega un lead de tu formulario al CRM

En Diil un lead es un tipo especial de evento. Cada evento tiene un nombre (por ejemplo, contact_form) y ese nombre hay que declararlo antes en el CRM. Marca en él “Esto es un lead” y cada envío con ese nombre se convertirá en una tarjeta en CRM → Leads.

  1. Un visitante rellena el formulario y pulsa “Enviar”.
  2. El widget recoge los campos, averigua quién es la persona (nombre, teléfono, email, mensaje) y lo envía.
  3. El servidor comprueba que el nombre está declarado, que el lead trae teléfono o email y que no tiene pinta de bot.
  4. Aparece una tarjeta de lead en el CRM y, si lo has configurado, una notificación en Telegram.

Dos reglas que conviene tener claras desde el principio:

  • Un nombre no declarado se rechaza. El CRM solo acepta lo que conoce: nada de basura sorpresa por culpa de una errata.
  • ¿Declarado, pero sin marcar como lead? Entonces se guarda como un evento normal y no se crea ninguna tarjeta de lead.

Configura un tipo de lead en el CRM

Dos minutos de clics, una vez por cada tipo de formulario:

  1. Abre Marketing → Eventos

    Aquí se describen todos los eventos que puede enviar tu web.
  2. Crea un evento

    Ponle el nombre que usará tu código: letras latinas, dígitos y guiones bajos, empezando por una letra: contact_form, callback_request, quote_request.
  3. Marca “Esto es un lead”

    A partir de ahora los envíos se convierten en tarjetas de lead. Como dice la pista del CRM, el formulario debe enviar una vía de respuesta: un teléfono o un email.
  4. Opcional: marca “Este evento genera ingresos”

    Solo así se guardan el importe y la moneda del lead. Sin esta casilla se ignoran sin decir nada.

Opción A: un formulario con un atributo

Añade data-crm-lead="nombre_de_tu_evento" a cualquier formulario de una página que tenga el script del widget. Esa es toda la integración. Los formularios que aparecen más tarde (en un modal, tras un cambio de ruta en una SPA) se detectan solos.

Ejemplo completo

Un formulario de “pide presupuesto” con nombre, teléfono, email y mensaje, un importe para el informe de ingresos, un mensaje de “gracias” y una validación propia. Primero HTML puro; las versiones de React y Vue llaman a crmLead() desde su propio manejador de envío.

<form id="quote" data-crm-lead="quote_request" data-crm-value="149900" data-crm-currency="EUR">
  <label>Tu nombre <input name="name" autocomplete="name" required></label>
  <label>Teléfono <input name="phone" type="tel" autocomplete="tel"></label>
  <label>Email <input name="email" type="email" autocomplete="email"></label>
  <label>¿Qué necesitas? <textarea name="message" rows="4"></textarea></label>

  <!-- No es uno de los campos conocidos: aparece tal cual en la tarjeta del lead -->
  <label>Tamaño del equipo
    <select name="team_size">
      <option>1–5</option>
      <option>6–20</option>
      <option>20+</option>
    </select>
  </label>

  <button type="submit">Enviar solicitud</button>
  <p class="form-status" role="status" hidden></p>
</form>

<script>
  const form = document.getElementById('quote');
  const status = form.querySelector('.form-status');
  const button = form.querySelector('button');

  function say(text) {
    status.textContent = text;
    status.hidden = false;
  }

  // 1. Antes de enviar: nuestra propia validación. preventDefault() = no se envía nada
  form.addEventListener('crm:lead-before', (event) => {
    const phone = form.elements.phone.value.trim();
    const email = form.elements.email.value.trim();
    if (!phone && !email) {
      event.preventDefault();
      say('Déjanos un teléfono o un email para poder responderte.');
      return;
    }
    button.disabled = true;
  });

  // 2. Después de enviar: el widget no muestra nada, el "gracias" es cosa nuestra
  form.addEventListener('crm:lead', (event) => {
    button.disabled = false;
    say(event.detail.ok
      ? '¡Gracias! Te responderemos en un día laborable.'
      : 'Algo ha fallado. Inténtalo de nuevo o llámanos.');
  });
</script>

<script src="https://widget.sitecog.com/widget.js" defer></script>

Qué pasa cuando se envía el formulario

  1. El widget siempre cancela el envío nativo: la página no se recarga y el action del formulario no se usa.
  2. Lanza crm:lead-before sobre el formulario. Si algún listener llama a event.preventDefault(), la historia acaba aquí y no se envía nada.
  3. Recoge los campos con FormData, salvo los campos excluidos (contraseñas, datos de tarjeta y compañía). Solo cuentan los valores de texto: los campos de archivo se ignoran. Varios campos con el mismo nombre (un grupo de checkboxes) se unen con ", ".
  4. Envía el lead, protegido con un pase de formulario de un solo uso (más sobre esto en protección contra spam).
  5. Lanza crm:lead con { ok: true } o { ok: false } en event.detail.
  6. Si ok es true, llama a form.reset(). Si falla, el formulario se queda como está para que el visitante no pierda lo que ha escrito.

El widget no muestra ninguna interfaz propia: ni toast, ni spinner, ni “gracias”. Tu web, tu diseño, tus palabras: escucha crm:lead y enseña lo que quieras.

Atributos del formulario

AtributoEjemploQué hace
data-crm-lead"quote_request"Convierte el formulario en un formulario de leads. El valor es el nombre del evento declarado en el CRM. Un atributo vacío equivale al nombre lead_submit, que también hay que declarar.
data-crm-value"149900"Importe en unidades menores, un entero: 149900 son 1.499,00. Solo se guarda si el evento tiene “Este evento genera ingresos”.
data-crm-currency"EUR"Moneda del importe: EUR, USD, UAH…
data-crm-ignoresin valorVa en un campo o en un contenedor (fieldset, div…), no en el propio formulario. Ese campo, o todo lo que haya dentro del contenedor, nunca se envía. Mira Campos que nunca se envían.

Eventos del formulario

Los dos eventos hacen bubbling, así que puedes escucharlos en el propio formulario o una sola vez en document para todos los formularios de la página.

EventoCuándoevent.detailCancelable
crm:lead-beforeJusto después del submit, antes de enviar nada{ name }: el nombre del eventoSí: preventDefault() detiene el envío
crm:leadCuando el servidor ha respondido{ ok }: true si el lead se ha aceptadoNo
Un listener para todos los formularios de leads de la páginajs
document.addEventListener('crm:lead', (event) => {
  if (event.detail.ok) {
    event.target.closest('.modal')?.classList.add('is-thanks');
  }
});

Nombres de campo que entiende el CRM

Una tarjeta de lead tiene cuatro huecos principales: nombre, teléfono, email y mensaje. El widget los rellena fijándose en los nombres de los campos. Los nombres se recortan y se pasan a minúsculas, y luego se comparan de forma exacta con esta lista (así que Phone funciona y your-phone no):

HuecoNombres de campo que lo rellenanLongitud máx.
Nombrename, fio, username, user_name, fullname, full_name, firstname, first_name, contact_name, client_name, имя, фио, ім'я200
Teléfonophone, tel, telephone, mobile, phone_number, contact_phone, телефон, тел40
Emailemail, e_mail, e-mail, mail, contact_email, почта, пошта, емейл320
Mensajemessage, comment, comments, text, question, note, description, task, сообщение, комментарий, вопрос, повідомлення, коментар4000
  • Gana la primera coincidencia. Si un formulario tiene phone y mobile, el hueco lo rellena el que aparezca primero.
  • Todo lo demás también se guarda. Los campos desconocidos y las segundas coincidencias van a “extra” y aparecen en la tarjeta del lead en el orden del formulario. Hasta 30 campos extra; claves de hasta 60 caracteres, valores de hasta 1000.
  • Un teléfono solo cuenta con entre 7 y 20 dígitos. Espacios, paréntesis y guiones no molestan; un + inicial se conserva.
  • Teléfono o email, sí o sí. Un lead sin ninguno de los dos se rechaza con no_contact: no habría forma de responder.

Campos que nunca se envían

Un formulario de leads no es sitio para contraseñas ni números de tarjeta, y el widget se encarga de que no acaben en el CRM aunque alguien los meta en el mismo <form> por despiste. Estos campos se saltan siempre:

  • Los <input type="password">, se llamen como se llamen.
  • Todo lo marcado con data-crm-ignore: el atributo puede ir en el propio campo o en cualquier contenedor (fieldset, div…), y entonces se salta todo lo que haya dentro.
  • Los campos con un nombre sensible. El nombre se trocea en palabras (por _, -, ., camelCase…) y se excluye si alguna de ellas, como palabra suelta, es card, cc, csc, cvv, cvc, iban, ssn, secret o pass. Además, basta con que el nombre contenga en cualquier sitio password, passwd, pwd, token, csrf, xsrf, creditcard, cardnumber o ccnum.

Unos ejemplos: card_number, cvv, csrf_token y user_password no se envían; discard_reason sí, porque ahí card no es una palabra suelta. Y si un campo con cierto nombre queda excluido, quedan excluidos todos los campos con ese mismo nombre.

Los campos ocultos (type="hidden") sí se envían, siempre que su nombre no sea sensible: son perfectos para pasar el producto, el plan o la página desde la que se escribió.

Qué llega y qué nohtml
<form data-crm-lead="signup_request">
  <input name="email" type="email">                <!-- ✓ se envía -->
  <input name="plan" type="hidden" value="pro">    <!-- ✓ oculto, pero se envía -->
  <input name="password" type="password">          <!-- ✗ type="password" -->
  <input name="card_number">                       <!-- ✗ nombre sensible -->

  <fieldset data-crm-ignore>                       <!-- ✗ nada de lo que hay dentro -->
    <input name="billing_address">
    <input name="billing_zip">
  </fieldset>

  <button type="submit">Empezar</button>
</form>

crmLead() aplica la misma regla de nombres a las claves de fields. Y el servidor vuelve a pasar el mismo filtro por su cuenta, también en POST /lead con clave secreta: un campo con nombre sensible nunca acaba en el CRM, venga de donde venga.

Opción B: envía leads desde JavaScript

Cuando el estado del formulario es tuyo (React, Vue, un asistente de varios pasos, un chatbot), llama al widget directamente. Las dos funciones aparecen en window en cuanto se carga widget.js.

crmLead(name, fields, options)

const { ok } = await window.crmLead(
  'callback_request',
  { name: 'Anna', phone: '+49 30 1234567', message: 'Llamadme después de las 17:00, por favor' },
  { value: 149900, currency: 'EUR' },
);
namestringobligatorio
Nombre del evento declarado en el CRM y marcado como “Esto es un lead”. Letras latinas, dígitos y guiones bajos, empezando por una letra (^[A-Za-z][A-Za-z0-9_]*$). Un nombre que no encaja recibe un aviso en la consola y { ok: false }.
fieldsobjectobligatorio
Los datos del formulario como pares clave–valor planos. Las claves siguen las mismas reglas de nombres de campo que los formularios: las conocidas rellenan nombre, teléfono, email y mensaje; el resto va a “extra”. Las claves con nombre sensible (password, card_number…) se descartan, igual que en los formularios.
options.valueintegeropcional
Importe en unidades menores: 149900 = 1.499,00. Solo se guarda en eventos con “Este evento genera ingresos”.
options.currencystringopcional
Moneda del importe, por ejemplo EUR.

Devuelve una Promise que se resuelve en:

okboolean
true: el lead se ha aceptado. false: se ha rechazado o no ha llegado; el motivo no se indica, a propósito (mira por qué).

crmLeadForm(form, name)

Hace exactamente lo mismo que el atributo data-crm-lead, pero desde código. Viene bien cuando el formulario lo renderiza una librería de terceros y no puedes añadirle atributos, o cuando el nombre se decide en tiempo de ejecución. No devuelve nada; el resultado llega por el mismo evento crm:lead.

const form = document.querySelector('#newsletter-popup form');
window.crmLeadForm(form, 'newsletter_signup');

form.addEventListener('crm:lead', (e) => {
  if (e.detail.ok) form.innerHTML = '<p>¡Ya estás dentro! Revisa tu bandeja de entrada.</p>';
});
formHTMLFormElementobligatorio
El elemento de formulario que se va a vincular.
namestringobligatorio
Nombre del evento declarado en el CRM, con las mismas reglas que en crmLead.

Declaraciones de TypeScript

El widget es un script normal, así que TypeScript no sabe nada de él. Pega esto en cualquier archivo .d.ts:

crm-widget.d.tsts
export {};

declare global {
  interface Window {
    crmLead?: (
      name: string,
      fields: Record<string, string>,
      options?: { value?: number; currency?: string },
    ) => Promise<{ ok: boolean }>;
    crmLeadForm?: (form: HTMLFormElement, name: string) => void;
  }
}

Cómo funciona la protección contra spam

Un formulario público es un imán para bots. No necesitas un CAPTCHA para mantenerlos fuera: el widget y el servidor se encargan juntos, y los visitantes reales ni se enteran.

Un pase de formulario de un solo uso

Antes de enviar, el widget obtiene del servidor un “pase de formulario” firmado. Para ganar tiempo, lo pide en cuanto el visitante pone el foco en el formulario por primera vez. Un pase es:

  • de un solo uso: un pase, un lead;
  • ligado a tu web: un pase de un sitio no sirve en otro;
  • válido durante 24 horas.

Los bots que hacen POST a ciegas contra el endpoint no tienen pase y se rechazan. Y un doble clic o un reenvío con el mismo pase devuelve { ok: true }, pero el lead se guarda una sola vez: nada de tarjetas duplicadas por culpa de dedos impacientes.

El honeypot

Es el campo oculto company_site de antes. Una persona no lo ve, así que se queda vacío. Un bot que rellena todos los campos que encuentra se delata solo, y el lead se rechaza.

Leads “sospechosos”

Algunos leads tienen algo raro pero podrían ser reales. Esos se aceptan y reciben la etiqueta Sospechoso en el CRM, para que un gestor les eche un vistazo antes de llamar:

  • el formulario se rellenó en menos de 3 segundos, más rápido de lo humanamente posible;
  • el formulario estuvo abierto más de 30 minutos antes de enviarse;
  • llegaron más de 5 leads desde una misma IP en una hora.

La IP que ves en la tarjeta del lead está recortada (en IPv4 el último octeto pasa a cero: 203.0.113.57 → 203.0.113.0; en IPv6 se corta a /48), según las mismas reglas de qué guardamos y durante cuánto.

“Spam” es un estado que una persona pone a mano en el CRM. Nada se marca como spam automáticamente, así que ningún cliente real acaba en la papelera sin que nadie se entere.

Por qué el navegador solo recibe ok: true o false

Decirle a un bot “rechazado: honeypot relleno” es darle una clase gratis de cómo colarse. Por eso, desde el navegador, todos los rechazos se ven iguales: { ok: false }, sin motivo. ¿Depurando tu propio formulario? La lista de comprobación cubre todos los casos, y la vía del servidor sí te dice qué ha fallado, porque está protegida con una clave secreta.

Por dentro: la petición del navegador

Para curiosos: nunca tendrás que montarla tú. El widget obtiene un pase de POST https://back.sitecog.com/marketing/fk (respuesta: {"pass":"…"}) y luego envía el lead:

Lo que envía el widgethttp
POST https://back.sitecog.com/marketing/f
Content-Type: application/json

{
  "n": "contact_form",
  "pass": "…",
  "fields": {
    "name": "Anna",
    "email": "anna@example.com",
    "message": "Hi!",
    "company_site": ""
  },
  "val": 149900,
  "cur": "EUR",
  "u": "https://shop.example/contacts",
  "vid": "…",
  "sid": "…"
}

La respuesta es { "ok": true } o { "ok": false }. vid y sid son los ids del visitante y de la sesión, para que el lead quede vinculado al canal publicitario por el que llegó el visitante: mira Eventos y analítica.

Envía leads desde tu servidor

No todos los leads nacen en un navegador. Usa la vía del servidor cuando:

  • un gestor toma un pedido por teléfono y lo mete en tu back office;
  • tu formulario se procesa en el backend (un handler en PHP, una server action de Next.js) y prefieres no depender del widget;
  • los leads llegan de otro sistema: un marketplace, un servicio de reservas, un bot.
POST https://back.sitecog.com/marketing/lead
x-event-key: sk_…
Content-Type: application/json

Claves secretas

La vía del servidor se autentica con una clave secreta. Créala en CRM → Marketing → Eventos → Claves secretas → Emitir una clave. Una clave tiene la forma sk_ + 48 caracteres hexadecimales; un sitio puede tener hasta 5 claves activas y cualquiera de ellas se puede revocar. Ponle a cada clave un nombre que diga dónde vive (“servidor de pagos”, “pedidos por teléfono”): tu yo del futuro te lo agradecerá cuando toque revocar una.

Ejemplo de petición

curl https://back.sitecog.com/marketing/lead \
  -H "x-event-key: sk_3f9a1c7e5b2d4f6a8c0e1b3d5f7a9c2e4b6d8f0a1c3e5b7d" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "phone_order",
    "event_id": "order-1024",
    "fields": {
      "name": "Anna Schmidt",
      "phone": "+49 30 1234567",
      "message": "Two pairs of Air 3, graphite. Delivery to the office."
    },
    "value": 149900,
    "currency": "EUR",
    "url": "https://shop.example/contacts"
  }'

Cuerpo de la petición

x-event-keyheaderstringobligatorio
Clave secreta sk_… del CRM. Si falta o está revocada → 401 invalid_key.
namestringobligatorio
Nombre del evento declarado en el CRM y marcado como “Esto es un lead”. Alias corto: n.
fieldsobjectobligatorio
El lead en sí: nombre, teléfono, email, mensaje y lo que haga falta, con las mismas reglas de nombres de campo. Tiene que incluir un teléfono o un email. Mete siempre aquí los datos de contacto: las claves que pongas en la raíz del cuerpo se mezclan con el lead.
event_idstringopcional
Tu id para este lead, hasta 128 caracteres: un número de pedido, un id de ticket. Hace la petición idempotente. Alias: id.
visitor_idstringopcional
El id del visitante del navegador (crm_vid). Alias: vid. Mira atribución.
session_idstringopcional
El id de sesión del navegador (crm_sid). Con él, el lead hereda el canal publicitario y las etiquetas UTM de esa sesión. Alias: sid.
valueintegeropcional
Importe en unidades menores: 149900 = 1.499,00. Solo se guarda en eventos con “Este evento genera ingresos”. Alias: val.
currencystringopcional
Moneda del importe, por ejemplo EUR. Alias: cur.
urlstringopcional
La página de la que trata el lead o de la que viene. Alias: u.

Respuesta

200 OKjson
{ "ok": true, "duplicate": false }
okboolean
Siempre true con un 200. Los problemas vuelven como 4xx con un message: mira errores.
duplicateboolean
true si ya existe un lead con este event_id. No se ha guardado nada nuevo, y no pasa nada.

A diferencia del navegador, la vía del servidor no usa pases de formulario ni comprobaciones de tiempo: la clave secreta ya es prueba suficiente. El honeypot sigue valiendo: un company_site no vacío en fields recibe 400 rejected. Y el filtro de nombres sensibles también: aunque la petición venga firmada con tu clave, un campo como card_number o user_password no se guarda.

Idempotencia: reintenta sin miedo

Las redes fallan en el peor momento. ¿La petición llegó o no? Con event_id no necesitas saberlo: vuelve a enviarla. Una repetición devuelve {"ok":true,"duplicate":true} y el lead no se guarda dos veces.

Mismo event_id, segunda vezjson
{ "ok": true, "duplicate": true }

Atribución: qué anuncio trajo el lead

Los leads del widget se vinculan al visitante automáticamente. Un lead del servidor no sabe nada del navegador, a menos que se lo cuentes. El widget guarda el id del visitante en localStorage con la clave crm_vid y el id de sesión con crm_sid. Envíalos a tu backend junto con el formulario o el pedido, y pásalos después:

En el navegador, al pagarjs
const crm = {
  vid: localStorage.getItem('crm_vid'),
  sid: localStorage.getItem('crm_sid'),
};

await fetch('/api/orders', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ ...order, crm }),
});
// …y en el servidor: visitor_id: body.crm.vid, session_id: body.crm.sid

Con session_id, el lead hereda el canal publicitario y las etiquetas UTM de la primera visita de esa sesión, así que aparece en los informes junto a la campaña que se lo ganó. Más en Eventos y analítica.

Errores

Desde el navegador, crmLead() y el evento crm:lead solo dicen ok: false. La vía del servidor responde con un estado y un message:

EstadoCuerpoQué ha pasado
400{"message":"unknown_event","name":"phone_order"}No hay ningún evento con este nombre en el CRM. Decláralo en Marketing → Eventos (revisa la ortografía y las mayúsculas).
400{"message":"invalid_event_name"}El nombre tiene caracteres que no son letras latinas, dígitos o guiones bajos, o no empieza por una letra.
400{"message":"no_contact"}No hay ni teléfono (7–20 dígitos) ni email en fields.
400{"message":"invalid_body"}El cuerpo no es un objeto JSON con la forma esperada.
400{"message":"rejected"}El campo honeypot company_site está relleno.
401{"message":"invalid_key"}x-event-key falta, está mal formada o revocada.
413—El cuerpo pesa más de 8 KB.
429{"message":"rate_limit_exceeded"}Demasiadas peticiones en este minuto. Espera al siguiente.

Las peticiones del navegador también pueden recibir 400 unknown_origin o 400 unknown_domain cuando el dominio de la página no es un sitio del CRM: los verás en la pestaña Network, mientras el código sigue recibiendo ok: false.

Límites

QuéLímite
Peticiones por IP (todas las rutas de marketing juntas)120 por minuto
Peticiones por sitio6000 por minuto
Pases de formulario por IP20 por minuto
Cuerpo de la petición8 KB
Nombre / teléfono / email / mensaje200 / 40 / 320 / 4000 caracteres
Campos extrahasta 30; clave de hasta 60 y valor de hasta 1000 caracteres
Teléfono7–20 dígitos para contar como contacto
event_idhasta 128 caracteres
Claves secretashasta 5 activas por sitio

Las ventanas son minutos fijos: tras un 429, espera a que empiece el minuto siguiente. Un visitante real nunca se acercará; un script aporreando tu formulario, sí.

Solución de problemas

El lead no ha llegado

Repasa la lista: casi siempre es una de estas:

  • El nombre no está declarado. En Marketing → Eventos tiene que haber un evento con exactamente este nombre, mayúsculas incluidas. Un data-crm-lead vacío equivale a lead_submit: declara ese.
  • No está marcado “Esto es un lead”. Entonces el envío se guarda como un evento normal: búscalo en las estadísticas de eventos, no en Leads.
  • Ni teléfono ni email. O están, pero con nombres que el CRM no conoce (your-phone, contact[email]) y han acabado en “extra”. Renómbralos: mira la tabla de campos. Un teléfono con menos de 7 dígitos tampoco cuenta.
  • Los datos estaban en un campo de archivo. Los archivos se ignoran: el widget solo envía texto.
  • Un campo real se llama company_site. Es el nombre del honeypot; el lead se trata como un bot.
  • Tu propio listener de crm:lead-before ha llamado a preventDefault(), quizá cuando no te lo esperabas.
  • El widget no está en esta página. Sin widget.js el atributo no hace nada y el formulario se envía a la antigua (o no se envía).
  • Lo bloquea una Content Security Policy. Si tu web tiene CSP, necesita script-src https://widget.sitecog.com y connect-src https://back.sitecog.com. La consola del navegador te lo dirá en rojo.
  • El dominio no es un sitio del CRM. El sitio se reconoce por el origen de la página (se quita el www.). Probar en localhost o en un dominio de staging que no está añadido al CRM da unknown_domain en la pestaña Network.
  • Has hecho muchas pruebas. 20 pases de formulario por minuto y por IP sobran para personas, pero no para clics frenéticos. Espera un minuto.

Ha llegado el lead, pero falta un campo

  • El nombre del campo parece sensible. Repasa la regla de nombres: un promo_pass se descarta porque pass es una palabra suelta. Renómbralo (promo_code) y listo.
  • El campo, o algo que lo envuelve, lleva data-crm-ignore. Suele pasar con un fieldset o un div heredado de otra parte del formulario.
  • Es un type="password": esos no se envían nunca.
  • Es un campo de archivo. Los archivos se ignoran de todas formas: el widget solo envía texto.

No se muestra el importe

Marca “Este evento genera ingresos” en el tipo de evento. Comprueba también que el importe es un entero en unidades menores: 1499.00 se envía como 149900.

Notificaciones en Telegram

Un lead que nadie ve es un lead perdido. En los ajustes de CRM → Leads puedes conectar un bot de Telegram: pega el token del bot, activa las notificaciones, decide si también se envían los sospechosos y fija horas de silencio para que el turno de noche de los bots no despierte a tu equipo de ventas.

Las notificaciones usan formato HTML, y todo lo que escribió el visitante se escapa antes de llegar ahí. Un “nombre” como <a href="…">Haz clic aquí</a> llega como texto plano: un visitante no puede colar un enlace en el chat de tu equipo ni romper el formato. Los campos largos se recortan para que una novela en el mensaje no se convierta en un muro de texto; el lead completo siempre está en el CRM.

Eliminar los datos de una persona a petición suya

“Por favor, borren todo lo que tengan sobre mí” es una petición normal, y atenderla no debería suponer una semana excavando en tablas. El CRM tiene dos herramientas para ello, sin código por tu parte.

Desde un lead o un chat

La ficha de un lead y la de un chat tienen “Eliminar los datos del visitante”. Antes de borrar nada, el CRM muestra exactamente qué se va a eliminar:

  • el perfil del visitante y la analítica: visitas a páginas y eventos;
  • chats y adjuntos: el número de chats, mensajes y archivos;
  • leads: solo si marcas “Eliminar también las solicitudes de este visitante”. Desactivado por defecto: un lead suele ser un negocio en curso, y la decisión es tuya.

Un lead enviado desde tu servidor sin visitor_id no está vinculado a ningún visitante, así que ahí solo se puede eliminar el propio lead.

Por correo o teléfono

Normalmente la petición llega por correo: “Soy anna@example.com, olvídenme”. Ve a CRM → Ajustes → “Solicitudes de eliminación de datos”, introduce el correo o el teléfono que dio la persona y el CRM encontrará sus leads, sus chats y su cuenta en tu web. Un botón elimina todo lo encontrado; también puede irse la analítica de visitas de los visitantes relacionados.

  • Permisos. Para eliminar se necesitan los mismos permisos que para editar esas secciones. Un gestor que solo puede ver los chats ve lo encontrado, pero no puede borrarlo.
  • Registro de actividad. Cada eliminación queda en el registro de actividad, sin el correo ni el teléfono de la persona: si no, el registro guardaría justo lo que se pidió olvidar.
  • Sin deshacer. Eliminado es eliminado. Revisa las cifras antes de confirmar.