Verificación de email en Shopify
Shopify no expone un hook previo al registro en la tienda, pero puedes verificar los emails con dos enfoques complementarios:
- App Proxy — un endpoint en tu servidor al que llama el JavaScript de tu tienda antes de enviar el formulario de registro
- Webhook customers/create — un webhook que se dispara después de crear el cliente y te permite etiquetar o marcar las cuentas inválidas
Este tutorial cubre los dos patrones.
Requisitos previos
- Una tienda de Shopify y una cuenta de Partner
- Una aplicación en Node.js (Express o similar) desplegada de forma pública
- Una clave de API de Mailbeam (regístrate gratis)
Opción A — App Proxy (en tiempo real, antes del registro)
Un App Proxy enruta las peticiones de {tu-tienda}.myshopify.com/apps/verify-email a tu servidor.
Configura el App Proxy
En los ajustes de tu app de Shopify Partner → App proxy:
- Subpath:
apps - Subpath prefix:
verify-email - Proxy URL:
https://tu-servidor.com/api/verify-email
El endpoint del proxy
// server/routes/shopifyVerify.js
import express from "express";
// Todavía no hay SDK: este es el envoltorio de 12 líneas de /docs/quickstart.
import { verifyEmail } from "./lib/mailbeam";
const router = express.Router();
router.post("/api/verify-email", async (req, res) => {
const { email } = req.body;
if (!email) {
return res.json({ valid: false, error: "El email es obligatorio." });
}
try {
const { valid, score, reason } = await verifyEmail(email);
if (!valid || score < 60) {
const message =
reason === "disposable_domain"
? "Usa una dirección de email permanente."
: "Escribe una dirección de email válida.";
return res.json({ valid: false, error: message });
}
res.json({ valid: true });
} catch {
// Falla en abierto: no bloquees el registro
res.json({ valid: true });
}
});
export default router;JavaScript en la tienda
Añade esto a la plantilla de registro de tu tema de Shopify:
// assets/mailbeam-verify.js
(function () {
const form = document.querySelector('form[action="/account"]');
const emailInput = document.querySelector('input[name="customer[email]"]');
if (!form || !emailInput) return;
form.addEventListener('submit', async function (event) {
// Intercepta solo los formularios de registro
const actionInput = form.querySelector('input[name="form_type"]');
if (!actionInput || actionInput.value !== 'create_customer') return;
event.preventDefault();
const email = emailInput.value.trim();
try {
const res = await fetch('/apps/verify-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email }),
});
const { valid, error } = await res.json();
if (!valid) {
showError(emailInput, error || 'Usa una dirección de email válida.');
return;
}
} catch {
// Falla en abierto ante errores de red
}
form.submit();
});
function showError(input, message) {
let errorEl = document.getElementById('mailbeam-email-error');
if (!errorEl) {
errorEl = document.createElement('p');
errorEl.id = 'mailbeam-email-error';
errorEl.style.cssText = 'color: red; font-size: 0.875rem; margin-top: 0.25rem;';
input.parentNode.insertBefore(errorEl, input.nextSibling);
}
errorEl.textContent = message;
input.focus();
}
})();Opción B — webhook customers/create (después del registro)
Este patrón se ejecuta después de que Shopify cree el cliente. Es útil para etiquetar cuentas sospechosas:
// server/routes/shopifyWebhook.js
import crypto from "crypto";
// Todavía no hay SDK: este es el envoltorio de 12 líneas de /docs/quickstart.
import { verifyEmail } from "./lib/mailbeam";
router.post("/webhooks/customers/create", express.raw({ type: "application/json" }), async (req, res) => {
// Verifica la firma del webhook
const hmac = req.headers["x-shopify-hmac-sha256"];
const hash = crypto
.createHmac("sha256", process.env.SHOPIFY_WEBHOOK_SECRET)
.update(req.body)
.digest("base64");
if (hmac !== hash) {
return res.status(401).send("Unauthorized");
}
const customer = JSON.parse(req.body.toString());
const { email, id: customerId } = customer;
try {
const { valid, score } = await verifyEmail(email);
if (!valid || score < 40) {
// Etiqueta al cliente para revisarlo
await tagShopifyCustomer(customerId, ["suspicious-email", "requires-review"]);
}
} catch {
// Registra el error pero no hagas fallar el webhook
console.error("[Mailbeam] error de verificación");
}
res.status(200).send("OK");
});Buenas prácticas
- Usa el App Proxy para prevenir en tiempo real y el webhook para auditar
- Devuelve siempre
{ valid: true }en los bloques catch: falla en abierto - La verificación HMAC de Shopify es obligatoria en los webhooks (buena práctica de seguridad)