Analizando el Rendimiento de tu Tienda en el Panel de Jumpseller
Mejora tus ventas analizando el comportamiento de tus clientes. Distintas métricas te ayudaran en el análisis respecto a la administración de tus p...
Tampermonkey es una extensión que permite personalizar cómo ves el panel de tu tienda. En esta guía instalarás un contador de unidades por pedido, sin tener que programar. El script es el código que copiarás desde esta misma página.
Necesitas Google Chrome actualizado en un computador y acceso al panel de tu tienda. Este ejemplo funciona en la pantalla actual de Pedidos, con una dirección del tipo mi-tienda.jumpseller.com/admin/. Si accedes desde otro dominio o usas otra pantalla de pedidos, escríbenos antes de instalarlo.
El contador se muestra solo en el perfil de Chrome donde lo instalas. No modifica los pedidos ni añade el total a correos o exportaciones. No lo uses para preparar pedidos con packs o bundles, porque puede contar sus productos más de una vez. No está preparado para Chrome en teléfonos.
Verás la confirmación de que la extensión está instalada. Si aparece Quitar de Chrome / Remove from Chrome, ya la tienes y puedes continuar.
chrome://extensions/ en la barra de direcciones de Chrome y pulsa Intro.El interruptor debe quedar activado, como en esta imagen:

Si no encuentras este ajuste, actualiza Chrome y vuelve a intentarlo. Si tu computador no permite actualizarlo, envíanos una captura para ayudarte. Consulta también la ayuda oficial de Tampermonkey.
No necesitas modificar el código. Se ejecuta únicamente en las páginas de pedidos del panel de tiendas Jumpseller, no en el sitio público ni en otras páginas web.
// ==UserScript==
// @name Jumpseller — Order units (visual)
// @namespace jumpseller.local.order-units
// @version 0.3.0
// @description Suma las cantidades ya renderizadas del pedido. Solo visual; no guarda ni envía datos.
// @match https://*.jumpseller.com/admin/*/orders/*
// @match https://*.jumpseller.com/admin/orders/*
// @match https://*.jumpseller.com/admin/*/orders-v2/*
// @match https://*.jumpseller.com/admin/orders-v2/*
// @run-at document-idle
// @grant none
// @noframes
// ==/UserScript==
/* Local visual helper for Jumpseller admin order pages (orders and orders-v2) only.
* No network calls, credentials, storage or order/theme writes.
* Bundles/packs are unsupported: parent/component rows can be double-counted.
* If the admin markup changes, disable the script and request a review.
*/
(() => {
'use strict';
if (!/^([a-z0-9]+(?:-[a-z0-9]+)*)\.jumpseller\.com$/i.test(location.hostname) || window.top !== window.self) return;
// Supports both order screens: /admin/<locale>/orders/edit/<ID> and /admin/<locale>/orders-v2/edit/<ID>.
if (location.protocol !== 'https:' || !/^\/admin\/(?:[a-z]{2}(?:-[a-z]{2})?\/)?orders(?:-v2)?(?:\/|$)/i.test(location.pathname)) return;
const ROUTE = /^\/admin\/(?:([a-z]{2})(?:-[a-z]{2})?\/)?orders(?:-v2)?\/edit\/(\d+)\/?$/i;
const KEY = '__jumpsellerVisualOrderUnits';
const ID = 'jumpseller-visual-order-units';
window[KEY]?.stop?.();
let scheduled = null;
let stopped = false;
const routeId = () => location.pathname.match(ROUTE)?.[2] || null;
const SPANISH = ['es', 'cl', 'mx', 'ar', 'co', 'pe', 'uy', 'ec', 'bo', 'py', 've', 'cr', 'gt', 'do', 'pa', 'sv', 'hn', 'ni'];
const loc = (location.pathname.match(ROUTE)?.[1] || document.documentElement?.lang || 'en').slice(0, 2).toLowerCase();
const labels = ['pt', 'br'].includes(loc)
? ['Total de unidades', 'linhas de produto', 'Cálculo local; não é guardado. Bundles não suportados.']
: SPANISH.includes(loc)
? ['Total de unidades', 'líneas de producto', 'Cálculo local; no se guarda. Bundles no soportados.']
: ['Total units', 'product lines', 'Local calculation; not saved. Bundles unsupported.'];
function remove() { document.getElementById(ID)?.remove(); }
function directText(element) {
return Array.from(element.childNodes).filter(n => n.nodeType === 3).map(n => n.textContent).join('');
}
function readTable(table) {
let units = 0, lines = 0;
for (const row of table.querySelectorAll('tbody > tr')) {
// Product rows show "$price x qty" in a div; subtotal/shipping/total rows don't.
// The product image is not required: it can be missing and its markup differs between screens.
const price = row.querySelector('td > div.tabular-nums');
if (!price) continue;
const match = directText(price).trim().match(/\s[x×]\s*(\d+)\s*$/u);
if (!match) throw Error('Unrecognized quantity');
const qty = Number(match[1]);
if (!Number.isSafeInteger(qty) || qty < 0 || !Number.isSafeInteger(units + qty)) throw Error('Invalid quantity');
units += qty; lines++;
}
if (!lines) throw Error('No product rows');
return { units, lines };
}
function update() {
scheduled = null;
if (stopped) return;
const id = routeId();
if (!id) { remove(); return; }
// Show a total only when the displayed order matches the current page.
const headings = Array.from(document.querySelectorAll('.text-xl.font-normal'))
.filter(e => new RegExp('#\\s*' + id + '\\s*$').test(e.textContent.trim()));
if (headings.length !== 1) { remove(); return; }
const heading = headings[0];
const root = heading.parentElement;
const tables = Array.from(root.querySelectorAll('table.w-full.border-collapse'))
.filter(t => t.querySelector('tbody > tr > td > div.tabular-nums'));
if (tables.length !== 1) { remove(); return; }
let count;
try { count = readTable(tables[0]); }
catch (_) { remove(); return; } // Fail closed: no misleading partial count.
let badge = document.getElementById(ID);
if (!badge) {
badge = document.createElement('div');
badge.id = ID;
badge.setAttribute('role', 'status');
badge.setAttribute('aria-live', 'polite');
badge.style.cssText = 'margin:8px 0;padding:10px 14px;border:1px solid #d1d5db;border-radius:6px;background:#f8fafc;color:#111827;font-size:15px;font-weight:600';
heading.insertAdjacentElement('afterend', badge);
} else if (badge.previousElementSibling !== heading) {
heading.insertAdjacentElement('afterend', badge);
}
const label = `${labels[0]}: ${count.units}`;
if (badge.textContent !== label) badge.textContent = label;
const title = `#${id} · ${count.lines} ${labels[1]} · ${labels[2]}`;
if (badge.title !== title) badge.title = title;
}
function schedule() {
if (!stopped && scheduled === null) scheduled = setTimeout(update, 80);
}
const observer = new MutationObserver(schedule);
observer.observe(document.body, { childList: true, subtree: true, characterData: true });
const interval = setInterval(schedule, 1000); // URL changes with no DOM event.
const handle = {
stop() {
stopped = true;
observer.disconnect();
clearTimeout(scheduled);
clearInterval(interval);
remove();
if (window[KEY] === handle) delete window[KEY];
}
};
window[KEY] = handle;
update();
})();Si el botón no puede copiar, el código quedará seleccionado: pulsa ⌘C o Ctrl+C. También puedes descargar el script.
Ejemplo: pedido con 10 unidades. Tres bolsas de harina, dos paquetes de polvos de hornear y cinco de mantequilla suman 3 + 2 + 5 = 10.

Para eliminar el script, usa la papelera junto a su nombre. Para quitar Tampermonkey por completo, abre chrome://extensions/ y pulsa Quitar en la extensión; esto afecta también a los demás scripts que hayas instalado.
| Qué ocurre | Qué hacer |
|---|---|
| No aparece el contador | Comprueba que Tampermonkey, el script y Permitir scripts de usuario estén activados. Abre un pedido y recarga. |
| Aparecen dos contadores | Desactiva las copias anteriores y deja una sola habilitada. Después recarga. |
| El total no coincide | Si el pedido contiene packs o bundles, no uses este total para preparar el despacho. Si no los contiene, desactiva el contador y avísanos. |
| Dejó de aparecer después de un cambio en el panel | Desactívalo y envíanos una captura para ayudarte. |
| Chrome indica que tu empresa bloquea la instalación | Pide ayuda a la persona que configura o mantiene ese computador. |
Si no logras completar un paso, envíanos una captura o foto de la pantalla y cuéntanos qué intentabas hacer. Así podremos guiarte para continuar.
Probar gratis por 7 días. No se requiere tarjeta de crédito.