Cómo medir fuente y medio para Ninja Forms 📊
Aquí puedes empezar con una breve explicación de por qué es importante medir la fuente y el medio de los envíos de formularios. Menciona los beneficios, como entender de dónde vienen tus leads y optimizar tus campañas de marketing. Puedes incluir una frase como “Si alguna vez te has preguntado de dónde provienen los envíos de tus formularios de Ninja Forms, ¡este tutorial es para ti!”.

¿Qué son la fuente (source) y el medio (medium)? 🤔
Es crucial aclarar estos conceptos antes de ir a lo técnico.
Fuente (source): Es el origen de donde vino la visita, por ejemplo, Google, Facebook, un correo electrónico, etc.
Medio (medium): Es la categoría general de la fuente, como “orgánico”, “pago” (CPC), “social”, “email”, etc.
1) JavaScript (first-touch + autollenado)
Pega tal cual en el footer del theme (o en un HTML widget global), una sola vez:
<script>
(function () {
var COOKIE = "rkz_attrib";
var DAYS = 90;
function cookieDomain(){
var h = location.hostname.split('.');
return (h.length >= 2) ? "."+h.slice(-2).join('.') : location.hostname;
}
function setCookie(name, value, days){
var d = new Date(); d.setTime(d.getTime()+days*864e5);
document.cookie = name+"="+encodeURIComponent(JSON.stringify(value))+
"; expires="+d.toUTCString()+"; path=/; domain="+cookieDomain()+"; SameSite=Lax";
}
function getCookie(name){
var m = document.cookie.match(new RegExp('(^| )'+name+'=([^;]+)'));
if (!m) return null;
try { return JSON.parse(decodeURIComponent(m[2])); } catch(e){ return null; }
}
var p = new URLSearchParams(location.search);
var ref = document.referrer || "";
var hasUTM = ["utm_source","utm_medium","utm_campaign","utm_term","utm_content"].some(k => p.has(k));
var hasAdsId = p.has("gclid") || p.has("fbclid") || p.has("msclkid");
function classify(){
var src = (p.get("utm_source") || "").toLowerCase();
var med = (p.get("utm_medium") || "").toLowerCase();
var camp = (p.get("utm_campaign") || "").toLowerCase();
var r = ref.toLowerCase();
var channel = "Directo";
if (hasAdsId || ["cpc","ppc","paid","sem"].includes(med)) channel = "Paid Search";
else if (r.includes("google.") || r.includes("bing.") || r.includes("yahoo.") || r.includes("duckduckgo")) channel = "Orgánico";
else if (r.includes("facebook") || r.includes("instagram") || r.includes("t.co") || r.includes("x.com") || r.includes("linkedin")) channel = "Social";
else if (ref) channel = "Referido";
var source = src || (ref ? (new URL(ref)).hostname.replace(/^www\./,"") : "direct");
var medium = med || (channel==="Orgánico" ? "organic" : channel==="Social" ? "social" : channel==="Paid Search" ? "cpc" : "direct");
return { source, medium, campaign: camp, channel };
}
// Set first-touch once, or refresh if llega con nuevas UTM/IDs
var attrib = getCookie(COOKIE);
if (!attrib || hasUTM || hasAdsId) {
var c = classify();
attrib = { source:c.source, medium:c.medium, campaign:c.campaign, channel:c.channel,
landing: location.href, referrer: ref, ts: new Date().toISOString() };
setCookie(COOKIE, attrib, DAYS);
}
function fill(){
var a = getCookie(COOKIE) || {};
var value = [a.source, a.medium, a.campaign].filter(Boolean).join(" / ");
document.querySelectorAll("input.js-medio").forEach(function(el){
if (!el.value) el.value = value || "Desconocido";
});
}
document.addEventListener("DOMContentLoaded", fill);
document.addEventListener("nfFormReady", fill);
})();
</script>
2) PHP (respaldo server-side)
Deja solo este snippet en functions.php
de tu child theme (
<?php
// Rellena el campo 'medio' al enviar (server-side)
add_filter('ninja_forms_submit_data', function($form_data){
// 1) Intenta desde cookie (first-touch)
$value = '';
if (!empty($_COOKIE['rkz_attrib'])) {
$json = json_decode(stripslashes($_COOKIE['rkz_attrib']), true);
if (is_array($json)) {
$src = sanitize_text_field($json['source'] ?? '');
$med = sanitize_text_field($json['medium'] ?? '');
$cmp = sanitize_text_field($json['campaign'] ?? '');
$value = trim(implode(' / ', array_filter([$src, $med, $cmp])));
}
}
// 2) Fallback: UTM o referrer
if ($value === '') {
$utm_source = sanitize_text_field($_GET['utm_source'] ?? '');
$utm_medium = sanitize_text_field($_GET['utm_medium'] ?? '');
$utm_campaign = sanitize_text_field($_GET['utm_campaign'] ?? '');
if ($utm_source || $utm_medium || $utm_campaign) {
$value = implode(' / ', array_filter([$utm_source, $utm_medium, $utm_campaign]));
} else {
$ref = strtolower(sanitize_text_field($_SERVER['HTTP_REFERER'] ?? ''));
if (!$ref) $value = 'Directo';
elseif (strpos($ref,'google')!==false || strpos($ref,'bing')!==false || strpos($ref,'yahoo')!==false || strpos($ref,'duckduckgo')!==false) $value='Orgánico';
elseif (strpos($ref,'facebook')!==false || strpos($ref,'instagram')!==false || strpos($ref,'x.com')!==false || strpos($ref,'t.co')!==false || strpos($ref,'linkedin')!==false) $value='Social';
else $value='Referido';
}
}
// 3) Escribe en el campo key = 'medio' si está vacío
if (!empty($form_data['fields']) && is_array($form_data['fields'])) {
foreach ($form_data['fields'] as &$field) {
if (($field['key'] ?? '') === 'medio' && empty($field['value'])) {
$field['value'] = $value ?: 'Desconocido';
}
}
}
return $form_data;
}, 999);
?>
Pruebas (rápidas)
UTM: abre la página del formulario con
?utm_source=google&utm_medium=cpc&utm_campaign=prueba
→ envía → el envío debe mostrargoogle / cpc / prueba
en medio.Orgánico: entra desde una búsqueda de Google sin UTM →
Orgánico
.Social: entra desde un enlace en Facebook/Instagram →
Social
.Directo: escribe la URL a mano →
Directo
.