cja-executive-briefing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseExecutive Briefing (Customer Journey Analytics)
高管简报(CJA)
Produce a polished, leadership-ready performance document. Executives do not
read data tables — they read narratives that answer "are we growing?", "what
changed?", and "what do we do about it?"
This skill converts CJA data into a briefing that a VP or C-suite leader can
read in under 3 minutes, with supporting data available for those who want to
dig deeper.
Tone: business impact, not technical metrics. Write "Revenue grew 12% driven by
a strong Paid Search week" not "metrics/revenue increased by 0.12 per metrics/sessions."
生成一份经过润色、适合领导层查看的绩效文档。高管不会阅读数据表——他们阅读的是能够回答“我们是否在增长?”、“发生了什么变化?”以及“我们该怎么做?”的叙事内容。
此技能将CJA数据转换为一份副总裁或高管层可以在3分钟内读完的简报,同时为想要深入了解的人提供支持数据。
语气:聚焦业务影响,而非技术指标。应撰写“付费搜索表现强劲,推动收入增长12%”,而非“metrics/revenue较metrics/sessions增长0.12”。
CJA MCP Tools Used
使用的CJA MCP工具
- — understand the business context of the data view
describeCja(DATAVIEW_CONTEXT_GUIDE) - — identify the north-star and supporting KPIs
listComponentUsage - — resolve user-specified or discovered metric IDs
findMetrics - — include custom business KPIs
findCalculatedMetrics - — pull KPI values for current and comparison period
runReport - — identify top driver dimension values
searchDimensionItems
- — 了解数据视图的业务背景
describeCja(DATAVIEW_CONTEXT_GUIDE) - — 识别核心指标和辅助KPI
listComponentUsage - — 解析用户指定或发现的指标ID
findMetrics - — 包含自定义业务KPI
findCalculatedMetrics - — 获取当前周期和对比周期的KPI数值
runReport - — 识别顶级驱动维度值
searchDimensionItems
Phase 0 — Setup
阶段0 — 设置
- Call to list available data views.
findDataViews - If the user hasn't specified a data view, present the list and ask which to use.
- Call with the chosen ID.
setDefaultSessionDataViewId - Confirm the reporting period (default: last 7 days) and the audience for the briefing (executive, board, team lead).
- 调用列出可用的数据视图。
findDataViews - 如果用户未指定数据视图,列出选项并询问使用哪一个。
- 使用选定的ID调用。
setDefaultSessionDataViewId - 确认报告周期(默认:过去7天)和简报受众(高管、董事会、团队负责人)。
Phase 1 — Establish Context
阶段1 — 建立背景
1.1 Load data view context
1.1 加载数据视图背景
Call to understand:
describeCja("DATAVIEW_CONTEXT_GUIDE")- What business the data view represents (e-commerce, media, SaaS, etc.)
- The primary conversion event and revenue metric
- Calendar conventions and timezone. Record these values — they are
inputs to every date computation in 1.2:
- — day of week each week starts on (Sunday, Monday, …). Default: Monday (ISO 8601) if the context guide doesn't specify.
WEEK_START_DOW - — month the fiscal year begins. Default: January (calendar year) if the context guide doesn't specify.
FISCAL_YEAR_START_MONTH - — for example,
TIMEZONE.America/Los_Angeles - — one of
CALENDAR_SOURCE(values came from"context guide"),describeCja(the context guide didn't expose them and you used the defaults above), or"default fallback"(the user explicitly specified them)."user override"
This context determines what counts as the "north-star metric" and what
language to use in the narrative (e.g., "subscribers" vs "customers" vs "users").
调用以了解:
describeCja("DATAVIEW_CONTEXT_GUIDE")- 数据视图代表的业务类型(电商、媒体、SaaS等)
- 主要转化事件和收入指标
- 日历规则及时区。记录这些值——它们是1.2中所有日期计算的输入:
- — 每周开始的星期几(周日、周一……)。如果背景指南未指定,默认值为周一(ISO 8601标准)。
WEEK_START_DOW - — 财年开始的月份。如果背景指南未指定,默认值为1月(日历年)。
FISCAL_YEAR_START_MONTH - — 例如,
TIMEZONE。America/Los_Angeles - — 取值为
CALENDAR_SOURCE(值来自"context guide")、describeCja(背景指南未提供,使用上述默认值)或"default fallback"(用户明确指定)。"user override"
此背景决定了什么是“核心指标”,以及叙事中应使用的语言(例如,“订阅用户”vs“客户”vs“用户”)。
1.2 Determine reporting period
1.2 确定报告周期
Infer the period type from the user's request. Do not stop to ask — proceed immediately.
从用户请求中推断周期类型。无需停顿询问——直接执行。
The principle
原则
Two runs of this skill on the same data view, period type, and prompt MUST
produce identical and date ranges. Determinism comes
from (a) reading calendar conventions from 1.1 instead of improvising, and
(b) applying the alignment rule for the period type without taste calls.
currentcomparison针对同一数据视图、周期类型和提示运行两次此技能,必须生成完全相同的和日期范围。确定性来自:(a) 从1.1读取日历规则而非自行设定;(b) 严格应用周期类型的对齐规则,不做主观判断。
当前对比Period type → alignment rule
周期类型 → 对齐规则
Pick exactly one period type from the user's request:
| User request | | Current period | Comparison period |
|---|---|---|---|
| "last week" / unspecified | | Most recent full week ending before today, aligned to | The week immediately before, same alignment |
| "this month" / "MTD" | | 1st of current month → today | 1st of prior month → same day-of-month as today |
| "last month" | | Prior full calendar month (1st → last day) | The month before that |
| "this quarter" / "QTD" | | Start of current fiscal quarter → today; fiscal quarters derived from | Same days into the prior fiscal quarter |
| "last quarter" / "Q[N]" | | Prior full fiscal quarter | The fiscal quarter before that |
| Custom date range | | Use as specified | Equal-length window ending the day before |
从用户请求中选择恰好一种周期类型:
| 用户请求 | | 当前周期 | 对比周期 |
|---|---|---|---|
| “上周”/未指定 | | 截至今日之前最近的完整一周,与 | 紧接在前的同一对齐规则的一周 |
| “本月”/“MTD” | | 当月1日 → 今日 | 上月1日 → 与今日同日 |
| “上月” | | 上一完整日历月(1日 → 月末) | 上上月 |
| “本季度”/“QTD” | | 当前财季开始 → 今日;财季由 | 上一财季同期天数 |
| “上季度”/“Q[N]” | | 上一完整财季 | 上上个财季 |
| 自定义日期范围 | | 使用指定范围 | 与当前范围长度相同,结束于 |
Universal invariants (must hold for every period type)
通用不变规则(适用于所有周期类型)
Before calling , verify all six:
runReportcurrent.startDate < current.endDatecomparison.startDate < comparison.endDate- (no overlap)
comparison.endDate < current.startDate - The day after equals
comparison.endDate(contiguous)current.startDate - and
currenthave the same length in dayscomparison - The alignment rule for is satisfied:
PERIOD_TYPE- : both
weeklys fall onstartDateWEEK_START_DOW - : both
monthlys fall on the 1st of a monthstartDate - : both
month-to-dates fall on the 1st; bothstartDates have the same day-of-monthendDate - : both
quarterlys fall on the first day of a fiscal quarterstartDate - : both
quarter-to-dates fall on a fiscal quarter start; bothstartDates are the same number of days into the quarterendDate - : lengths match; contiguity holds
custom
If ANY invariant fails, recompute the dates. Never paper over a mismatch by editing the footer.
调用前,验证以下所有规则:
runReportcurrent.startDate < current.endDatecomparison.startDate < comparison.endDate- (无重叠)
comparison.endDate < current.startDate - 次日等于
comparison.endDate(连续)current.startDate - 和
current的天数完全相同comparison - 满足的对齐规则:
PERIOD_TYPE- :两个
weekly均为startDateWEEK_START_DOW - :两个
monthly均为当月1日startDate - :两个
month-to-date均为当月1日;两个startDate的日期相同endDate - :两个
quarterly均为财季首日startDate - :两个
quarter-to-date均为财季开始日;两个startDate处于财季的同一天数endDate - :长度匹配;保持连续
custom
如果任何规则不满足,重新计算日期。绝对不要通过编辑页脚来掩盖不匹配问题。
Worked examples — today is Tuesday, May 26, 2026
示例——今日为2026年5月26日(周二)
These examples assume the data view's context guide returns and . Numbers change for other calendars — that's exactly the point.
WEEK_START_DOW = SundayFISCAL_YEAR_START_MONTH = January| User request | | Current | Comparison |
|---|---|---|---|
| "last week" | | May 17 (Sun) – May 23 (Sat) | May 10 (Sun) – May 16 (Sat) |
| "this month" / "MTD" | | May 1 – May 26 | Apr 1 – Apr 26 |
| "last month" | | Apr 1 – Apr 30 | Mar 1 – Mar 31 |
| "this quarter" / "QTD" | | Apr 1 – May 26 | Jan 1 – Feb 24 |
| "last quarter" | | Jan 1 – Mar 31 | Oct 1 – Dec 31 (2025) |
| Custom: "May 15–22" | | May 15 – May 22 (8 days) | May 7 – May 14 (8 days) |
If instead, the weekly row becomes vs . The other rows are unchanged.
WEEK_START_DOW = MondayMay 18 (Mon) – May 24 (Sun)May 11 (Mon) – May 17 (Sun)这些示例假设数据视图的背景指南返回和。日历规则不同时数值会变化——这正是本部分的意义所在。
WEEK_START_DOW = SundayFISCAL_YEAR_START_MONTH = January| 用户请求 | | 当前周期 | 对比周期 |
|---|---|---|---|
| “上周” | | 5月17日(周日)– 5月23日(周六) | 5月10日(周日)– 5月16日(周六) |
| “本月”/“MTD” | | 5月1日 – 5月26日 | 4月1日 – 4月26日 |
| “上月” | | 4月1日 – 4月30日 | 3月1日 – 3月31日 |
| “本季度”/“QTD” | | 4月1日 – 5月26日 | 1月1日 – 2月24日 |
| “上季度” | | 1月1日 – 3月31日 | 2025年10月1日 – 12月31日 |
| 自定义:“5月15–22日” | | 5月15日 – 5月22日(8天) | 5月7日 – 5月14日(8天) |
如果,则每周行变为 vs 。其他行保持不变。
WEEK_START_DOW = Monday5月18日(周一)– 5月24日(周日)5月11日(周一)– 5月17日(周日)A common AI failure mode
AI常见错误模式
The AI may "know" from training data that weeks are Mon–Sun (ISO 8601) or that
quarters are Q1=Jan–Mar (calendar). Silently overriding the context guide with
those defaults is exactly the determinism bug this section exists to prevent.
The footer's methodology line MUST accurately describe the dates you computed
— if footer says "weeks start Sunday" but is a Monday,
that's a bug to fix in the dates, not in the footer.
current.startDateAI可能从训练数据中“知道”周是周一至周日(ISO 8601)或季度是Q1=1月–3月(日历季度)。但用这些默认值悄悄覆盖背景指南正是本部分要防止的确定性漏洞。页脚的方法说明行必须准确描述你计算的日期——如果页脚写“周从周日开始”但是周一,那需要修正日期,而非编辑页脚。
current.startDate1.3 Audience assumption
1.3 受众假设
Default to internal leadership (VPs, directors, senior managers). This means:
- Include specific dimension values (e.g., channel names) in the narrative
- Surface both positive and negative findings with equal directness
- The reader understands your business — no need to define basic terms
If the user says "external," "board," or "investors," shift to higher-level
business outcomes, remove any internal channel naming that could be sensitive,
and lead with the most positive finding.
默认受众为内部领导层(副总裁、总监、高级经理)。这意味着:
- 在叙事中包含具体维度值(例如,渠道名称)
- 同等直接地呈现正面和负面发现
- 读者了解你的业务——无需定义基本术语
如果用户提到“外部”、“董事会”或“投资者”,则转向更高层次的业务成果,移除任何可能敏感的内部渠道名称,并以最正面的发现开头。
Phase 2 — Discover North-Star Metrics
阶段2 — 发现核心指标
Pull the most-used metrics to identify what the org actually tracks as success.
Run both calls in parallel — this is fast and sets the foundation for every KPI
decision downstream:
listComponentUsage(componentType: "metric")
listComponentUsage(componentType: "calculatedMetric")提取使用最频繁的指标,以确定组织实际追踪的成功标准。并行运行两个调用——这会更快,且为后续所有KPI决策奠定基础:
listComponentUsage(componentType: "metric")
listComponentUsage(componentType: "calculatedMetric")Deterministic selection — do not improvise
确定性选择——不要自行发挥
The KPI set MUST be reproducible across runs for the same data view. Two runs of
this skill on the same period must produce the same metric values, which requires
selecting the same metric IDs every time. Follow this algorithm exactly:
- Combine both results into a single ranked list.
listComponentUsage - Sort by descending. Break ties by metric ID alphabetically (stable secondary sort).
usageCount - Resolve metric IDs to human-readable display names with or
describeMetric.describeCalculatedMetric - Take the top 6 metric IDs from this sorted list. That is the KPI set.
Do NOT cherry-pick by metric "type" (volume vs conversion vs revenue) and do NOT
swap in an alternative metric because its name reads better in a narrative.
Different runs picking vs produce wildly
different numbers and break trust in the briefing.
metrics/ordersmetrics/orders_1_1针对同一数据视图,KPI集合必须在多次运行中可重现。针对同一周期运行两次此技能必须生成相同的指标数值,这要求每次都选择相同的指标ID。严格遵循以下算法:
- 将两个的结果合并为一个排名列表。
listComponentUsage - 按降序排序。若出现并列,按指标ID字母顺序排序(稳定的二级排序)。
usageCount - 使用或
describeMetric将指标ID解析为易读的显示名称。describeCalculatedMetric - 从此排序后的列表中选取前6个指标ID。这就是KPI集合。
不要根据指标“类型”(数量vs转化vs收入)挑选,也不要因为某个指标名称在叙事中读起来更好就替换成其他指标。不同运行中选择 vs 会产生截然不同的数值,破坏对简报的信任。
metrics/ordersmetrics/orders_1_1When the user specifies metrics explicitly
用户明确指定指标时
If the user names metrics in their request ("give me a briefing on revenue,
orders, and conversion rate"), resolve each name to one specific metric ID
via . If multiple metrics match a name (e.g., "Orders" matches both
and a calculated metric called "Orders"), pick the one with
the highest and document the choice.
findMetricsmetrics/ordersusageCount如果用户在请求中指定了指标(“给我一份关于收入、订单和转化率的简报”),通过将每个名称解析为一个具体的指标ID。如果多个指标匹配一个名称(例如,“Orders”同时匹配和一个名为“Orders”的计算指标),选择最高的那个,并记录此选择。
findMetricsmetrics/ordersusageCountAlways disclose the metric IDs used
始终披露使用的指标ID
Include a small "Metrics included" line in the briefing artifact's footer
listing the resolved metric IDs (e.g., , ,
). This makes the report auditable and lets the user
confirm a re-run is using the same metrics.
metrics/orders_1_1metrics/visitsmetrics/page_viewsCap at 6 KPIs. More is noise.
在简报文档的页脚中添加一行小型的“包含指标”说明,列出解析后的指标ID(例如,, , )。这使报告可审计,并让用户确认重新运行时使用的是相同指标。
metrics/orders_1_1metrics/visitsmetrics/page_views最多保留6个KPI。过多会造成干扰。
Phase 3 — Pull KPI Data
阶段3 — 获取KPI数据
Run both reports in parallel — current period and comparison period — with all
selected metrics. Use a date dimension (e.g., ) so the
report returns summary totals across the full period. The
array in the response contains the aggregate values you need.
variables/daterangedaysummaryData.totalsrunReport(
startDate: "<current period start>T00:00:00",
endDate: "<current period end>T00:00:00",
dimensionIds: "variables/daterangeday",
metricIds: "metrics/visits,metrics/orders_1_1,metrics/revenue_1,...",
page: 0,
limit: 1
)
runReport(
startDate: "<prior period start>T00:00:00",
endDate: "<prior period end>T00:00:00",
dimensionIds: "variables/daterangeday",
metricIds: "metrics/visits,metrics/orders_1_1,metrics/revenue_1,...",
page: 0,
limit: 1
)Read from each response — the values correspond to
the metrics in the order they were specified in .
summaryData.filteredTotalsmetricIdsCompute for each KPI:
- value
current - value
prior - = current − prior
delta - = delta / prior × 100
pctChange - : up / down / flat (using ±3% threshold)
direction - : positive if higher is better, negative if lower is better
polarity - : green (favorable), red (unfavorable), yellow (mixed/flat)
signal
并行运行当前周期和对比周期的两份报告,包含所有选定指标。使用日期维度(例如,),以便报告返回整个周期的汇总总数。响应中的数组包含所需的汇总值。
variables/daterangedaysummaryData.totalsrunReport(
startDate: "<current period start>T00:00:00",
endDate: "<current period end>T00:00:00",
dimensionIds: "variables/daterangeday",
metricIds: "metrics/visits,metrics/orders_1_1,metrics/revenue_1,...",
page: 0,
limit: 1
)
runReport(
startDate: "<prior period start>T00:00:00",
endDate: "<prior period end>T00:00:00",
dimensionIds: "variables/daterangeday",
metricIds: "metrics/visits,metrics/orders_1_1,metrics/revenue_1,...",
page: 0,
limit: 1
)从每个响应中读取——这些值与中指定的指标顺序对应。
summaryData.filteredTotalsmetricIds为每个KPI计算:
- 值
current - 值
prior - = 当前值 − 对比值
delta - = delta / 对比值 × 100
pctChange - : 上升/下降/持平(使用±3%阈值)
direction - : 正向(值越高越好),负向(值越低越好)
polarity - : 绿色(有利)、红色(不利)、黄色(混合/持平)
signal
Phase 4 — Find What Drove the Movement
阶段4 — 找出变化驱动因素
For the 2 KPIs with the largest absolute % change, find the top driver:
Run current and prior period breakdown reports in parallel:
runReport(
startDate: "<current period start>",
endDate: "<current period end>",
dimensionIds: "variables/marketing_channel",
metricIds: "<top-moved metric id>",
limit: 5
)
runReport(
startDate: "<prior period start>",
endDate: "<prior period end>",
dimensionIds: "variables/marketing_channel",
metricIds: "<top-moved metric id>",
limit: 5
)Compare channel-level values between periods to find which dimension value's delta
most closely mirrors the overall metric change. This becomes the "driven by" phrase
in the narrative.
Only run dimension breakdowns for the 2 most-moved metrics (by absolute % change).
This constraint exists because: (a) more breakdowns add latency without adding
executive value, and (b) the two largest movers are what leadership will ask about
first. The remaining KPIs get context from the narrative without needing attribution.
If returns no useful breakdown (e.g., only one
channel has data), try or
as alternative driver dimensions.
variables/marketing_channelvariables/page_typevariables/product_category针对绝对百分比变化最大的2个KPI,找出顶级驱动因素:
并行运行当前周期和对比周期的细分报告:
runReport(
startDate: "<current period start>",
endDate: "<current period end>",
dimensionIds: "variables/marketing_channel",
metricIds: "<top-moved metric id>",
limit: 5
)
runReport(
startDate: "<prior period start>",
endDate: "<prior period end>",
dimensionIds: "variables/marketing_channel",
metricIds: "<top-moved metric id>",
limit: 5
)比较周期间的渠道级数值,找出哪个维度值的变化最接近整体指标的变化。这将成为叙事中的“由……驱动”表述。
仅针对变化最大的2个指标(按绝对百分比变化)运行维度细分。此限制的原因是:(a) 更多细分会增加延迟,且不会为高管带来额外价值;(b) 变化最大的两个指标是领导层首先会询问的。其余KPI从叙事中获取背景信息,无需归因。
如果未返回有用的细分(例如,只有一个渠道有数据),尝试使用或作为替代驱动维度。
variables/marketing_channelvariables/page_typevariables/product_categoryPhase 5 — Write the Executive Narrative
阶段5 — 撰写高管叙事内容
Compose 3–5 bullet points as the narrative. Each bullet follows this structure:
[Signal emoji] [Metric]: [Value] ([+/-pctChange%] vs [prior period]) — [Plain-English context]
Guidelines:
- Open with the most important finding (highest-impact metric, positive or negative)
- Use business language: "revenue," "customers," "conversions" — not "metrics/revenue"
- Name the driver when known: "driven by Paid Search," "led by Product Page improvements"
- Include one forward-looking note if relevant: "This trend should be monitored..."
- For negative trends: be direct but not alarming. Suggest investigation, not panic.
Examples of well-written bullets:
- "Revenue reached $1.24M last week, up 8.2% vs prior week — Paid Search drove the majority of the gain (+$82K)."
- "Conversion Rate declined to 2.1% (−0.4pp), primarily on mobile. Desktop conversion remained stable at 3.4%."
- "Sessions were flat at 540K (+1.1%) — organic and direct traffic offset a reduction in email campaign sends."
- "Bounce Rate ticked up to 43% (+2pp). No single driver identified; worth monitoring through end of month."
撰写3–5个要点作为叙事内容。每个要点遵循以下结构:
[信号表情] [指标]: [数值] ([+/-pctChange%] vs [对比周期]) — [通俗易懂的背景说明]
指南:
- 以最重要的发现开头(影响最大的指标,无论正负)
- 使用业务语言:“收入”、“客户”、“转化”——而非“metrics/revenue”
- 已知驱动因素时注明:“由付费搜索驱动”、“受产品页面优化推动”
- 如有相关,添加一条前瞻性说明:“此趋势应持续监控……”
- 对于负面趋势:直接但不要恐慌。建议调查,而非惊慌。
撰写良好的要点示例:
- “上周收入达124万美元,较上周增长8.2%——付费搜索贡献了大部分增长(+8.2万美元)。”
- “转化率降至2.1%(−0.4个百分点),主要来自移动端。桌面端转化率稳定在3.4%。”
- “会话数持平于54万(+1.1%)——自然流量和直接流量抵消了电子邮件营销发送量的减少。”
- “跳出率小幅上升至43%(+2个百分点)。未发现明确驱动因素;值得监控至月末。”
Phase 6 — Generate the HTML Briefing Document
阶段6 — 生成HTML简报文档
Generate the briefing inline. Write to .
This document should look polished enough to share with leadership — not a
developer tool output.
/tmp/cja_executive_briefing_<YYYY-MM-DD_HHMMSS>.html在线生成简报。写入。此文档应足够精美,可分享给领导层——而非开发者工具输出。
/tmp/cja_executive_briefing_<YYYY-MM-DD_HHMMSS>.htmlRendering rules — apply consistently across runs
渲染规则——所有运行保持一致
Two runs of this skill on the same data view + period must render identically
(modulo the generation timestamp). The rules below pin the formatting choices
that the AI would otherwise drift on.
针对同一数据视图+周期运行两次此技能,必须生成完全相同的渲染结果(生成时间戳除外)。以下规则固定了AI原本可能随意变动的格式选择。
Number formatting
数字格式
- KPI values (the big number in each tile) — use full digits with
thousands separators (,
8,160,77,584). Do NOT use SI suffixes like1,250,000orK, even for large values. Executives want exact numbers, not abbreviations.M - Percent change (in pills and narrative bullets) — always one decimal
place, rounded half-away-from-zero. For example, displays as
−23.55%, never−23.6%. Compute on full-precision values; round only at display time.−23.5% - Percentage-point change (for already-percentage metrics like Conversion
Rate or Bounce Rate) — same rounding, suffix . Example:
pp.+0.40 pp - Currency — prefix with thousands separators and no decimals for values ≥ $100 (
$); cents only when value < $100 ($1,240,000).$45.20
- KPI数值(每个卡片中的大数字)——使用带千位分隔符的完整数字(,
8,160,77,584)。绝对不要使用1,250,000或K等SI后缀,即使数值很大。高管想要精确数字,而非缩写。M - 百分比变化(在标签和叙事要点中)——始终保留一位小数,采用四舍五入到最近整数的规则。例如,显示为
−23.55%,而非−23.6%。基于全精度数值计算;仅在显示时四舍五入。−23.5% - 百分点变化(针对本身就是百分比的指标,如转化率或跳出率)——四舍五入规则相同,后缀为。示例:
pp。+0.40 pp - 货币——以开头,带千位分隔符;数值≥100美元时不保留小数(
$);数值<100美元时保留分($1,240,000)。$45.20
Null / missing data handling
空值/缺失数据处理
A KPI tile must reflect what the data view actually returned. The AI must
not silently substitute a different metric or hide a tile to make the
briefing look cleaner.
- Both periods return 0 or NULL for a metric in the resolved set: render
the tile with =
kpi-value, pill classData unavailable, pill textflat, and⚠ N/Atext =prior. The tile stays in the grid; do not omit it.Both periods returned no data — validate instrumentation - One period returns valid data, the other 0 / NULL: render the tile with
the valid value as , pill class
kpi-value, pill textflat, and⚠ N/Atext =prior.Prior {period_noun}: no data - Never substitute a derived metric (e.g., adding "Conversion Rate" because Revenue came back $0). The visible KPI set MUST match the resolved metric IDs disclosed in the footer.
- If a Revenue / monetary metric is unavailable, surface a above the KPI grid explaining the gap. Do not invent a value.
.callout.note
KPI卡片必须如实反映数据视图返回的内容。AI绝对不要悄悄替换为其他指标或隐藏卡片,以使简报看起来更整洁。
- 解析后的指标集合中,某个指标在两个周期均返回0或NULL:渲染卡片时,设为
kpi-value,标签类为数据不可用,标签文本为flat,⚠ N/A文本为prior。卡片保留在网格中;不要省略。两个周期均无数据——请验证数据采集 - 一个周期返回有效数据,另一个周期返回0/NULL:渲染卡片时,设为有效数值,标签类为
kpi-value,标签文本为flat,⚠ N/A文本为prior。对比{周期名词}: 无数据 - 绝对不要替换为衍生指标(例如,因收入返回0而添加“转化率”)。可见的KPI集合必须与页脚中披露的解析指标ID一致。
- 如果收入/货币指标不可用,在KPI网格上方添加说明此缺口。不要编造数值。
.callout.note
Template variables
模板变量
Populate every in the HTML template below using these rules.
The briefing belongs to the customer — never substitute Adobe, CJA, or any
vendor language into customer-visible fields.
{PLACEHOLDER}- — The customer's business or brand name, derived from the data view context loaded in Phase 1.1. Strip technical/environment suffixes like
{ORG_NAME},— Prod,- Demo,Stage,Test. If the data view name has no clean brand label, fall back to the data view display name with suffixes removed. Do not invent a name and do not substitute a vendor name.MCP - — One of
{PERIOD_TYPE},Weekly,Monthly, orQuarterly(default), chosen from the period inferred in Phase 1.2.Performance - — Use exactly this pattern, with no vendor names:
{LEDE_SENTENCE}Example:Leadership readout for the {period type lowercase} of {PERIOD_LABEL} compared to {COMPARISON_LABEL}.Leadership readout for the week of May 12–18, 2026 compared to May 5–11, 2026. - — Data view display name as returned by
{DATA_VIEW}. Suffixes are acceptable here — this row is the technical identifier line, not the title.findDataViews - /
{PERIOD_LABEL}— Human-readable date ranges, e.g.,{COMPARISON_LABEL}.May 12–18, 2026 - — Today's date in the same human format, e.g.,
{GENERATED_DATE}.May 23, 2026 - /
{METRIC_LABEL}/{FORMATTED_VALUE}/{PCT_CHANGE}— Per-KPI values from Phase 3. Use the metric's customer-facing display name, not its internal ID.{PRIOR_VALUE}
使用以下规则填充HTML模板中的所有。简报属于客户——绝对不要将Adobe、CJA或任何供应商语言替换到客户可见字段中。
{PLACEHOLDER}- — 客户的业务或品牌名称,取自阶段1.1加载的数据视图背景。移除技术/环境后缀,如
{ORG_NAME}、— Prod、- Demo、Stage、Test。如果数据视图名称没有清晰的品牌标签,回退到移除后缀的数据视图显示名称。不要编造名称,也不要替换为供应商名称。MCP - — 取值为
{PERIOD_TYPE}、Weekly、Monthly或Quarterly(默认),从阶段1.2推断的周期中选择。Performance - — 严格使用此格式,不包含供应商名称:
{LEDE_SENTENCE}。示例:领导层汇报:{小写周期类型} {PERIOD_LABEL} 对比 {COMPARISON_LABEL}。领导层汇报:2026年5月12–18日 对比 5月5–11日 - —
{DATA_VIEW}返回的数据视图显示名称。此处可保留后缀——此行是技术标识行,而非标题。findDataViews - /
{PERIOD_LABEL}— 易读的日期范围,例如{COMPARISON_LABEL}。2026年5月12–18日 - — 今日日期,采用相同的易读格式,例如
{GENERATED_DATE}。2026年5月23日 - /
{METRIC_LABEL}/{FORMATTED_VALUE}/{PCT_CHANGE}— 来自阶段3的每个KPI数值。使用指标的客户可见显示名称,而非内部ID。{PRIOR_VALUE}
HTML Template
HTML模板
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Performance Briefing — {ORG_NAME} — {PERIOD}</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; }
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; }
/* === Callout === */
.callout { background: var(--accent-red-soft);
border-left: 4px solid var(--accent-red);
border-radius: 6px;
padding: 18px 22px; margin-bottom: 32px;
display: flex; gap: 14px; align-items: flex-start; }
.callout .warn-icon { font-size: 22px; line-height: 1; flex-shrink: 0;
color: var(--accent-yellow); }
.callout-title { font-weight: 700; color: var(--accent-red);
margin-bottom: 4px; font-size: 15px; }
.callout-body { font-size: 14px; color: #4a2222; line-height: 1.55; }
.callout.note { background: #fdf6e7; border-left-color: var(--accent-yellow); }
.callout.note .callout-title { color: #8a5a08; }
.callout.note .callout-body { color: #5a4108; }
/* === 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: 38px;
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); }
/* === Narrative === */
.narrative-card { background: var(--surface); border-radius: 8px;
padding: 32px 36px;
box-shadow: 0 1px 3px rgba(0,0,0,.04);
margin-bottom: 24px; }
.narrative-card h2 { font-family: "Playfair Display", Georgia, serif;
font-size: 24px; font-weight: 700;
margin-bottom: 18px;
padding-bottom: 12px;
border-bottom: 1px solid var(--border); }
.bullet-list { list-style: none; }
.bullet-list li { padding: 14px 0; font-size: 15px; line-height: 1.65;
border-bottom: 1px solid #f1eeea; }
.bullet-list li:last-child { border-bottom: none; }
.bullet-list .signal { margin-right: 6px; }
.bullet-list .metric-highlight { font-weight: 700; }
.bullet-list .driver { color: var(--accent-red); font-style: italic; }
/* === 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; }
.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; }
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; }
.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.grey { background: #f1efea; color: var(--ink-muted); }
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, .narrative-card, .section {
box-shadow: none; border: 1px solid var(--border);
}
}
</style>
</head>
<body>
<header>
<div class="header-inner">
<div class="eyebrow">{PERIOD_TYPE} Performance Briefing</div>
<h1>{ORG_NAME} Performance</h1>
<p class="lede">{LEDE_SENTENCE}</p>
<div class="meta">
<span><span class="icon">📅</span> {PERIOD_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="#highlights">Highlights</a>
<a href="#narrative">Summary</a>
<a href="#data">KPI Detail</a>
<a href="#drivers">Drivers</a>
</nav>
<div class="container">
<!--
Optional critical callout. Include ONLY when the data has a
notable finding worth raising above the fold (e.g., a metric
moved >25% week-over-week, or data is missing/anomalous).
Use the .note variant (yellow) for non-critical context;
omit entirely if there is nothing noteworthy.
-->
<!--
<div class="callout">
<span class="warn-icon">⚠</span>
<div>
<div class="callout-title">Critical: {ONE_LINE_HEADLINE}</div>
<div class="callout-body">{ONE_PARAGRAPH_CONTEXT}</div>
</div>
</div>
-->
<!-- Headline KPI Tiles -->
<div class="section-label">Key Performance Indicators</div>
<div id="highlights" class="kpi-row">
<!-- Repeat for each KPI (4-6 tiles), class = up | down | flat:
<div class="kpi-tile down">
<div class="kpi-head">
<div class="kpi-label">{METRIC_LABEL}</div>
</div>
<div class="kpi-value">{FORMATTED_VALUE}</div>
<span class="pill down">▼ {PCT_CHANGE}%</span>
<span class="prior">Prior week: {PRIOR_VALUE}</span>
</div>
-->
</div>
<!-- Executive Narrative -->
<div id="narrative" class="narrative-card">
<h2>Executive Summary</h2>
<ul class="bullet-list">
<!--
<li>
<span class="signal">{EMOJI}</span>
<span class="metric-highlight">{Metric}:</span> {value} ({delta} vs prior period) —
<span class="driver">{plain-English driver or context}</span>
</li>
-->
</ul>
</div>
<!-- Supporting Data Table -->
<div id="data" class="section">
<div class="section-header" onclick="toggle('data-body')">
<h2>Full KPI Detail</h2>
<span id="data-body-icon">▾</span>
</div>
<div id="data-body">
<table>
<thead><tr>
<th>Metric</th>
<th>{PERIOD_LABEL}</th>
<th>{COMPARISON_LABEL}</th>
<th>Change</th>
<th>% Change</th>
<th>Signal</th>
</tr></thead>
<tbody>
<!-- One row per KPI with delta and badge -->
</tbody>
</table>
</div>
</div>
<!-- Key Drivers -->
<div id="drivers" class="section">
<div class="section-header" onclick="toggle('drv-body')">
<h2>What Drove the Movement</h2>
<span id="drv-body-icon">▾</span>
</div>
<div id="drv-body">
<table>
<thead><tr>
<th>Metric</th>
<th>Top Driver</th>
<th>Value This Period</th>
<th>Value Prior Period</th>
<th>Contribution</th>
</tr></thead>
<tbody>
<!-- One row per metric with top dimension driver -->
</tbody>
</table>
</div>
</div>
</div>
<footer>
Performance Briefing — {ORG_NAME} — Generated {GENERATED_DATE}<br>
<span style="opacity:.7">
Methodology: {PERIOD_TYPE}
· current {CURRENT_START_ISO}–{CURRENT_END_ISO}
· comparison {COMPARISON_START_ISO}–{COMPARISON_END_ISO}
· week starts {WEEK_START_DOW}
· fiscal year starts {FISCAL_YEAR_START_MONTH}
· tz {TIMEZONE}
· calendar source: {CALENDAR_SOURCE}
· metrics: {METRIC_IDS_CSV}
</span>
</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>html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Performance Briefing — {ORG_NAME} — {PERIOD}</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; }
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; }
/* === Callout === */
.callout { background: var(--accent-red-soft);
border-left: 4px solid var(--accent-red);
border-radius: 6px;
padding: 18px 22px; margin-bottom: 32px;
display: flex; gap: 14px; align-items: flex-start; }
.callout .warn-icon { font-size: 22px; line-height: 1; flex-shrink: 0;
color: var(--accent-yellow); }
.callout-title { font-weight: 700; color: var(--accent-red);
margin-bottom: 4px; font-size: 15px; }
.callout-body { font-size: 14px; color: #4a2222; line-height: 1.55; }
.callout.note { background: #fdf6e7; border-left-color: var(--accent-yellow); }
.callout.note .callout-title { color: #8a5a08; }
.callout.note .callout-body { color: #5a4108; }
/* === 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: 38px;
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); }
/* === Narrative === */
.narrative-card { background: var(--surface); border-radius: 8px;
padding: 32px 36px;
box-shadow: 0 1px 3px rgba(0,0,0,.04);
margin-bottom: 24px; }
.narrative-card h2 { font-family: "Playfair Display", Georgia, serif;
font-size: 24px; font-weight: 700;
margin-bottom: 18px;
padding-bottom: 12px;
border-bottom: 1px solid var(--border); }
.bullet-list { list-style: none; }
.bullet-list li { padding: 14px 0; font-size: 15px; line-height: 1.65;
border-bottom: 1px solid #f1eeea; }
.bullet-list li:last-child { border-bottom: none; }
.bullet-list .signal { margin-right: 6px; }
.bullet-list .metric-highlight { font-weight: 700; }
.bullet-list .driver { color: var(--accent-red); font-style: italic; }
/* === 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; }
.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; }
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; }
.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.grey { background: #f1efea; color: var(--ink-muted); }
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, .narrative-card, .section {
box-shadow: none; border: 1px solid var(--border);
}
}
</style>
</head>
<body>
<header>
<div class="header-inner">
<div class="eyebrow">{PERIOD_TYPE} Performance Briefing</div>
<h1>{ORG_NAME} Performance</h1>
<p class="lede">{LEDE_SENTENCE}</p>
<div class="meta">
<span><span class="icon">📅</span> {PERIOD_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="#highlights">Highlights</a>
<a href="#narrative">Summary</a>
<a href="#data">KPI Detail</a>
<a href="#drivers">Drivers</a>
</nav>
<div class="container">
<!--
Optional critical callout. Include ONLY when the data has a
notable finding worth raising above the fold (e.g., a metric
moved >25% week-over-week, or data is missing/anomalous).
Use the .note variant (yellow) for non-critical context;
omit entirely if there is nothing noteworthy.
-->
<!--
<div class="callout">
<span class="warn-icon">⚠</span>
<div>
<div class="callout-title">Critical: {ONE_LINE_HEADLINE}</div>
<div class="callout-body">{ONE_PARAGRAPH_CONTEXT}</div>
</div>
</div>
-->
<!-- Headline KPI Tiles -->
<div class="section-label">Key Performance Indicators</div>
<div id="highlights" class="kpi-row">
<!-- Repeat for each KPI (4-6 tiles), class = up | down | flat:
<div class="kpi-tile down">
<div class="kpi-head">
<div class="kpi-label">{METRIC_LABEL}</div>
</div>
<div class="kpi-value">{FORMATTED_VALUE}</div>
<span class="pill down">▼ {PCT_CHANGE}%</span>
<span class="prior">Prior week: {PRIOR_VALUE}</span>
</div>
-->
</div>
<!-- Executive Narrative -->
<div id="narrative" class="narrative-card">
<h2>Executive Summary</h2>
<ul class="bullet-list">
<!--
<li>
<span class="signal">{EMOJI}</span>
<span class="metric-highlight">{Metric}:</span> {value} ({delta} vs prior period) —
<span class="driver">{plain-English driver or context}</span>
</li>
-->
</ul>
</div>
<!-- Supporting Data Table -->
<div id="data" class="section">
<div class="section-header" onclick="toggle('data-body')">
<h2>Full KPI Detail</h2>
<span id="data-body-icon">▾</span>
</div>
<div id="data-body">
<table>
<thead><tr>
<th>Metric</th>
<th>{PERIOD_LABEL}</th>
<th>{COMPARISON_LABEL}</th>
<th>Change</th>
<th>% Change</th>
<th>Signal</th>
</tr></thead>
<tbody>
<!-- One row per KPI with delta and badge -->
</tbody>
</table>
</div>
</div>
<!-- Key Drivers -->
<div id="drivers" class="section">
<div class="section-header" onclick="toggle('drv-body')">
<h2>What Drove the Movement</h2>
<span id="drv-body-icon">▾</span>
</div>
<div id="drv-body">
<table>
<thead><tr>
<th>Metric</th>
<th>Top Driver</th>
<th>Value This Period</th>
<th>Value Prior Period</th>
<th>Contribution</th>
</tr></thead>
<tbody>
<!-- One row per metric with top dimension driver -->
</tbody>
</table>
</div>
</div>
</div>
<footer>
Performance Briefing — {ORG_NAME} — Generated {GENERATED_DATE}<br>
<span style="opacity:.7">
Methodology: {PERIOD_TYPE}
· current {CURRENT_START_ISO}–{CURRENT_END_ISO}
· comparison {COMPARISON_START_ISO}–{COMPARISON_END_ISO}
· week starts {WEEK_START_DOW}
· fiscal year starts {FISCAL_YEAR_START_MONTH}
· tz {TIMEZONE}
· calendar source: {CALENDAR_SOURCE}
· metrics: {METRIC_IDS_CSV}
</span>
</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>Phase 7 — Deliver the Briefing
阶段7 — 交付简报
- Write the HTML to
/tmp/cja_executive_briefing_<YYYY-MM-DD_HHMMSS>.html - Open with
open /tmp/cja_executive_briefing_<YYYY-MM-DD_HHMMSS>.html - Output the narrative bullets directly in chat so the user can copy-paste them into an email or slide deck immediately — the HTML is the "appendix."
In-chat format:
Performance Briefing — Last Week vs Prior Week
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📈 Revenue: $1.24M (+8.2%) — Paid Search drove the majority of the gain.
📉 Conversion Rate: 2.1% (−0.4pp) — Mobile checkout declined; desktop stable.
➡ Sessions: 540K (+1.1%) — Essentially flat; organic offset email decline.
📈 Orders: 11,340 (+6.7%) — Product page improvements appear to be contributing.
⚠️ Bounce Rate: 43% (+2pp) — No clear driver identified; monitor next week.
Full briefing document: /tmp/cja_executive_briefing_<YYYY-MM-DD_HHMMSS>.html- 将HTML写入
/tmp/cja_executive_briefing_<YYYY-MM-DD_HHMMSS>.html - 使用打开文件
open /tmp/cja_executive_briefing_<YYYY-MM-DD_HHMMSS>.html - 在聊天中直接输出叙事要点,以便用户可以立即复制粘贴到电子邮件或幻灯片中——HTML是“附录”。
聊天内格式:
绩效简报 — 上周 vs 上上周
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📈 收入:124万美元(+8.2%)——付费搜索贡献了大部分增长。
📉 转化率:2.1%(−0.4个百分点)——移动端结账转化率下降;桌面端稳定。
➡ 会话数:54万(+1.1%)——基本持平;自然流量抵消了电子邮件营销的下滑。
📈 订单数:11340笔(+6.7%)——产品页面优化似乎起到了作用。
⚠️ 跳出率:43%(+2个百分点)——未发现明确驱动因素;下周继续监控。
完整简报文档:/tmp/cja_executive_briefing_<YYYY-MM-DD_HHMMSS>.htmlTone and Style Rules
语气和风格规则
- Write outcomes, not activities. "Revenue grew" not "metrics/revenue increased."
- Name the driver concisely. "Paid Search drove the gain" not "Marketing Channel = Paid Search had a higher value in period A vs period B."
- One sentence per bullet. Two at most. Executives skim.
- Lead with the most important finding. Do not build to a conclusion.
- Be direct about bad news. "Conversion Rate declined" not "Conversion Rate saw some movement in a downward direction."
- Quantify everything. Every bullet must have a number. Opinions without data are not executive communication.
- Avoid jargon. No "dimensions," "metrics IDs," "data view context," or "MCP tool calls" in the output.
- 撰写成果,而非活动。 写“收入增长”而非“metrics/revenue有所增加”。
- 简洁说明驱动因素。 写“付费搜索推动增长”而非“营销渠道=付费搜索在周期A中的数值高于周期B”。
- 每个要点一句话。 最多两句。高管会快速浏览。
- 以最重要的发现开头。 不要逐步引出结论。
- 直接说明坏消息。 写“转化率下降”而非“转化率出现了一些下滑趋势”。
- 所有内容量化。 每个要点必须包含数字。没有数据的观点不是高管沟通内容。
- 避免行话。 叙事中不要出现“维度”、“指标ID”、“数据视图背景”或“MCP工具调用”等术语。
Important Guardrails
重要约束
- Read-only reporting. Never modify metrics, segments, or projects.
- Use business language, not technical IDs. Replace dimension IDs (e.g., ) with their display names. Never expose internal IDs in the narrative.
variables/evar5 - Always state the date range prominently. Executives need context — "last week" is ambiguous; write "April 7–13, 2026."
- Don't invent data. If a KPI is unavailable or the report returns no data, say so explicitly rather than omitting or estimating.
- Cap the briefing to the most impactful findings. 3–5 KPI tiles + 2–3 driver bullets is ideal; more than 8 KPIs dilutes the message.
- Note significant context. Mention known external factors (campaigns, holidays, product releases) that affect the metrics when relevant.
- Validate numbers before presenting. Cross-check KPI values against a second call if they look anomalous.
runReport - Customer-branded output, never vendor-branded. The briefing is the customer's document about their own business. Never use "Adobe", "CJA", "Customer Journey Analytics", or any vendor/product name in the customer-visible briefing (title, lede, narrative, tables, footer, or in-chat output). The red/black header palette is the only Adobe-branded element allowed in the artifact.
- 只读报告。 永远不要修改指标、细分或项目。
- 使用业务语言,而非技术ID。 将维度ID(例如,)替换为其显示名称。叙事中永远不要暴露内部ID。
variables/evar5 - 始终突出显示日期范围。 高管需要背景信息——“上周”是模糊的;应写“2026年4月7–13日”。
- 不要编造数据。 如果KPI不可用或报告无数据,明确说明,而非省略或估算。
- 简报聚焦最具影响力的发现。 3–5个KPI卡片 + 2–3个驱动因素要点是理想的;超过8个KPI会削弱信息传递效果。
- 注明重要背景。 相关时提及影响指标的已知外部因素(营销活动、节假日、产品发布)。
- 呈现前验证数值。 如果数值看起来异常,通过第二次调用交叉检查KPI数值。
runReport - 输出客户品牌化内容,而非供应商品牌化。 简报是客户关于自身业务的文档。客户可见的简报(标题、导语、叙事、表格、页脚或聊天内输出)中永远不要使用“Adobe”、“CJA”、“Customer Journey Analytics”或任何供应商/产品名称。红色/黑色标题配色是允许保留的唯一Adobe品牌元素。
Example Interaction
示例交互
"Write me an executive briefing for last week's performance."
- Setup: Confirm data view with . User selects their primary data view. Call
findDataViews.setDefaultSessionDataViewId - Scope: Confirm reporting period (last 7 days, April 7–13, 2026) and key KPIs (Revenue, Conversion Rate, Sessions, AOV).
- Data pull: Run for each KPI: current week vs. prior week and vs. same week last year.
runReport - Narrative draft: Compose 3–4 executive bullets in business language: "Revenue of $2.4M was up 8% week-over-week, driven by a 15% increase in Paid Search conversions. Conversion Rate dipped 2 points to 3.1%, consistent with the product page redesign rollout on April 9."
- HTML report: Generate the print-ready HTML briefing with KPI tiles, narrative section, and driver table. Open the file. Present a 2-sentence summary to the user and offer to adjust tone or scope.
“为我撰写一份上周绩效的高管简报。”
- 设置: 使用确认数据视图。用户选择其主数据视图。调用
findDataViews。setDefaultSessionDataViewId - 范围: 确认报告周期(过去7天,2026年4月7–13日)和关键KPI(收入、转化率、会话数、平均订单价值)。
- 数据获取: 为每个KPI运行:本周 vs 上周,以及 vs 去年同期。
runReport - 叙事草稿: 用业务语言撰写3–4个高管要点:“收入达240万美元,较上周增长8%,主要来自付费搜索转化增长15%。转化率下降2个百分点至3.1%,与4月9日推出的产品页面重新设计一致。”
- HTML报告: 生成可打印的HTML简报,包含KPI卡片、叙事部分和驱动因素表格。打开文件。向用户呈现2句话的摘要,并提供调整语气或范围的选项。