📄 6.6.9. ¿Cómo insertar codigo Javascript en mi sitio web?

¿Cómo insertar codigo Javascript o Scripts en mi sitio web?


.El Editor JS de Waclis te permite incorporar código JavaScript para agregar funcionalidades, mediciones y widgets (como Analytics, píxeles, chatbots, botones, efectos y automatizaciones).

El Editor JS te permite incorporar código JavaScript, cargar scripts externos, y también agregar links CSS (por ejemplo, para estilos de un widget o librería), sin tocar el código base del sitio.


Beneficios

  • Agregas integraciones (Analytics, píxeles, Hotjar, chat, etc.) en minutos.

  • Mejoras la experiencia del usuario (botones, efectos, validaciones, formularios).

  • Personalizas comportamiento del sitio sin depender de desarrollos complejos.

  • Centralizas tus scripts en un solo lugar.




Pasos detallados


Cómo acceder al Editor JS

  1. Ingresa a tu Waclis.

  2. Ve a Configuración > Diseño > Editar sitio.

  3. Haz clic en Personalizar diseño y luego en Editor JS.

  4. Verás un campo de texto: pega allí tu código (Ctrl+V / Command+V).

  5. Haz clic en Guardar.

  6. Revisa tu sitio en una pestaña nueva y valida que todo funcione como esperas.


⚠️
  • Todo lo que pegues debe ir entre:

    <script> y </script>

  • Puedes pegar varios scripts, uno debajo del otro, idealmente separados por una línea y con comentarios.

  • Si un proveedor te da un script que ya incluye <script>...</script>, pégalo tal cual.


💡

Base obligatoria para que los scripts funcionen correctamente 

En sitios creados con Waclis, algunos elementos (como botones, secciones, productos, carruseles o el carrito) pueden cargarse después de que la página ya inició.

Por eso, si pegas un script “común” puede que no encuentre los elementos y parezca que “no funciona”.

✅ Para evitarlo, te recomendamos pegar primero esta “base obligatoria” en tu Editor JS.

Esta base se encarga de:

  • Esperar a que el sitio termine de cargar.

  • Reintentar buscar elementos que se cargan más tarde.

  • Reaplicar scripts cuando el contenido cambia (por ejemplo, cuando se actualiza un listado o se abre un modal).

Importante: agrega esta base una sola vez, al inicio.

Luego pega debajo tus scripts personalizados.

Código de la base obligatoria (para pegar en el Editor JS)

<script>
(function () {
window.NX = window.NX || {};

// Ejecuta cuando el DOM está listo
NX.onReady = function (fn) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", fn);
} else {
fn();
}
};

// Espera a que exista un elemento (reintenta hasta timeout)
NX.waitFor = function (selector, cb, opts) {
opts = opts || {};
var timeout = opts.timeout || 12000;
var interval = opts.interval || 200;
var start = Date.now();

var timer = setInterval(function () {
var el = document.querySelector(selector);
if (el) {
clearInterval(timer);
cb(el);
} else if (Date.now() - start > timeout) {
clearInterval(timer);
}
}, interval);
};

// Re-ejecuta una función cuando el sitio cambia contenido (renders, modales, listados, etc.)
NX.observeRerun = function (fn) {
var t;
var mo = new MutationObserver(function () {
clearTimeout(t);
t = setTimeout(fn, 250);
});
mo.observe(document.documentElement, { childList: true, subtree: true });
};
})();
</script>



Ejemplos de personalización con JavaScript


1) Google Analytics 4 (GA4) – gtag

<script>
(function () {
var GA_ID = "G-XXXXXXXXXX"; // Reemplaza por tu ID
var s = document.createElement("script");
s.async = true;
s.src = "https://www.googletagmanager.com/gtag/js?id=" + encodeURIComponent(GA_ID);
document.head.appendChild(s);

window.dataLayer = window.dataLayer || [];
function gtag(){ dataLayer.push(arguments); }
window.gtag = gtag;

gtag("js", new Date());
gtag("config", GA_ID);
})();
</script>

2) Google Tag Manager (GTM)

<script>
(function(w,d,s,l,i){
w[l]=w[l]||[];
w[l].push({"gtm.start": new Date().getTime(), event:"gtm.js"});
var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),
dl=l!="dataLayer"?"&l="+l:"";
j.async=true;
j.src="https://www.googletagmanager.com/gtm.js?id="+i+dl;
f.parentNode.insertBefore(j,f);
})(window,document,"script","dataLayer","GTM-XXXXXXX"); // Reemplaza GTM-XXXXXXX
</script>

3) Meta Pixel (Facebook/Instagram)

<script>
(function(f,b,e,v,n,t,s){
if(f.fbq) return;
n=f.fbq=function(){ n.callMethod? n.callMethod.apply(n,arguments) : n.queue.push(arguments); };
if(!f._fbq) f._fbq=n;
n.push=n; n.loaded=!0; n.version="2.0"; n.queue=[];
t=b.createElement(e); t.async=!0; t.src=v;
s=b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t,s);
})(window, document, "script", "https://connect.facebook.net/en_US/fbevents.js");

fbq("init", "123456789012345"); // Reemplaza por tu Pixel ID
fbq("track", "PageView");
</script>

4) TikTok Pixel

<script>
(function (w, d, t) {
w.TiktokAnalyticsObject = t;
var ttq = w[t] = w[t] || [];
ttq.methods = ["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie"];
ttq.setAndDefer = function(t,e){ t[e]=function(){ t.push([e].concat([].slice.call(arguments,0))); }; };
for (var i=0; i<ttq.methods.length; i++) ttq.setAndDefer(ttq, ttq.methods[i]);
ttq.instance = function(t){ var e=ttq._i[t]||[]; for (var n=0; n<ttq.methods.length; n++) ttq.setAndDefer(e, ttq.methods[n]); return e; };
ttq.load = function(e,n){
var i="https://analytics.tiktok.com/i18n/pixel/events.js";
ttq._i=ttq._i||{}; ttq._i[e]=[]; ttq._i[e]._u=i; ttq._t=ttq._t||{}; ttq._t[e]=+new Date;
ttq._o=ttq._o||{}; ttq._o[e]=n||{};
var o=d.createElement("script"); o.async=!0; o.src=i+"?sdkid="+e+"&lib="+t;
var a=d.getElementsByTagName("script")[0]; a.parentNode.insertBefore(o,a);
};
ttq.load("XXXXXXXXXXXXXXX"); // Reemplaza por tu Pixel ID
ttq.page();
})(window, document, "ttq");
</script>

5) Hotjar (mapas de calor y grabaciones)

<script>
(function(h,o,t,j,a,r){
h.hj=h.hj||function(){ (h.hj.q=h.hj.q||[]).push(arguments); };
h._hjSettings={hjid:1234567,hjsv:6}; // Reemplaza hjid
a=o.getElementsByTagName("head")[0];
r=o.createElement("script"); r.async=1;
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
a.appendChild(r);
})(window,document,"https://static.hotjar.com/c/hotjar-",".js?sv=");
</script>

6) Cargar un chatbot (script externo genérico)

<script>
(function () {
var s = document.createElement("script");
s.async = true;
s.src = "https://TU-CHATBOT.com/widget.js"; // Reemplaza por el link real del proveedor
document.head.appendChild(s);
})();
</script>

7) Botón “Volver arriba”

<script>
NX.onReady(function () {
if (document.getElementById("nxTopBtn")) return;

var btn = document.createElement("button");
btn.id = "nxTopBtn";
btn.textContent = "↑";
btn.setAttribute("aria-label", "Volver arriba");
btn.style.cssText = "position:fixed;right:16px;bottom:16px;width:44px;height:44px;border-radius:999px;border:0;cursor:pointer;display:none;z-index:999999;box-shadow:0 10px 25px rgba(0,0,0,.15)";
document.body.appendChild(btn);

window.addEventListener("scroll", function () {
btn.style.display = window.scrollY > 500 ? "block" : "none";
});

btn.addEventListener("click", function () {
window.scrollTo({ top: 0, behavior: "smooth" });
});
});
</script>

8) Scroll suave para links con “#”

<script>
NX.onReady(function () {
document.addEventListener("click", function (e) {
var a = e.target.closest('a[href^="#"]');
if (!a) return;

var id = a.getAttribute("href");
if (!id || id === "#") return;

var target = document.querySelector(id);
if (!target) return;

e.preventDefault();
target.scrollIntoView({ behavior: "smooth", block: "start" });
});
});
</script>

9) Sombra en header al hacer scroll (funciona aunque el header no tenga clase fija)

<script>
NX.onReady(function () {
function apply() {
var header = document.querySelector("header") || document.querySelector(".navbar") || document.querySelector("[class*='header']");
if (!header) return;

var onScroll = function () {
header.style.boxShadow = window.scrollY > 10 ? "0 8px 24px rgba(0,0,0,.12)" : "none";
};
window.addEventListener("scroll", onScroll, { passive: true });
onScroll();
}

apply();
NX.observeRerun(apply);
});
</script>

10) Guardar UTMs (campañas) para usarlas después

<script>
NX.onReady(function () {
var params = new URLSearchParams(location.search);
var keys = ["utm_source","utm_medium","utm_campaign","utm_term","utm_content"];
var data = {};
keys.forEach(function (k) { var v = params.get(k); if (v) data[k] = v; });

if (Object.keys(data).length) {
localStorage.setItem("nx_utm", JSON.stringify(data));
}
});
</script>

11) Pegar UTMs en inputs ocultos (si existen)

<script>
NX.onReady(function () {
function apply() {
var raw = localStorage.getItem("nx_utm");
if (!raw) return;

var utm;
try { utm = JSON.parse(raw); } catch(e) { return; }

document.querySelectorAll("form").forEach(function (form) {
Object.keys(utm).forEach(function (k) {
var input = form.querySelector('input[name="'+k+'"]');
if (input) input.value = utm[k];
});
});
}

apply();
NX.observeRerun(apply);
});
</script>

12) WhatsApp dinámico (mensaje con página actual)

<script>
NX.onReady(function () {
var PHONE = "5491100000000"; // CAMBIA: código país + número (sin +)
function buildMsg() {
return "Hola, tengo una consulta sobre: " + document.title + " - " + location.href;
}
function apply() {
// Si ya existe un botón de WhatsApp, lo intenta encontrar
var wa = document.querySelector('a[href*="wa.me"], a[href*="api.whatsapp.com"]');
if (!wa) return;

wa.href = "https://wa.me/" + PHONE + "?text=" + encodeURIComponent(buildMsg());
wa.target = "_blank";
wa.rel = "noopener";
}

apply();
NX.observeRerun(apply);
});
</script>

13) “Copiar cupón” (funciona con cualquier botón que tenga data-copy)

<script>
NX.onReady(function () {
document.addEventListener("click", async function (e) {
var btn = e.target.closest("[data-copy]");
if (!btn) return;

try {
await navigator.clipboard.writeText(btn.getAttribute("data-copy") || "");
btn.setAttribute("data-copied", "1");
btn.textContent = "Copiado ✅";
setTimeout(function(){ btn.removeAttribute("data-copied"); }, 1500);
} catch (err) {
alert("No se pudo copiar. Intenta manualmente.");
}
});
});
</script>

14) Banner superior cerrable (no vuelve a aparecer)

<script>
NX.onReady(function () {
var KEY = "nx_hide_banner_top";
if (localStorage.getItem(KEY) === "1") return;
if (document.getElementById("nxTopBanner")) return;

var bar = document.createElement("div");
bar.id = "nxTopBanner";
bar.style.cssText = "position:sticky;top:0;z-index:999999;padding:10px 14px;text-align:center;background:#111;color:#fff;font-size:14px";
bar.innerHTML = '🚚 Envíos a todo el país <button id="nxCloseTopBanner" style="margin-left:10px;border:0;padding:6px 10px;border-radius:10px;cursor:pointer;">Cerrar</button>';
document.body.prepend(bar);

bar.querySelector("#nxCloseTopBanner").addEventListener("click", function () {
localStorage.setItem(KEY, "1");
bar.remove();
});
});
</script>

15) Lazy-load de imágenes (mejora performance)

<script>
NX.onReady(function () {
function apply() {
document.querySelectorAll("img").forEach(function (img) {
if (!img.hasAttribute("loading")) img.setAttribute("loading", "lazy");
if (!img.hasAttribute("decoding")) img.setAttribute("decoding", "async");
});
}
apply();
NX.observeRerun(apply);
});
</script>

16) Contador regresivo (solo si existe #countdown)

<script>
NX.onReady(function () {
var el = document.getElementById("countdown");
if (!el) return;

var target = new Date("2026-01-10T23:59:59").getTime();
var timer = setInterval(function () {
var diff = target - Date.now();
if (diff <= 0) { clearInterval(timer); el.textContent = "¡Terminó!"; return; }

var d = Math.floor(diff / (1000*60*60*24));
var h = Math.floor((diff / (1000*60*60)) % 24);
var m = Math.floor((diff / (1000*60)) % 60);
var s = Math.floor((diff / 1000) % 60);
el.textContent = d + "d " + h + "h " + m + "m " + s + "s";
}, 1000);
});
</script>

17) Autocompletar año actual (si existe #currentYear)

<script>
NX.onReady(function () {
function apply() {
var el = document.getElementById("currentYear");
if (el) el.textContent = String(new Date().getFullYear());
}
apply();
NX.observeRerun(apply);
});
</script>

18) Detectar clicks en “Agregar al carrito” (tracking básico)

<script>
NX.onReady(function () {
document.addEventListener("click", function (e) {
var btn = e.target.closest("button, a, input");
if (!btn) return;

var txt = (btn.textContent || btn.value || "").trim().toLowerCase();
if (!txt.includes("agregar al carrito")) return;

console.log("[NX] Click agregar al carrito:", { page: location.href, title: document.title });
});
});
</script>

19) Modal “Ayuda” simple (botón flotante + modal)

<script>
NX.onReady(function () {
if (document.getElementById("nxHelpFab")) return;

var fab = document.createElement("button");
fab.id = "nxHelpFab";
fab.textContent = "Ayuda";
fab.style.cssText = "position:fixed;left:16px;bottom:16px;z-index:999999;border:0;border-radius:999px;padding:12px 14px;cursor:pointer;box-shadow:0 10px 25px rgba(0,0,0,.15)";
document.body.appendChild(fab);

var modal = document.createElement("div");
modal.id = "nxHelpModal";
modal.style.cssText = "position:fixed;inset:0;display:none;z-index:999999;background:rgba(0,0,0,.45)";
modal.innerHTML = '<div style="max-width:520px;margin:10vh auto;background:#fff;border-radius:16px;padding:18px;box-shadow:0 15px 45px rgba(0,0,0,.2)">' +
'<div style="display:flex;justify-content:space-between;align-items:center">' +
'<b>¿Necesitas ayuda?</b><button id="nxHelpClose" style="border:0;cursor:pointer">✕</button></div>' +
'<p style="margin:10px 0 0">Escribe por WhatsApp o envía un email desde la sección de contacto.</p>' +
'</div>';
document.body.appendChild(modal);

fab.addEventListener("click", function () { modal.style.display = "block"; });
modal.addEventListener("click", function (e) {
if (e.target.id === "nxHelpModal" || e.target.id === "nxHelpClose") modal.style.display = "none";
});
});
</script>

20) Forzar target=_blank en links externos

<script>
NX.onReady(function () {
function apply() {
document.querySelectorAll("a[href^='http']").forEach(function (a) {
try {
var u = new URL(a.href);
if (u.host !== location.host) {
a.target = "_blank";
a.rel = "noopener";
}
} catch(e) {}
});
}
apply();
NX.observeRerun(apply);
});
</script>

21) Bloquear “Enter” en inputs (evita envíos accidentales)

<script>
NX.onReady(function () {
document.addEventListener("keydown", function (e) {
var el = e.target;
if (!(el instanceof HTMLInputElement)) return;
if (e.key !== "Enter") return;

// Permite enter en búsquedas, bloquea en formularios comunes
if ((el.type || "").toLowerCase() !== "search") {
e.preventDefault();
}
}, true);
});
</script>

22) Validación simple de email

<script>
NX.onReady(function () {
document.addEventListener("submit", function (e) {
var form = e.target;
if (!(form instanceof HTMLFormElement)) return;

var email = form.querySelector('input[type="email"]');
if (!email) return;

var ok = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value.trim());
if (!ok) {
e.preventDefault();
alert("Revisa el email, parece inválido.");
email.focus();
}
}, true);
});
</script>

23) Detectar si hay “carrito” visible y loguear cambios

<script>
NX.onReady(function () {
function scan() {
var cart = document.querySelector("[href*='carrito'], [class*='carrito'], [id*='carrito']");
if (cart) console.log("[NX] Carrito detectado en la página");
}
scan();
NX.observeRerun(scan);
});
</script>

24) Cargar CSS externo (real y seguro)

<script>
NX.onReady(function () {
var href = "https://TU-DOMINIO.com/tu-estilo.css"; // cambia esto
if ([].slice.call(document.styleSheets).some(function(s){ return s.href === href; })) return;

var link = document.createElement("link");
link.rel = "stylesheet";
link.href = href;
document.head.appendChild(link);
});
</script>

25) Cargar scriptxterno (real y seguro)

<script>
NX.onReady(function () {
function loadScript(src) {
return new Promise(function (resolve, reject) {
if (document.querySelector('script[src="'+src+'"]')) return resolve();
var s = document.createElement("script");
s.async = true;
s.src = src;
s.onload = resolve;
s.onerror = reject;
document.head.appendChild(s);
});
}

loadScript("https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js")
.then(function(){ console.log("[NX] dayjs cargado"); })
.catch(function(){ console.log("[NX] No se pudo cargar dayjs"); });
});
</script>

26) Resaltar productos “Destacados” (busca títulos comunes)

<script>
NX.onReady(function () {
function apply() {
var h = Array.from(document.querySelectorAll("h1,h2,h3,h4")).find(function (x) {
return (x.textContent || "").trim().toLowerCase() === "destacados";
});
if (!h) return;

h.style.textTransform = "uppercase";
h.style.letterSpacing = "0.08em";
}
apply();
NX.observeRerun(apply);
});
</script>

27) “Sticky” en CTA de WhatsApp (si existe link a wa.me)

<script>
NX.onReady(function () {
function apply() {
var wa = document.querySelector('a[href*="wa.me"]');
if (!wa) return;

wa.style.position = "fixed";
wa.style.right = "16px";
wa.style.bottom = "80px";
wa.style.zIndex = "999999";
}
apply();
NX.observeRerun(apply);
});
</script>

28) Debug rápido: mostrar errores de JS en pantalla (para validar en vivo)

<script>
NX.onReady(function () {
if (document.getElementById("nxJsDebug")) return;

var box = document.createElement("div");
box.id = "nxJsDebug";
box.style.cssText = "position:fixed;left:12px;top:12px;max-width:520px;z-index:999999;background:#111;color:#fff;padding:10px 12px;border-radius:12px;font-size:12px;display:none;white-space:pre-wrap";
document.body.appendChild(box);

function show(msg) {
box.style.display = "block";
box.textContent = msg;
}

window.addEventListener("error", function (e) {
show("JS ERROR: " + (e.message || "Error") + "\n" + (e.filename || "") + ":" + (e.lineno || ""));
});

window.addEventListener("unhandledrejection", function (e) {
show("PROMISE REJECTION:\n" + String(e.reason || "Rechazo no manejado"));
});
});
</script>