The core goal of attribution analysis is to answer "why did the metric change." This is not a task that can be completed in a single step—it is adiagnostic process, requiring the integrated use of multiple analytical methods, ultimately converging into a complete attribution conclusion.
Diagnosis follows the logic of "first characterize, then locate, then find the cause": first figure out how much it changed (Step 1), then decompose which business link went wrong (Step 2), then locate the specific dimension and dimension value (Step 3), then correlate external events to find the root cause (Step 4), and finally synthesize all findings to give a conclusion (Step 5).
┌───────────────────────────────────────────────────────────────┐
│ 归因诊断全流程 │
│ │
│ Step 1 确认波动事实 → 变了多少?跟什么比? │
│ ↓ │
│ Step 2 因子拆解 → 哪个业务环节出了问题?(定性) │
│ ↓ │
│ Step 3 维度归因 → 问题环节在哪些维度上集中?(定位) │
│ ↓ ↘ 发现集中点 → 继续下钻到更细维度 │
│ Step 4 外部事件关联 → 天气?节假日?竞对?行业政策?(找因) │
│ ↓ │
│ Step 5 综合诊断结论 → 汇总所有发现,输出归因报告 │
│ │
│ * 并非每次都需走完全部步骤,根据复杂度灵活调整 │
│ * 每步的发现逐步积累,最终在 Step 5 统一收口 │
└───────────────────────────────────────────────────────────────┘
Why do factor decomposition (Step 2) before dimension attribution (Step 3)?
Factor decomposition answers "which link is broken" (traffic? conversion? average order value?), while dimension attribution answers "where is it broken" (which channel? which region?). Only after knowing which link has the problem does dimension attribution have direction—instead of blindly scanning all dimensions against the overall metric, you precisely drill down on the problem factor.
For example: GMV drops 10%. If you directly do dimension attribution, you might find "the Retail channel contributed 70% of the decline," but you still do not know whether Retail has less traffic or worse conversion. If you first do factor decomposition and find "the decline in conversion rate is the main cause," then do dimension attribution on the conversion rate, and you directly locate "the Retail channel's conversion rate dropped 18% period-over-period." Each step narrows the scope, making it much more efficient.
Of course, if the metric has no clear business formula that can be decomposed (Step 2 is not applicable), just skip directly to Step 3 for dimension attribution.
0. Interface Information (Reuse Gateway API)
This Skill reuses the Gateway API system of metric-query. All API call rules are completely consistent with metric-query.
Gateway Search API (Retrieve Metrics and Dimensions)
Search Metrics: GET https://gateway.can.aloudata.com/api/metrics/search?keyword={关键词,可逗号分隔}&pageSize={数量}
Single-Metric Dimensions: GET https://gateway.can.aloudata.com/api/metrics/{metricName}/dimensions?keyword={可选过滤词,支持逗号分隔多关键词}
Batch Metric Dimensions: GET https://gateway.can.aloudata.com/api/metrics/dimensions?metricNames={指标1,指标2}&keyword={可选过滤词,支持逗号分隔多关键词}
Authentication Method: All requests must carry an API Key, passed via the request header X-API-Key (it can also be passed via the ?apikey= query parameter). Requests without a key or with an invalid key will return 401.
Iron Rules for Calls:
- All requests must include the API Key authentication header
-H "X-API-Key: $CAN_API_KEY",$CAN_API_KEYread from environment variables (users need to configure it in~/.openclaw/.envtheCAN_API_KEY=cgk-xxxxxxxx) - Chinese parameters in URLs must be URL-encoded, using
--data-urlencode+-G
Example:
curl -H "X-API-Key: $CAN_API_KEY" "https://gateway.can.aloudata.com/api/metrics/search?pageSize=5" --data-urlencode "keyword=销售额" -G curl -H "X-API-Key: $CAN_API_KEY" "https://gateway.can.aloudata.com/api/metrics/retail_amt/dimensions" # 维度多关键词过滤(逗号分隔,匹配任一即返回,匹配范围包括维度名/展示名/描述/维度值样本) curl -H "X-API-Key: $CAN_API_KEY" "https://gateway.can.aloudata.com/api/metrics/retail_amt/dimensions" --data-urlencode "keyword=渠道,地区,品牌" -G
Metric Query API (Execute Data Query)
Interface: POST https://gateway.can.aloudata.com/api/metrics/query
Use heredoc to pass the JSON body (because timeConstraint contains single quotes, it is forbidden to use -d '...'):
curl -X POST "https://gateway.can.aloudata.com/api/metrics/query" \
-H "X-API-Key: $CAN_API_KEY" \
-H "Content-Type: application/json" \
-d @- <<'EOF'
{JSON请求体}
EOF
The request body format is completely consistent with metric-query, and follows all 9 iron rules and construction specifications of the metric-query Skill (including NOW() usage, metricDefinitions registration, ratio/ranking pitfalls, heredoc parameter passing, etc.).
Step 1: Confirm the Fluctuation Facts
The starting point of attribution is to figure out "exactly how much it changed" and "compared with what." If the baseline is chosen incorrectly, everything afterward is wasted.
1.1 Determine the Comparison Baseline
| User says | Comparison baseline | Implementation method |
|---|---|---|
| "Decreased period-over-period" "compared with last month" | Previous period | __sameperiod__mom__ Series |
| "Decreased year-over-year" "compared with last year" | Same period last year | __sameperiod__yoy__ Series |
| "How far from the target" "missed the target" | Target value | The user needs to provide the target value, or it must be obtained from the system |
| "Why did it drop" (baseline not specified) | Default to period-over-period | Confirm with the user after inferring; if it involves a seasonal industry, year-over-year is recommended |
When the user does not specify a baseline: Do not assume directly; confirm with the user first. For example: "Is the decline you mentioned compared with last month (period-over-period), or compared with the same period last year (year-over-year)? If this industry has obvious seasonality, year-over-year is recommended to exclude seasonal factors."
1.2 Query the overall change amount
After retrieving the metric through Gateway, first check the overall change:
# 搜索指标
curl -H "X-API-Key: $CAN_API_KEY" "https://gateway.can.aloudata.com/api/metrics/search?pageSize=5" --data-urlencode "keyword=销售额" -G
# 查整体环比变化
curl -X POST "https://gateway.can.aloudata.com/api/metrics/query" \
-H "X-API-Key: $CAN_API_KEY" \
-H "Content-Type: application/json" \
-d @- <<'EOF'
{
"metrics": ["retail_amt", "retail_amt__sameperiod__mom__value", "retail_amt__sameperiod__mom__growthvalue", "retail_amt__sameperiod__mom__growth"],
"timeConstraint": "DateTrunc(['metric_time'], \"MONTH\") = DATEADD(DateTrunc(NOW(), \"MONTH\"), -1, \"MONTH\")"
}
EOF
Output:Clear numerical facts—the metric changed from X to Y, a change of Z (change rate W%). Subsequent analysis is all based on this.
1.3 Observe the time trend (optional but recommended)
Check the trend over recent months to determine whether it is an abnormal fluctuation or a sustained trend:
{
"metrics": ["retail_amt"],
"dimensions": ["metric_time__month"],
"timeConstraint": "DateTrunc(['metric_time'], \"MONTH\") >= DATEADD(DateTrunc(NOW(), \"MONTH\"), -6, \"MONTH\") AND DateTrunc(['metric_time'], \"MONTH\") < DateTrunc(NOW(), \"MONTH\")",
"orders": [{"metric_time__month": "asc"}]
}
Step 2: Factor decomposition (qualitative—which business link has the problem)
First figure out "which link is broken"; only then will the subsequent dimensional attribution have a target.
2.1 Determine whether it applies
The prerequisite for factor decomposition is that the metric has a clear business formula.If there is a formula, this step must be done first; if there is not, skip directly to Step 3.
Common decomposition formulas:
| Composite metric | Decomposition formula | Factor meaning |
|---|---|---|
| GMV / Sales | UV × Conversion rate × Average order value | Traffic × Conversion × Price |
| Sales | Number of buyers × Average order value | Number of customers × Price |
| Sales | Number of orders × Item unit price × Attach rate | Order volume × Price × Purchase depth |
| Profit | Revenue - Cost | Revenue side vs Cost side |
If the user does not explicitly provide a formula, infer it based on business common sense and confirm with the user. For example, if the user asks "Why did GMV drop", you can proactively suggest: "Shall I decompose it by UV × Conversion rate × Average order value to see which link has the problem?"
2.2 Obtain factor data
Search for the metrics corresponding to each factor through Gateway, then query the values for the current period and the baseline period:
# 搜索相关因子指标
curl -H "X-API-Key: $CAN_API_KEY" "https://gateway.can.aloudata.com/api/metrics/search?pageSize=10" --data-urlencode "keyword=UV,转化率,客单价,购买人数" -G
{
"metrics": ["visitor_cnt", "buyer_cnt", "AOV",
"visitor_cnt__sameperiod__mom__value",
"buyer_cnt__sameperiod__mom__value",
"AOV__sameperiod__mom__value"],
"timeConstraint": "DateTrunc(['metric_time'], \"MONTH\") = DATEADD(DateTrunc(NOW(), \"MONTH\"), -1, \"MONTH\")"
}
If some factors do not have directly corresponding metrics, calculate them using metricDefinitions + expr:
"metricDefinitions": {
"cvr": { "expr": "[buyer_cnt]/[visitor_cnt]" }
}
2.3 Calculate factor contribution
Multiplicative formula Y = A × B × C:
When the change rates of the factors are small (all < 20%), the approximation method can be used:
ΔY% ≈ ΔA% + ΔB% + ΔC% + 交叉项
A 对 Y 的贡献 ≈ ΔA% / ΔY%
When the change rates are large, use Shapley value decompositionto ensure accuracy:
import itertools, math
def shapley_decomposition(factors_base, factors_current):
"""
factors_base: dict, 如 {"UV": 10000, "CVR": 0.05, "AOV": 200}
factors_current: dict, 如 {"UV": 12000, "CVR": 0.045, "AOV": 210}
返回各因子对总变化量的 Shapley 贡献
"""
factor_names = list(factors_base.keys())
n = len(factor_names)
contributions = {}
for name in factor_names:
shapley_val = 0
others = [fn for fn in factor_names if fn != name]
for subset_size in range(n):
for subset in itertools.combinations(others, subset_size):
subset_set = set(subset)
val_with, val_without = 1, 1
for fn in factor_names:
if fn == name:
val_with *= factors_current[fn]
val_without *= factors_base[fn]
elif fn in subset_set:
val_with *= factors_current[fn]
val_without *= factors_current[fn]
else:
val_with *= factors_base[fn]
val_without *= factors_base[fn]
weight = math.factorial(subset_size) * math.factorial(n - subset_size - 1) / math.factorial(n)
shapley_val += weight * (val_with - val_without)
contributions[name] = shapley_val
return contributions
Additive formula Y = A + B + C: Just look directly at the change amount of each term; no complex decomposition is needed.
Mixed additive + multiplicative: First decompose additively, then apply Shapley separately to the multiplicative terms.
2.4 Waterfall chart visualization
The most intuitive way to present the results of factor decomposition is with a **Waterfall Chart**—the starting point is the baseline value, the endpoint is the current-period value, and each segment in between represents the contribution of one factor. Positive contributions go up (green), negative contributions go down (red), and at a glance you can see which part is dragging things down and which part is holding things up.
Use Python + matplotlib to generate a waterfall chart:
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
matplotlib.rcParams['axes.unicode_minus'] = False
def waterfall_chart(factors, contributions, base_value, current_value, title, save_path):
"""
factors: list, 因子名称列表,如 ["UV", "转化率", "客单价", "交叉项"]
contributions: list, 各因子的贡献量(绝对值变化量,非百分比),如 [+20000, -15000, +5000, -500]
base_value: float, 基准期总值
current_value: float, 当期总值
title: str, 图表标题
save_path: str, 保存路径
"""
labels = ["基准值"] + factors + ["当期值"]
values = [base_value] + contributions + [current_value]
# 计算瀑布图的底部位置和柱子高度
bottoms = [0]
heights = [base_value]
running = base_value
for c in contributions:
if c >= 0:
bottoms.append(running)
heights.append(c)
else:
bottoms.append(running + c)
heights.append(abs(c))
running += c
bottoms.append(0)
heights.append(current_value)
colors = ["#4472C4"] # 基准值:蓝色
for c in contributions:
colors.append("#2E7D32" if c >= 0 else "#C62828") # 正向绿,负向红
colors.append("#4472C4") # 当期值:蓝色
fig, ax = plt.subplots(figsize=(10, 6))
bars = ax.bar(labels, heights, bottom=bottoms, color=colors, width=0.6, edgecolor='white')
# 在柱子上标注数值
for i, (bar, val) in enumerate(zip(bars, values)):
if i == 0 or i == len(values) - 1:
text = f"{val:,.0f}"
y_pos = bar.get_y() + bar.get_height() + base_value * 0.01
else:
text = f"{'+' if val >= 0 else ''}{val:,.0f}"
y_pos = bar.get_y() + bar.get_height() + base_value * 0.01
ax.text(bar.get_x() + bar.get_width()/2, y_pos, text,
ha='center', va='bottom', fontsize=10, fontweight='bold')
# 添加连接线
for i in range(len(bars) - 1):
x1 = bars[i].get_x() + bars[i].get_width()
x2 = bars[i+1].get_x()
y = bars[i].get_y() + bars[i].get_height() if i == 0 else bottoms[i] + heights[i]
ax.plot([x1, x2], [y, y], color='gray', linewidth=0.8, linestyle='--')
ax.set_title(title, fontsize=14, fontweight='bold', pad=15)
ax.set_ylabel("指标值")
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.tight_layout()
plt.savefig(save_path, dpi=150, bbox_inches='tight')
plt.close()
Use in the report: embed the generated waterfall chart image into the diagnostic report (if it is an HTML report, embed it directly; if it is a Markdown report, reference the image path).
2.5 Output of factor decomposition
After this step is completed, you should be able to answer:
- "In which business stage did the change mainly occur?" (e.g., the decline in conversion rate was the main cause, contributing 65%)
- "How much did each factor contribute?" (intuitively presented by the waterfall chart)
This conclusion directly determines the direction of Step 3—the dimensional attribution in Step 3 should prioritize the factor with the largest contribution, rather than blindly scanning the overall metric.
Step 3: Dimensional attribution (locate—on which dimensions the problem is concentrated)
Now that you know which stage has the problem (Step 2), you need to locate "where the problem in this stage is concentrated."
If Step 2 identified the main factor (such as conversion rate), this step shouldtarget that factorto perform dimensional attribution and drill-down. If Step 2 is not applicable (the metric has no decomposition formula), then perform dimensional attribution directly on the overall metric.
3.1 Horizontal scan: multi-dimensional parallel analysis
Select attribution dimensions
Query the available dimensions of the metric (or main factor metric):
curl -H "X-API-Key: $CAN_API_KEY" "https://gateway.can.aloudata.com/api/metrics/{metricName}/dimensions"
From the available dimensions, select 3-5 dimensions that are most likely to affect fluctuations in business terms:
- User specified → prioritize the user's
- Not specified → prioritize business entity dimensions such as channel, region, product line, brand, etc.
- Avoid dimensions with overly fine granularity (such as SKU), unless requested by the user
Query the change amount for each dimension
{
"metrics": ["{指标}", "{指标}__sameperiod__mom__value", "{指标}__sameperiod__mom__growthvalue"],
"dimensions": ["{维度名}"],
"timeConstraint": "DateTrunc(['metric_time'], \"MONTH\") = DATEADD(DateTrunc(NOW(), \"MONTH\"), -1, \"MONTH\")",
"orders": [{"{指标}__sameperiod__mom__growthvalue": "asc"}]
}
Note: here {指标} should be the metric corresponding to the main factor found in Step 2 (such as buyer_cnt and visitor_cnt corresponding to conversion rate), and not necessarily the overall metric the user initially asked about.
Calculate contribution
维度值变化量 = 当期值 - 基准值
总变化量 = Σ 所有维度值的变化量(应等于 Step 1 的总体变化量,作为校验)
贡献度 = 维度值变化量 / |总变化量| × 100%
Use the denominatorabsolute value, positive contribution = driving growth, negative contribution = dragging down the decline.
Highlight the main contributing factors
After calculating the contribution, mark the main contributors according to the following rules so that key findings are visible at a glance:
| Contribution (absolute value) | Mark | Meaning |
|---|---|---|
| ≥ 30% | 🔴 Main contributor | Must be analyzed in depth as a drill-down target |
| 10% ~ 30% | 🟡 Secondary contributor | Worth attention; drill-down optional |
| < 10% | No mark | Small impact; generally no drill-down needed |
Evaluate the explanatory power of each dimension
- Concentration: did a few dimension values contribute most of the change? (e.g., a certain channel contributed 70% of the decline) → strong dimensional explanatory power
- Business interpretability: does the data finding make sense in business terms?
If the explanatory power of all dimensions is very weak (changes are evenly distributed, with no dimension values marked with 🔴), it may not be a structural change, but rather an overall factor at work → look for explanations in Step 4 external events.
3.2 Vertical drill-down: go deeper layer by layer
When a certain dimension value contributes a significant amount of change, ask "within this dimension value, which sub-dimension caused it?"
Determine the drill-down path
Dimensions from coarse to fine:
一级渠道 → 二级渠道 → 地区 → 城市
品类大类 → 品类中类 → 品牌
Execute drill-down
For the dimension values with the largest contribution (top 1-2), add filters to constrain them, then perform attribution on the next-level dimensions:
{
"metrics": ["{指标}", "{指标}__sameperiod__mom__value", "{指标}__sameperiod__mom__growthvalue"],
"dimensions": ["{下一层维度}"],
"filters": ["[{上层维度}]= \"{贡献最大的值}\""],
"timeConstraint": "..."
}
Drill-down termination conditions
- A sufficiently specific root cause has been found
- Changes are evenly distributed at the current level, with no concentration point
- The number of levels reaches 3-4
- The data volume is too small to be statistically meaningful
3.3 Output of dimension attribution
After this step, you should be able to answer:
- "Which dimension is the change in the problem factor mainly concentrated in?"
- "Specifically, which dimension value contributes the most?"
- "What is the root cause path after drill-down?"
Combined with the factor decomposition in Step 2, you should now have a complete causal chain, for example:
"GMV fell 10% → the main cause is a decline in conversion rate (contributing 65%) → the conversion rate decline is concentrated in the Retail channel (contributing 70%) → further drill-down reveals the largest decline in East China"
Step 4: External event correlation (find the cause—why is this happening)
Internal data tells you "what changed" and "where it changed," but the root cause is often external—weather, holidays, competitors, policies, etc. This step seeks external explanations for the earlier data findings.
4.1 Determine whether external correlation is needed
The following signals indicate that external factors need attention:
- Dimension attribution has no obvious concentration point: changes are evenly distributed, indicating an "overall" factor
- Changes do not match seasonal patterns: for example, air conditioner sales instead decline in summer
- The magnitude of change is abnormally large: exceeding normal fluctuations, usually with an external trigger
- The user proactively mentions external factors
In fact, even if dimension attribution has an obvious concentration point, it is recommended to search for external events as supporting evidence—"the Retail channel conversion rate declined" is a fact, but "why did the Retail conversion rate decline" may require external information to answer.
4.2 External event search
Based on the business domain and the fluctuation time period, search for relevant external events:
| External factor | Search keyword examples | Typical impact pattern |
|---|---|---|
| Weather/natural disasters | "{region} {month} weather extreme heavy rain high temperature" | Affects offline foot traffic and logistics delivery |
| Holidays/major promotions | "{month} holidays promotional festivals Double 11 618" | Pre-promotion buildup - surge - decline cycle around major promotions |
| Competitor actions | "{industry} competitors promotions price cuts new product launches" | Price wars lead to changes in conversion rate/average order value |
| Industry policies | "{industry} policies regulations supervision new rules" | Compliance costs rise, categories are restricted |
| Macroeconomic | "Consumer Confidence Index {Month} CPI Employment" | Overall changes in consumer willingness |
| Platform Rules | "{Platform Name} Algorithm Traffic Rules Search Ranking" | Changes in traffic allocation cause UV fluctuations |
Use the WebSearch tool to search (if available), or prompt the user to confirm known external events.
4.3 Event and Data Alignment
After finding candidate external events, verify their consistency with the data findings:
Time alignment: Does the time the event occurred match the time the metric changed? (The event should precede or coincide with the change.)
Spatial alignment: For regional events (such as heavy rain in a certain area), is the data for that area indeed abnormal? Use the dimensional attribution results from Step 3 to verify.
Direction alignment: Is the expected direction of the event's impact consistent with the actual change? (Heavy rain → offline foot traffic decreases → offline channels indeed declined.)
Magnitude alignment: Is the scope of the event's impact sufficient to explain the magnitude of the change?
4.4 Outputs of External Associations
- "What external events may have affected the metrics?"
- "Are these external events consistent with the data findings?"
- "Which are certain conclusions supported by data, and which are inferences based on external information?"
Step 5: Comprehensive Diagnostic Conclusions
Summarize all findings into a complete attribution report.
5.1 Report Structure
# 指标波动归因诊断报告
## 1. 波动概况
- **分析指标**:{指标名称}
- **分析时段**:{当期} vs {基准期}
- **当期值**:{值} | **基准值**:{值}
- **变化量**:{±变化量}({变化率}%)
- **趋势判断**:{突发异常 / 持续趋势 / 季节性波动}
## 2. 归因发现
### 2.1 因子拆解(哪个环节出了问题)
**瀑布图**:(嵌入 Step 2 生成的瀑布图,直观展示各因子正负贡献)

| 因子 | 当期值 | 基准值 | 因子变化率 | 对总量贡献 | 贡献度 |
|------|-------|-------|----------|----------|-------|
| **{因子A}** 🔴 | xxx | xxx | {±X.X%} | {±xxx} | **{XX%}** |
| {因子B} | xxx | xxx | {±X.X%} | {±xxx} | {XX%} |
| {因子C} | xxx | xxx | {±X.X%} | {±xxx} | {XX%} |
→ 主要问题环节:**{因子A}**(贡献了 XX% 的变化)
### 2.2 维度归因(问题集中在哪里)
针对主因子 **{因子A}** 做维度归因,定位问题集中在哪里。
**Highlight 规则**:贡献度 ≥ 30% 的维度值标记为 🔴 主要贡献者,10%-30% 标记为 🟡 次要贡献者。
| 维度 | 维度值 | 当期值 | 基准值 | 变化量 | 贡献度 | 标记 |
|-----|-------|-------|-------|-------|-------|------|
| {维度1} | {值A} | xxx | xxx | {±xxx} | **{XX%}** | 🔴 主因 |
| {维度1} | {值B} | xxx | xxx | {±xxx} | {XX%} | 🟡 次因 |
| {维度1} | {值C} | xxx | xxx | {±xxx} | {XX%} | |
**下钻路径**:🔴 {维度1值A} → 🔴 {维度2值X} → 🔴 {维度3值Y},贡献了总变化的 XX%
### 2.3 外部事件(为什么会这样)
| 事件 | 发生时间 | 影响范围 | 与数据的一致性 |
|-----|---------|---------|-------------|
| {事件1} | {时间} | {范围} | {高/中/低} |
## 3. 归因结论
综合以上分析,本次{指标名}的{变化方向}主要由以下因素导致:
1. **主因**:{一句话说清核心原因,串联因子→维度→外部事件}
- 数据支撑:{因子拆解和维度归因的关键数字}
- 外部佐证:{相关外部事件,如有}
2. **次因**:{第二重要的原因}
- 数据支撑:...
3. **其他因素**:{其他较小的影响因素}
## 4. 建议关注
- {基于归因结论给出的可操作建议}
- {需要持续监控的指标或维度}
5.2 Report Writing Principles
Conclusion-driven, data-supported: State the conclusion first, then provide the evidence. Readers care most about "why did it change" and "what should be done," not the analysis process.
Distinguish certainty: What the data directly proves ("the data shows that the decline in conversion rate contributed 65%") vs. inferences based on external information ("speculated to be related to competitor promotions").
Provide a complete causal chain: The most valuable attribution is not a single-point finding, but a chain linking Step 2→3→4:
"Sales fell 12% period-over-period, mainly because the conversion rate dropped 18% (contributing 65% of the total decline). The conversion rate decline was concentrated in the Retail channel (contributing 70%), and further drilling down found that East China had the largest decline (contributing 45%). This is speculated to be related to large-scale competitor promotional activities in the region during the same period."
General Specifications
Query Construction
All API queries must comply with all the ironclad rules and specifications of metric-query, with special attention to:
- Relative time must use
NOW(), hard-coded dates are prohibited metricDefinitionsEach key inmetricsmust be registered in thecurlUse a heredoc to pass the JSON body- Dimension values must strictly follow the original wording returned by the Gateway
Query Efficiency
Attribution analysis usually requires multiple queries. To reduce the number of queries:
- Use the
__sameperiod__series to obtain the current value, baseline value, and change amount in one go - Keep the timeConstraint consistent across multiple queries
- During dimensional attribution in Step 3, you can query multiple dimensions at the same time (placing them in separate queries)
Numerical Calculation
- Use theabsolute valueof the total change as the denominator for contribution, to avoid sign confusion caused by negative numbers
- The sum of the contribution of each dimension value should be approximately 100%, as a check (a deviation > 5% requires investigation)
- When decomposing factors, if the baseline value is 0 → note "no data in the baseline period, change rate cannot be calculated"
- Percentage-type metrics (such as conversion rate): clearly distinguish "percentage point change" and "change rate"
Common error patterns
❌ Starting analysis without confirming the baseline: The user said "the metric dropped" but did not say compared to what. First confirm the baseline.
❌ Skipping factor decomposition and directly scanning dimensions: If the metric has a business formula, decomposition must come first so that subsequent dimension attribution has direction. Otherwise you only know "Retail declined" but not which part of Retail had the problem.
❌ Only doing factor decomposition without dimension attribution: Knowing "the conversion rate decline is the main cause" is not enough; you must further locate which channel and which region had the conversion rate drop.
❌ Only looking at internal data without relating it to external events: The data tells you "where it changed", but "why it changed" often requires external information to answer. Especially when the dimension attribution results are evenly distributed, you should look even harder for external factors.
❌ Using signed values in the contribution denominator: When the total change is negative the sign flips. The denominator must use absolute values.
❌ Ignoring cross terms in factor decomposition: When factor change rates are > 10%, the approximation decomposition error cannot be ignored. Use Shapley decomposition or at least report the cross terms.
❌ Drilling down too deep, insufficient data volume: Each drill-down narrows the data scope, and when the data volume is too small the conclusions are unreliable.
❌ Confusing "percentage point change" and "change rate": Conversion rate drops from 5% to 4% → percentage point change -1pp, change rate -20%.
❌ Treating data correlation as causation: Dimension attribution discovers "correlation"; causal inference requires combining external events and business logic.
Analysis quality checklist
- ✅ Comparison baseline has been confirmed and is reasonable
- ✅ Overall change has been quantified (with specific numbers and percentages)
- ✅ Factor decomposition (if applicable): the sum of each factor's contribution equals the total change
- ✅ Factor decomposition (if applicable): cross terms have been checked
- ✅ Dimension attribution: conducted around the main factor (rather than the total metric)
- ✅ Dimension attribution: the sum of the contribution of each dimension value is approximately 100%
- ✅ Dimension attribution: drill-down was performed on the dimension value with the largest contribution (at least one level attempted)
- ✅ External events: external events for the relevant time period were at least searched
- ✅ External events: consistency alignment with the data findings was performed
- ✅ The comprehensive conclusion connects the complete chain of factors → dimensions → external events
- ✅ The conclusion distinguishes certain findings from speculative judgments
- ✅ Actionable business recommendations were given
- ✅ Percentage conventions are consistent (percentage points vs change rate)
- ✅ All queries comply with the metric-query iron rules
- ✅ Factor decomposition generated a waterfall chart (if applicable)
- ✅ In dimension attribution, the main contributors (≥30%) have been marked highlight with 🔴