// Network Intelligence client — renders the pooled, anonymised ad results.
(function () {
'use strict';
var $ = function (id) { return document.getElementById(id); };
function esc(s) {
return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
});
}
function n(v) { return Number(v || 0).toLocaleString(); }
function pct(r) { return (Number(r || 0) * 100).toFixed(3) + '%'; }
function gate(msg) {
$('iLoading').style.display = 'none';
$('iGate').style.display = 'block';
$('iGate').innerHTML = msg;
}
function tile(v, label, cls) {
return '
';
}
function section(title, why, group, unitLabel) {
if (!group || !group.rows.length) return '';
var top = group.rows[0].rate || 1;
var rows = group.rows.map(function (r) {
var w = Math.max(2, Math.round((r.rate / top) * 100));
return '| ' + esc(r.label) + ' | ' +
'' + n(r.served) + ' | ' +
'' + n(r.clicks) + ' | ' +
'' + pct(r.rate) + ' | ' +
' |
';
}).join('');
var thin = group.thin
? '' + group.thin + ' more not shown — under the evidence threshold (' +
n(group.thinServed) + ' impressions between them).
'
: '';
return '' + esc(title) + '
' + esc(why) + '
' +
'
| ' + esc(unitLabel) +
' | Served | Clicks | Rate | |
' +
rows + '
' + thin + '
';
}
function render(d) {
var rep = d.report;
$('iLoading').style.display = 'none';
if (!rep || !rep.ready) {
gate('Not enough data yet. ' + esc((rep && rep.reason) || 'This fills in as the team advertises.'));
return;
}
$('iBody').style.display = 'block';
$('iTiles').innerHTML =
tile(n(rep.totals.ads), 'team ads measured', 'cool') +
tile(n(rep.totals.served), 'impressions served') +
tile(n(rep.totals.clicks), 'clicks', 'cool') +
tile(pct(rep.totals.rate), 'network click rate');
$('iReadout').innerHTML = (d.readout || []).map(function (line) {
return '' + esc(line) + '
';
}).join('') || 'Not enough evidence yet to draw conclusions.
';
var html = '';
html += section('Format', 'Text placements against banner placements, across everything the team has run.', rep.format, 'Format');
html += section('Angle', 'Which hook the destination link carried. This is the one worth acting on — it tells you what to lead with everywhere, not just in ads.', rep.angle, 'Angle');
html += section('Banner creative', 'Which designs from the team kit are actually earning their impressions.', rep.creative, 'Design');
html += section('Banner size', 'Placement size, pooled across every design.', rep.size, 'Size');
html += section('Text ad headlines', 'Individual headlines that have run enough to be judged.', rep.headline, 'Headline');
$('iSections').innerHTML = html || 'Nothing has crossed the evidence threshold yet. Keep the ads running.
';
}
async function boot() {
try {
var r = await fetch('/api/public/suite-intel');
if (r.status === 401) { gate('You’re not signed in yet. Open the Suite and connect the wallet that holds your position, then come back.'); return; }
if (r.status === 403) {
var g = await r.json();
gate((g.error || 'Not open for this position yet.') + ' See your Suite.');
return;
}
if (!r.ok) { gate('Could not read the network just now — try again shortly.'); return; }
render(await r.json());
} catch (e) {
gate('Connection hiccup — reload to try again.');
}
}
document.addEventListener('DOMContentLoaded', boot);
})();