Loading...
Loading...
Identifies which items (pages, campaigns, products, channels, regions) had the biggest increases or decreases for a key metric between two time periods. Use this skill when someone asks "what's up and what's down," "which campaigns moved the most," "top gainers and losers," "what pages are trending," "show me what changed by channel," or any variation of identifying the biggest movers and decliners for a metric.
npx skill4agent add adobe/skills cja-top-movers-watchlistdescribeCja(DATAVIEW_CONTEXT_GUIDE)findMetricsfindCalculatedMetricsfindDimensionsrunReportsearchDimensionItemsfindDataViewssetDefaultSessionDataViewIddescribeCja("DATAVIEW_CONTEXT_GUIDE")WEEK_START_DOWTIMEZONEfindMetrics(search: "<user's metric name>")"Which metric would you like to track? I can suggest: Sessions, Revenue, Orders based on what your team uses most."
| Dimension | Use Case |
|---|---|
| Marketing Channel | "Which channels moved?" |
| Page Name | "Which pages are trending?" |
| Campaign | "Which campaigns improved?" |
| Product | "Which products gained/lost traction?" |
| Country / Region | "Which markets moved?" |
| Device Type | "Did mobile or desktop shift?" |
| Referring Domain | "Which referrers changed?" |
"Which dimension should I break down by — for example, marketing channel, page, campaign, country, or product?"
findDimensions(search: "<dimension keyword>")"I'll compare this week (Mar 13–19) vs last week (Mar 6–12). Sound right?"
WEEK_START_DOWstartDaterunReportperiodA.startDateperiodB.startDateperiodA.startDate - periodB.endDate == 1 dayrunReport(
dimensionIds: "<dimension id>",
metricIds: "<metric id>",
startDate: "<period A start>T00:00:00",
endDate: "<period A end>T23:59:59",
page: 0,
limit: 50
)runReport(
dimensionIds: "<dimension id>",
metricIds: "<metric id>",
startDate: "<period B start>T00:00:00",
endDate: "<period B end>T23:59:59",
page: 0,
limit: 50
)limit: 50rowsvaluedata[0]findDimensions(searchQuery: "<name>")variables/marketing_channelvariables/marketingchannelvalueAvalueBdeltapctChangestatus/tmp/cja_top_movers_report_<YYYY-MM-DD_HHMMSS>.html8,16077,5841,250,000KM−23.55%−23.6%−23.5%pp+0.40 pp$$1,240,000$45.20kpi-valueData unavailableflat⚠ N/ApriorBoth periods returned no data — validate instrumentationkpi-valueflat⚠ N/ApriorPrior {period_noun}: no data<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Top Movers — {ORG_NAME} — {METRIC_NAME} by {DIMENSION_NAME}</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700;900&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #f5f4f1;
--surface: #ffffff;
--ink: #1a1a1a;
--ink-muted: #6b6b6b;
--border: #e5e2dc;
--header-bg: #0e0e10;
--header-warm: #3a1010;
--accent-red: #c8312f;
--accent-red-bright: #ff6b68;
--accent-red-soft: #fdecea;
--accent-green: #1f7a4d;
--accent-yellow: #d4a017;
}
body { font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
background: var(--bg); color: var(--ink); line-height: 1.5;
-webkit-font-smoothing: antialiased; }
/* === Header === */
header { background: linear-gradient(120deg, var(--header-bg) 0%, #1a0d0d 55%, var(--header-warm) 100%);
color: #fff; padding: 56px 56px 44px; position: relative; overflow: hidden; }
header::after { content: ""; position: absolute; right: -140px; top: -140px;
width: 460px; height: 460px;
background: radial-gradient(circle, rgba(200,49,47,.35) 0%, transparent 70%);
pointer-events: none; }
.header-inner { max-width: 1080px; margin: 0 auto; position: relative; z-index: 1; }
.eyebrow { display: inline-flex; align-items: center; gap: 8px;
padding: 6px 14px; border: 1px solid rgba(255,107,104,.55);
border-radius: 999px; color: var(--accent-red-bright);
font-size: 11px; font-weight: 600; letter-spacing: 1.2px;
text-transform: uppercase; margin-bottom: 24px;
background: rgba(200,49,47,.10); }
.eyebrow::before { content: ""; width: 6px; height: 6px;
background: var(--accent-red-bright); border-radius: 50%; }
header h1 { font-family: "Playfair Display", Georgia, serif;
font-size: 56px; font-weight: 700; letter-spacing: -1.5px;
line-height: 1.05; margin-bottom: 14px; color: #fff; }
header .lede { font-size: 16px; max-width: 560px;
color: rgba(255,255,255,.80); margin-bottom: 24px;
line-height: 1.55; }
header .meta { display: flex; flex-wrap: wrap; gap: 22px;
font-size: 13px; color: rgba(255,255,255,.60); }
header .meta span { display: inline-flex; align-items: center; gap: 6px; }
header .meta .icon { opacity: .8; }
/* === Tabs === */
nav { background: var(--surface); border-bottom: 1px solid var(--border);
padding: 0 56px; display: flex; gap: 28px;
position: sticky; top: 0; z-index: 50; }
nav a { display: block; padding: 16px 0; font-size: 14px;
color: var(--ink); text-decoration: none;
border-bottom: 2px solid transparent;
transition: border-color .15s ease; }
nav a:hover { border-bottom-color: var(--accent-red); }
/* === Container === */
.container { max-width: 1080px; margin: 0 auto; padding: 36px 56px 60px; }
/* === Section label === */
.section-label { font-size: 11px; font-weight: 700;
text-transform: uppercase; letter-spacing: 1.4px;
color: var(--ink-muted); margin-bottom: 14px;
padding-bottom: 10px; border-bottom: 1px solid var(--border); }
/* === KPI grid === */
.kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 14px; margin-bottom: 36px; }
.kpi-tile { background: var(--surface); border-radius: 8px;
padding: 22px 22px 20px;
border-top: 3px solid #b9b6ae;
box-shadow: 0 1px 3px rgba(0,0,0,.05); }
.kpi-tile.down { border-top-color: var(--accent-red); }
.kpi-tile.up { border-top-color: var(--accent-green); }
.kpi-tile.flat { border-top-color: #b9b6ae; }
.kpi-head { display: flex; justify-content: space-between;
align-items: center; margin-bottom: 10px; }
.kpi-label { font-size: 11px; font-weight: 700;
text-transform: uppercase;
color: var(--ink-muted); letter-spacing: 1px; }
.kpi-value { font-family: "Playfair Display", Georgia, serif;
font-weight: 700; font-size: 34px;
line-height: 1; color: var(--ink);
margin-bottom: 12px; }
.pill { display: inline-flex; align-items: center; gap: 4px;
padding: 3px 9px; border-radius: 4px;
font-size: 12px; font-weight: 600; line-height: 1.4; }
.pill.down { background: var(--accent-red-soft); color: var(--accent-red); }
.pill.up { background: #ebf5ef; color: var(--accent-green); }
.pill.flat { background: #f1efea; color: var(--ink-muted); }
.prior { display: block; margin-top: 10px;
font-size: 12px; color: var(--ink-muted); }
/* === Dual risers / fallers panels === */
.two-col { display: grid; grid-template-columns: 1fr 1fr;
gap: 20px; margin-bottom: 22px; }
@media (max-width: 760px) { .two-col { grid-template-columns: 1fr; } }
/* === Sections (collapsible tables) === */
.section { background: var(--surface); border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,.04);
margin-bottom: 22px; overflow: hidden; }
/* Top-border accent on risers/fallers tiles */
.section.risers { border-top: 3px solid var(--accent-green); }
.section.fallers { border-top: 3px solid var(--accent-red); }
.section-header { padding: 18px 28px; border-bottom: 1px solid var(--border);
display: flex; justify-content: space-between;
align-items: center; cursor: pointer; }
.section-header h2 { font-family: "Playfair Display", Georgia, serif;
font-size: 18px; font-weight: 700; }
.section.risers .section-header h2 { color: var(--accent-green); }
.section.fallers .section-header h2 { color: var(--accent-red); }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
thead th { background: #faf8f4; padding: 12px 22px;
text-align: left; font-weight: 600;
text-transform: uppercase; letter-spacing: .6px;
font-size: 11px; color: var(--ink-muted);
border-bottom: 1px solid var(--border); }
tbody td { padding: 12px 22px; border-bottom: 1px solid #f4f1eb; }
tbody tr:last-child td { border-bottom: none; }
.delta-up { color: var(--accent-green); font-weight: 600; }
.delta-down { color: var(--accent-red); font-weight: 600; }
.badge { display: inline-block; padding: 3px 9px; border-radius: 4px;
font-size: 11px; font-weight: 600; }
.badge.green { background: #ebf5ef; color: var(--accent-green); }
.badge.red { background: var(--accent-red-soft); color: var(--accent-red); }
.badge.yellow { background: #fef6e3; color: #b67a08; }
.badge.blue { background: #eef2f8; color: #2c4a7a; }
.badge.grey { background: #f1efea; color: var(--ink-muted); }
.back-top { position: fixed; bottom: 24px; right: 24px;
background: var(--accent-red); color: #fff;
width: 44px; height: 44px; border-radius: 50%;
border: none; font-size: 20px; cursor: pointer;
box-shadow: 0 4px 12px rgba(200,49,47,0.30); }
footer { text-align: center; padding: 32px 24px;
font-size: 12px; color: var(--ink-muted); }
/* === Print === */
@media print {
nav { display: none; position: static; }
header { padding: 36px 32px 28px; }
header h1 { font-size: 42px; }
.section-header { cursor: default; }
.kpi-row { page-break-inside: avoid; }
.kpi-tile, .section {
box-shadow: none; border: 1px solid var(--border);
}
.back-top { display: none; }
}
</style>
</head>
<body>
<header>
<div class="header-inner">
<div class="eyebrow">Top Movers Report</div>
<h1>{ORG_NAME} Top Movers</h1>
<p class="lede">Biggest gainers and decliners for {METRIC_NAME} by {DIMENSION_NAME}, {PERIOD_A_LABEL} vs {PERIOD_B_LABEL}.</p>
<div class="meta">
<span><span class="icon">📅</span> {PERIOD_A_LABEL}</span>
<span><span class="icon">📊</span> {DATA_VIEW}</span>
<span><span class="icon">🕔</span> Prepared {GENERATED_DATE}</span>
</div>
</div>
</header>
<nav>
<a href="#summary">Summary</a>
<a href="#gainers">Gainers</a>
<a href="#decliners">Decliners</a>
<a href="#newdisappeared">New & Gone</a>
<a href="#fulltable">Full Table</a>
</nav>
<div class="container">
<!-- Summary KPI Tiles -->
<div class="section-label">Watchlist Summary</div>
<div id="summary" class="kpi-row">
<div class="kpi-tile flat">
<div class="kpi-head"><div class="kpi-label">Total Items Compared</div></div>
<div class="kpi-value">{TOTAL_ITEMS}</div>
<span class="prior">Dimension values in scope</span>
</div>
<div class="kpi-tile up">
<div class="kpi-head"><div class="kpi-label">Biggest Gain</div></div>
<div class="kpi-value">{TOP_GAINER_VALUE}</div>
<span class="pill up">▲ {TOP_GAINER_NAME}</span>
</div>
<div class="kpi-tile down">
<div class="kpi-head"><div class="kpi-label">Biggest Drop</div></div>
<div class="kpi-value">{TOP_DECLINER_VALUE}</div>
<span class="pill down">▼ {TOP_DECLINER_NAME}</span>
</div>
<div class="kpi-tile flat">
<div class="kpi-head"><div class="kpi-label">New Entries</div></div>
<div class="kpi-value">{NEW_ENTRIES}</div>
<span class="prior">Appeared this period</span>
</div>
<div class="kpi-tile flat">
<div class="kpi-head"><div class="kpi-label">Disappeared</div></div>
<div class="kpi-value">{DISAPPEARED}</div>
<span class="prior">Dropped out this period</span>
</div>
</div>
<!-- Gainers + Decliners side by side -->
<div class="two-col">
<div id="gainers" class="section risers">
<div class="section-header" onclick="toggle('gain-body')">
<h2>▲ Top 10 Gainers</h2>
<span id="gain-body-icon">▾</span>
</div>
<div id="gain-body">
<table>
<thead><tr>
<th>Item</th>
<th>{PERIOD_A_LABEL}</th>
<th>{PERIOD_B_LABEL}</th>
<th>Delta</th>
<th>% Change</th>
</tr></thead>
<tbody>
<!-- Top 10 gainers, sorted by delta desc -->
<!--
<tr>
<td>{ITEM_NAME}</td>
<td>{VALUE_A}</td>
<td>{VALUE_B}</td>
<td class="delta-up">+{DELTA}</td>
<td><span class="badge green">+{PCT}%</span></td>
</tr>
-->
</tbody>
</table>
</div>
</div>
<div id="decliners" class="section fallers">
<div class="section-header" onclick="toggle('dec-body')">
<h2>▼ Top 10 Decliners</h2>
<span id="dec-body-icon">▾</span>
</div>
<div id="dec-body">
<table>
<thead><tr>
<th>Item</th>
<th>{PERIOD_A_LABEL}</th>
<th>{PERIOD_B_LABEL}</th>
<th>Delta</th>
<th>% Change</th>
</tr></thead>
<tbody>
<!-- Top 10 decliners, sorted by delta asc -->
<!--
<tr>
<td>{ITEM_NAME}</td>
<td>{VALUE_A}</td>
<td>{VALUE_B}</td>
<td class="delta-down">−{DELTA}</td>
<td><span class="badge red">−{PCT}%</span></td>
</tr>
-->
</tbody>
</table>
</div>
</div>
</div>
<!-- New Entries & Disappeared -->
<div id="newdisappeared" class="section">
<div class="section-header" onclick="toggle('nd-body')">
<h2>New Entries & Disappeared Items</h2>
<span id="nd-body-icon">▾</span>
</div>
<div id="nd-body">
<table>
<thead><tr>
<th>Item</th>
<th>Status</th>
<th>{PERIOD_A_LABEL}</th>
<th>{PERIOD_B_LABEL}</th>
<th>Notes</th>
</tr></thead>
<tbody>
<!-- New entries: badge blue "New Entry" -->
<!-- Disappeared: badge grey "Disappeared" -->
</tbody>
</table>
</div>
</div>
<!-- Full Table -->
<div id="fulltable" class="section">
<div class="section-header" onclick="toggle('full-body')">
<h2>Full Comparison Table</h2>
<span id="full-body-icon">▾</span>
</div>
<div id="full-body">
<table>
<thead><tr>
<th>Item</th>
<th>{PERIOD_A_LABEL}</th>
<th>{PERIOD_B_LABEL}</th>
<th>Delta</th>
<th>% Change</th>
<th>Status</th>
</tr></thead>
<tbody>
<!-- All items sorted by absolute delta desc -->
</tbody>
</table>
</div>
</div>
</div>
<button class="back-top" onclick="window.scrollTo({top:0,behavior:'smooth'})">↑</button>
<footer>Top Movers — {ORG_NAME} — Generated {GENERATED_DATE}</footer>
<script>
function toggle(id) {
var el = document.getElementById(id);
var ic = document.getElementById(id + '-icon');
if (el.style.display === 'none') { el.style.display=''; ic.textContent='\u25be'; }
else { el.style.display='none'; ic.textContent='\u25b8'; }
}
</script>
</body></html>runReportrunReport/tmp/cja_top_movers_report_<YYYY-MM-DD_HHMMSS>.htmlopen /tmp/cja_top_movers_report_<YYYY-MM-DD_HHMMSS>.html"Which marketing channels moved the most last week vs the week before?"