← All posts

Windows on the frontend

Output Console: watch the page's console.log inside a tab panel — no DevTools

DevTools console works great — when it's open. Most of the time it isn't. And worse: the DevTools console shows logs from every page you currently use. Hard to fish out "my logs from this specific flow" in the noise avalanche. Output Console (since v2.13.66) is a read-only log viewer in the tab itself — you see logs of this tab, scoped to this domain, always available like other JustZix panels.

Four window types — where Output Console fits

TypeWhat it doesRead/write
CSS paneLive CSS editor, applied via <style>WRITE (CSS → page)
JS paneRun-on-demand JS script (▶ button)WRITE (JS → page)
JS ConsoleREPL with Ctrl+Enter eval + ↑↓ historyWRITE (JS → page) + READ (eval result)
Output ConsoleRead-only log viewerREAD ONLY

The first three types do something to the page. Output Console listens. Every console.log/warn/error/info/debug call from the page (and from other JustZix scripts) lands as a coloured line. Plus — a dedicated window.JUSTZIX.log() channel (since v2.13.73; primary alias since v2.13.76, brand-named with vanishingly small collision risk) that does NOT pipe to native console, only to Output Console — your scripts can log without polluting DevTools.

Architecture — page hook + sink broadcast

Output Console works in two steps:

  1. Page hook (MAIN world) — Injected via chrome.scripting.executeScript({world: 'MAIN', func: hookFn}) (CSP-immune since v2.13.74). Wraps console.log/warn/error/info/debug preserving passthrough to the original (DevTools loses nothing), but every call also posts window.postMessage({source:'jz-output-console', kind:'console', level, text, t}).
  2. Sink broadcast (ISOLATED world) — JustZix content script listens for window.message and broadcasts entries to all currently rendered Output Console panels via the _outputConsoleSinks Map. Each panel appends its line to its own log (per-instance state).

Plus stringifyArg — type-aware argument transformer:

viewMode: [C+J] / [C] / [J] — two channels, one panel

Since v2.13.73 Output Console has a cyclic viewMode button in the header. Three states:

ModeWhat you seeUse case
[C+J] (Both)Everything — page console + JustZix scriptsDefault — most complete view
[C] (Console only)Only page console.*Debug the page, without your own logs
[J] (JustZix only)Only window.JUSTZIX.log/.warn/.error/.info/.debug (or JZ.log if not taken)Your actions, clean, no noise

Implementation: zero JS overhead per line. Each entry gets a jz-output-line-{kind} class, and the mode adds a jz-output-mode-{mode} class on the pane. CSS hide-rules do the rest:

.jz-output-mode-standard .jz-output-line-jz { display: none; }
.jz-output-mode-jz       .jz-output-line-console { display: none; }
/* .jz-output-mode-both shows everything */

Per-level filters + search — power-user features

Under the ⚙ button opens a popover with 5 checkboxes: log / info / warn / error / debug. All checked by default except debug (default off — pages overuse console.debug for spam). Same mechanism as viewMode — class jz-output-hide-{level} + CSS rule, zero JS overhead.

Plus a 🔍 search toggle above the log. Live-filter substring match, case-insensitive. Esc clears. Persisted in sessionStorage per-tab — filters/search survive reload.

// In JS Console type:
for (let i = 0; i < 5; i++) console.log(`User ${i} action`);
for (let i = 0; i < 5; i++) console.warn(`User ${i} warning`);
JUSTZIX.log('My script log');

// Output Console will show 11 lines.
// Toggle [J] → only 1 (JUSTZIX.log).
// Toggle [C] + filter "warn" only → 5 (console.warn).
// Search "User 3" → catches "User 3 action" + "User 3 warning".

Use case 1 — Monitor dataLayer.push (GTM debug)

Classic GTM problem: you want to know what each tag sends to dataLayer. DevTools console = wade through dozens of other logs. Output Console:

// JS rule (auto-runs on site):
const origPush = window.dataLayer.push;
window.dataLayer.push = function(event) {
  JUSTZIX.log('[dataLayer]', JSON.stringify(event));
  return origPush.call(this, event);
};
JUSTZIX.log('dataLayer hook installed.');

Output Console in [J] mode shows only your JUSTZIX.log lines — each GTM tag = one coloured line. Filter "purchase" → only ecommerce. Filter "ga4" → only GA events. No F12, no Tag Assistant, no Network panel.

Use case 2 — Long-running QA flow monitoring

A QA tester logs a 30-minute flow. The DevTools console fills up after 5 minutes (default max ~1000 lines). Output Console:

Use case 3 — Async error tracking

JS pane error overlay (red bar) does NOT catch async errors — setTimeout(() => { throw err }, 100) won't show in the pane. Output Console DOES catch them — because console.error is also invoked by the global error handler:

// JS rule:
window.addEventListener('error', (e) => {
  JUSTZIX.error('[unhandled]', e.message, '@', e.filename + ':' + e.lineno);
});
window.addEventListener('unhandledrejection', (e) => {
  JUSTZIX.error('[promise reject]', e.reason);
});

Output Console in [J] mode + "error only" filter — every global error in a readable list. Handy when an SPA logs 50 errors per minute and you only want yours.

Use case 4 — API response monitor

A page has fetches that don't show up in the view (background sync). Check what the server replies:

// JS rule — proxy fetch:
const origFetch = window.fetch;
window.fetch = async function(...args) {
  const res = await origFetch.apply(this, args);
  const clone = res.clone();
  clone.json().then(data => {
    JUSTZIX.log('[fetch]', args[0], '→', JSON.stringify(data).slice(0, 200));
  }).catch(() => {});
  return res;
};

Output Console shows URL + first 200 chars of JSON response. Search by URL → see only one endpoint. Great for debugging flaky fetches without the F12 Network panel.

CSP-strict pages — why inline script failed (v2.13.74 fix)

Up to v2.13.73 the page hook was injected as a <script> element with textContent. Worked on ~99% of pages — but strict CSP (script-src 'self' without 'unsafe-inline', e.g. GitHub, Stripe checkout, banks) silently blocked execution. appendChild succeeded (DOM mutation OK), but the script didn't execute, no error thrown.

Symptom: window.JUSTZIX.log is not a function + console.log doesn't show up in Output Console. Fix (v2.13.74): the hook moved to chrome.scripting.executeScript({world: 'MAIN', func: hookFn}) — extension privileges trump page CSP. After first install Output Console gets a welcome message (since v2.13.76 it lists active aliases): [JustZix] Output Console hook ready. API: window.JUSTZIX (or JZ / __JUSTZIX__).log/.warn/.error/.info/.debug.

Pitfalls

What's next

Output Console closes out the in-tab mini-IDE — a read-only channel alongside the three write-channels (CSS pane / JS pane / JS Console). Together this is "Chrome DevTools alternative for 80% of cases" — no F12, scoped per domain, with customisable UI. Check also window.JZ helpers for the dedicated logging channel and debug GTM dataLayer.push as a concrete application.

Install JustZix — completely free, no account, no server.

Rate this post

No ratings yet — be the first.

Try it yourself

Install JustZix and paste any snippet from this article. Two minutes from zero to a working rule across all your devices.

Get JustZix

Features · How it works · Examples · Use cases