P paper2skillsPlaybook
AI 路线图 →

KOL ROI 因果归因(网红/达人投放效果的真实增量测算)

Skill-KOL-ROI-Causal-Attribution · 15-营销投放分析

causalexperimentrecommendation广告与投放推荐与搜索WF-B 广告优化WF-D 选品扫描WF-G Listing内容优化WF-L 内容营销增长
年化 ROI30 万/月
实现难度⭐⭐⭐☆☆
业务视角
适用角色CMO / 营销负责人 · 广告优化师 · CEO
适用平台Amazon + TikTok + Meta + KOL 四渠道 · Prime Day / Black Friday 预算前置
什么情况下用同时跑 Amazon 广告/TikTok/网红投放/邮件,不知道整体预算怎么分配最高效;网红投放花了大钱但不知道带来多少真实 GMV
成功是什么样的建立全渠道营销归因模型(MMM),每个渠道真实 ROI 可量化,大促前做预算优化模拟
业务痛点
多渠道预算分配靠感觉网红带货效果不知道怎么量化渠道之间互相抢功劳数据打架整体营销 ROI 算不清楚

1. 解决的问题

月 KOL 投放 30 万元,naive 归因显示 ROAS 3.5,但无法区分「因 KOL 才购买」和「本来就会买顺路点了链接」——PSM+DiD 因果归因将头部 KOL iROAS 从 4.2 修正为 1.8,将 30 万预算转向腰部 KOL 后年化增量 GMV 提升 44%

2. 核心算法逻辑

核心思想:KOL 投放的传统 ROI 计算(曝光量 × 转化率 × 客单价 / 投放费用)存在根本性缺陷——它无法区分「因为看了这条视频才购买」和「本来就会购买,顺路点了链接」。因果归因框架用反事实推断计算 KOL 投放的真实增量(ITE/LATE),消除自我选择偏差。

3. 业务应用场景

场景 A:TikTok KOL 矩阵投放效果评估(大品类分析)

- 业务痛点:品牌同时合作 50 个 TikTok KOL(头部 3 个 + 腰部 15 个 + 尾部 32 个),总投入 100 万元/月,naive GMV 归因显示 ROI = 3.5,但无法判断哪类 KOL 真正带来了增量 - 分析路径: 1. 获取 TikTok 平台的随机实验数据(Brand Lift Study,平台提供) 2. 对于无实验数据的 KOL,用 PSM 匹配「看过视频的用户」和「未看过但特征相似的用户」 3. 对每个 KOL 估计 iROAS - 结论示例: - 决策:将 30 万预算从头部 KOL 转移到腰部 KOL,总 iROAS 从 1.9 提升到 2.6

场景 B:小红书种草到 Amazon 购买的跨平台归因

4. 输入数据要求

请查看原始代码模板获取输入规格。

5. 输出结果

请查看原始代码模板获取输出规格。

6. 业务价值 / ROI

  • TikTok Brand Lift Study 可直接申请(需达量门槛),低难度
  • PSM + DiD 分析:中等(需匹配数据,但 Python 工具链成熟)
  • 跨平台归因(小红书→Amazon):较难(无 ID 打通,需 RDD 等间接方法)

7. 代码模板

代码块数量:6 · 路径:未检测到

from dataclasses import dataclass
import numpy as np
from scipy import stats

@dataclass
class KOLCampaign:
    kol_id: str
    spend: float
    naive_gmv: float
    exposed_users: int
    control_users: int
    exposed_cvr: float
    control_cvr: float
    aov: float

def estimate_incremental_roas(campaign: KOLCampaign) -> dict:
    """
    PSM 配对后的双样本因果 iROAS 估计。
    假设 exposed/control 已经过倾向得分匹配,组间特征平衡。
    """
    delta_cvr = campaign.exposed_cvr - campaign.control_cvr
    se = np.sqrt(
        campaign.exposed_cvr * (1 - campaign.exposed_cvr) / campaign.exposed_users
        + campaign.control_cvr * (1 - campaign.control_cvr) / campaign.control_users
    )
    z_stat = delta_cvr / se
    p_value = 2 * (1 - stats.norm.cdf(abs(z_stat)))

    incremental_gmv = delta_cvr * campaign.exposed_users * campaign.aov
    i_roas = incremental_gmv / campaign.spend if campaign.spend > 0 else 0.0
    attribution_fraction = incremental_gmv / campaign.naive_gmv if campaign.naive_gmv > 0 else 0.0

    return {
        "kol_id": campaign.kol_id,
        "naive_roas": round(campaign.naive_gmv / campaign.spend, 2),
        "i_roas": round(i_roas, 2),
        "incremental_gmv": round(incremental_gmv),
        "attribution_fraction": round(attribution_fraction, 3),
        "delta_cvr": round(delta_cvr, 4),
        "p_value": round(p_value, 4),
        "significant": p_value < 0.05,
    }

def rank_kol_portfolio(campaigns: list[KOLCampaign]) -> list[dict]:
    results = [estimate_incremental_roas(c) for c in campaigns]
    results.sort(key=lambda x: x["i_roas"], reverse=True)
    return results

# === 测试用例(模拟头部/腰部/尾部 KOL)===
campaigns = [
    KOLCampaign("KOL-TOP-001",    spend=50000, naive_gmv=210000, exposed_users=50000,
                control_users=50000, exposed_cvr=0.042, control_cvr=0.038, aov=1000),
    KOLCampaign("KOL-MID-007",    spend=20000, naive_gmv=62000,  exposed_users=25000,
                control_users=25000, exposed_cvr=0.031, control_cvr=0.020, aov=800),
    KOLCampaign("KOL-TAIL-023",   spend=5000,  naive_gmv=12000,  exposed_users=8000,
                control_users=8000,  exposed_cvr=0.028, control_cvr=0.019, aov=750),
]
results = rank_kol_portfolio(campaigns)
for r in results:
    print(f"{r['kol_id']}: naive_ROAS={r['naive_roas']} | iROAS={r['i_roas']} | "

8. 论文来源

未自动抽取;请查看原始 Skill 卡片。