Registrar mensajes de WhatsApp en Google Sheets y enviar desde una hoja
Apunta el destino del webhook del número a un flujo de n8n cuyo nodo de Google Sheets añada una fila por mensaje: remitente, nombre, texto, id del mensaje y hora. Para enviar desde una hoja, una función de Apps Script puede recorrer las filas y llamar a la Cloud API con UrlFetchApp, usando el phone number id y el token del número. El equipo sigue respondiendo desde la app de WhatsApp Business.
Peticiones de escritura de la API de Google Sheets permitidas por minuto y por usuario y proyecto; 300 por proyecto.
Llamadas URL Fetch de Apps Script para una cuenta de Google personal; las cuentas de Workspace tienen 100.000.
Tiempo máximo que puede ejecutarse una sola ejecución de Apps Script antes de detenerse.
¿Cómo se convierte cada mensaje de WhatsApp en una fila?
Meta envía cada mensaje del número al destino del webhook que configures, aquí un nodo Webhook de n8n que además responde a la petición de verificación de Meta. El siguiente nodo es Google Sheets con la operación Append Row, que asigna campos del payload a columnas: el número del remitente, el nombre de perfil, el texto, el id del mensaje de WhatsApp, la marca de tiempo y el phone number id receptor.
Usa Append or Update Row con el id del mensaje como clave en lugar de un simple append si quieres que los reintentos sean inofensivos. Meta vuelve a entregar un mensaje cuando cree que una entrega falló, y con el id como clave la segunda entrega se convierte en una actualización de la misma fila.
En un número con Coexistencia, las respuestas escritas en la app de WhatsApp Business llegan al mismo webhook como eventos smb_message_echoes. Regístralas con una columna de dirección y la hoja contendrá ambos lados de la conversación.
¿Dónde afecta la cuota de Sheets?
En las escrituras por usuario. La API de Sheets permite 300 peticiones de escritura por minuto y proyecto, y 60 por minuto y usuario por proyecto, y una credencial de n8n cuenta como un solo usuario. Un flujo que añade una fila por mensaje puede por tanto absorber cerca de un mensaje por segundo de forma sostenida.
Eso basta de sobra para la mayoría de los números de tienda. Deja de bastar tras una plantilla de difusión, cuando unos cientos de clientes responden en pocos minutos. La API responde entonces 429 Too Many Requests y, sin reintentos, se pierden filas.
Hay dos soluciones, y con cualquiera de ellas basta. Activa los reintentos con espera en el nodo de Google Sheets, lo que coincide con el consejo de Google de retroceder de forma exponencial. O agrupa: haz que n8n junte mensajes durante treinta segundos y los añada en una sola petición, de modo que muchas escrituras se conviertan en una.
¿Cómo se envían plantillas desde una hoja?
Con Apps Script, desde el menú Extensiones de la hoja. Una función lee las filas que aún no se han enviado, llama para cada una al endpoint de mensajes de la Cloud API con UrlFetchApp y escribe en la fila el id del mensaje devuelto y la hora. Un activador temporal puede ejecutarla cada pocos minutos, o puedes lanzarla a mano desde un menú personalizado.
Guarda el token de acceso en las propiedades del script y no en el código, para que quien pueda ver el script no lo vea.
Ten presentes las cuotas. Una cuenta de Google personal tiene 20.000 llamadas URL Fetch al día y una cuenta de Workspace 100.000, y cada ejecución se detiene a los seis minutos. Procesa las filas por lotes y marca cada una como enviada antes de seguir, para que una ejecución interrumpida continúe donde se quedó en lugar de enviar dos veces.
function sendPending() {
const token = PropertiesService.getScriptProperties().getProperty("WHATSAPP_TOKEN");
const sheet = SpreadsheetApp.getActive().getSheetByName("Send");
const rows = sheet.getDataRange().getValues();
for (let i = 1; i < rows.length; i++) {
const [phone, name, sentAt] = rows[i];
if (sentAt) continue;
const res = UrlFetchApp.fetch("https://graph.facebook.com/v23.0/<PHONE_NUMBER_ID>/messages", {
method: "post",
contentType: "application/json",
headers: { Authorization: "Bearer " + token },
payload: JSON.stringify({
messaging_product: "whatsapp", to: String(phone), type: "template",
template: { name: "order_ready", language: { code: "en" },
components: [{ type: "body", parameters: [{ type: "text", text: name }] }] },
}),
});
sheet.getRange(i + 1, 3).setValue(new Date());
}
}Errores comunes
- Añadir filas sin una clave basada en el id del mensaje. Los reintentos de Meta escriben entonces el mismo mensaje en dos filas.
- Escribir una fila por mensaje con una sola credencial durante una ráfaga de respuestas. El límite de 60 escrituras por minuto y usuario devuelve 429 y se pierden filas.
- Enviar texto libre desde la hoja a personas que no han escrito en las últimas 24 horas. Fuera de esa ventana de atención solo llega una plantilla aprobada.
Conecta el número en easycoexistence.com, apunta su destino del webhook al flujo de n8n y copia el phone number id y el token en el script. Desde US$ 9 por número conectado al mes, bajando hasta US$ 1 a medida que añades números, con los primeros 3 días gratis.
Preguntas frecuentes
¿Puedo usar Make o Zapier en lugar de n8n?
Sí. Un webhook personalizado de Make o un catch hook de Zapier recibe el mensaje y su paso de Google Sheets añade la fila.
¿Con qué cuenta de Google escribe n8n?
Con la que autorizó la credencial de Google en n8n. Esa cuenta necesita acceso de edición a la hoja, y su cuota de escritura por usuario es la que consume el flujo.
¿La columna del teléfono tiene el formato correcto?
Guarda los números como texto plano: dígitos con el código de país y sin el signo más, que es la forma en que Meta los envía. De lo contrario Sheets los trata como números, lo que elimina el signo más inicial y puede reformatear valores largos.
¿EasyCoexistence guarda una copia de los mensajes?
No. Meta entrega cada webhook a tu URL de n8n, y la hoja es la única copia.
Sigue leyendo
¿Listo para empezar?
Configura WhatsApp Coexistence en minutos, no en meses. La app sigue funcionando en el teléfono.
Empezar prueba gratisVerificado el