Publish campaign performance dashboard
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
.DS_Store
|
||||||
|
*.tmp
|
||||||
@@ -0,0 +1,902 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"pkg": "com.alibaba.aliexpresshd",
|
||||||
|
"adping_id": "11079265",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "谭超",
|
||||||
|
"geo": "BR",
|
||||||
|
"platform": "Kwai",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "purchase",
|
||||||
|
"remark": "8/10添加人群包后缀",
|
||||||
|
"channel": "kwai"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.alibaba.aliexpresshd",
|
||||||
|
"adping_id": "9751142",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "谭超",
|
||||||
|
"geo": "BR",
|
||||||
|
"platform": "Kwai",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "purchase",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "kwai"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.edadeal.android",
|
||||||
|
"adping_id": "10599157",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "idsp - 无事件要求",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.edadeal.android",
|
||||||
|
"adping_id": "6395488",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "idsp - 无事件要求",
|
||||||
|
"remark": "与10599157 under在同一个客户下",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.edadeal.android",
|
||||||
|
"adping_id": "91352117",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "idsp - 无事件要求",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.fxpro.direct.application",
|
||||||
|
"adping_id": "11080098",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "PK",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "reg_complete,depsitfirst_suc",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.fxpro.direct.application",
|
||||||
|
"adping_id": "7202934",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "PK",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "reg_complete,depsitfirst_suc",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.game.friends.ru",
|
||||||
|
"adping_id": "91414435",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Pause",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsaga",
|
||||||
|
"adping_id": "11324493",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "TH",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "af_level_achieved, af_purchase",
|
||||||
|
"remark": "0812 新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsaga",
|
||||||
|
"adping_id": "5497580",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "TH",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "af_level_achieved, af_purchase",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsaga",
|
||||||
|
"adping_id": "8998645",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "TH",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "af_level_achieved, af_purchase",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsaga",
|
||||||
|
"adping_id": "91535331",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "IN",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsaga",
|
||||||
|
"adping_id": "91410799",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "IN",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsodasaga",
|
||||||
|
"adping_id": "91471942",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "ID",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Pause",
|
||||||
|
"kpi": "idsp - 无事件要求",
|
||||||
|
"remark": "对照组和实验组用的同一个adping,人群包campaign没有新开adpingid给武汉",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsodasaga",
|
||||||
|
"adping_id": "91471943",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "PH",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Pause",
|
||||||
|
"kpi": "idsp - 无事件要求",
|
||||||
|
"remark": "对照组和实验组用的同一个adping,人群包campaign没有新开adpingid给武汉",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.krom.android",
|
||||||
|
"adping_id": "11079953",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "ID",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "first-money-in-non-referral-event",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.krom.android",
|
||||||
|
"adping_id": "5556054",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "ID",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "first-money-in-non-referral-event",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.oakever.meowdoku",
|
||||||
|
"adping_id": "91528811",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "PH",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Pause",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "只有实验组",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.puzzlegames.puzzlebrickslegend",
|
||||||
|
"adping_id": "91508383",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Pause",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.puzzlegames.puzzlebrickslegend",
|
||||||
|
"adping_id": "91508384",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Pause",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.vitastudio.mahjong",
|
||||||
|
"adping_id": "91538300",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "周梓君",
|
||||||
|
"geo": "ID",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.vitastudio.mahjong",
|
||||||
|
"adping_id": "91538301",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "周梓君",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.vitastudio.mahjong",
|
||||||
|
"adping_id": "91538306",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "周梓君",
|
||||||
|
"geo": "PH",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "8/14 还没上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.vitastudio.mahjong",
|
||||||
|
"adping_id": "91538307",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "周梓君",
|
||||||
|
"geo": "TH",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "8/14 还没上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.vitastudio.mahjong",
|
||||||
|
"adping_id": "91538308",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "周梓君",
|
||||||
|
"geo": "BR",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "8/14 还没上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.vitastudio.mahjong",
|
||||||
|
"adping_id": "91538309",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "周梓君",
|
||||||
|
"geo": "MY",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "8/14 还没上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.vitastudio.mahjong",
|
||||||
|
"adping_id": "91467820",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "谭超",
|
||||||
|
"geo": "ID",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.vitastudio.mahjong",
|
||||||
|
"adping_id": "91496148",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "谭超",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.vitastudio.mahjong",
|
||||||
|
"adping_id": "91496145",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "谭超",
|
||||||
|
"geo": "PH",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.vitastudio.mahjong",
|
||||||
|
"adping_id": "91467821",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "谭超",
|
||||||
|
"geo": "TH",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.vitastudio.mahjong",
|
||||||
|
"adping_id": "91496147",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "谭超",
|
||||||
|
"geo": "BR",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.vitastudio.mahjong",
|
||||||
|
"adping_id": "91496146",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "谭超",
|
||||||
|
"geo": "MY",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.yandex.bank",
|
||||||
|
"adping_id": "11078963",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "registration.result.ok",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.yandex.bank",
|
||||||
|
"adping_id": "2937658",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "registration.result.ok",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "daily.number.match.free.puzzle",
|
||||||
|
"adping_id": "91528810",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "周梓君",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.aliexpress.buyer",
|
||||||
|
"adping_id": "6060965",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "new_buyer>3%",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.aliexpress.buyer",
|
||||||
|
"adping_id": "4383473",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "new_buyer>3%",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.aliexpress.buyer",
|
||||||
|
"adping_id": "6061077",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "new_buyer>3%",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.aliexpress.buyer",
|
||||||
|
"adping_id": "6607117",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "new_buyer>3%",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.kinopoisk",
|
||||||
|
"adping_id": "10599681",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "idsp - 无事件要求",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.kinopoisk",
|
||||||
|
"adping_id": "8291713",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "万科",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "idsp - 无事件要求",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.ozon.app.android",
|
||||||
|
"adping_id": "11078827",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "UZ",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "s2s_firstorder",
|
||||||
|
"remark": "0811新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.ozon.app.android",
|
||||||
|
"adping_id": "11078981",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "KZ",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "s2s_firstorder",
|
||||||
|
"remark": "0811新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.ozon.app.android",
|
||||||
|
"adping_id": "11080833",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "KG",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "s2s_firstorder",
|
||||||
|
"remark": "0811新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.ozon.app.android",
|
||||||
|
"adping_id": "11081056",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "AM",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "s2s_firstorder",
|
||||||
|
"remark": "0811新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.ozon.app.android",
|
||||||
|
"adping_id": "5963400",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "UZ",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "s2s_firstorder",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.ozon.app.android",
|
||||||
|
"adping_id": "5963354",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "KZ",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "s2s_firstorder",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.ozon.app.android",
|
||||||
|
"adping_id": "9686529",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "KG",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "s2s_firstorder",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "ru.ozon.app.android",
|
||||||
|
"adping_id": "10080665",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "AM",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "s2s_firstorder",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "tech.jm",
|
||||||
|
"adping_id": "10501490",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "af_purchase",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "tech.jm",
|
||||||
|
"adping_id": "1745925",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "af_purchase",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.esprit.rpg.cntrctfft",
|
||||||
|
"adping_id": "11715627",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0826新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.esprit.rpg.cntrctfft",
|
||||||
|
"adping_id": "9311355",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0826新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsodasaga",
|
||||||
|
"adping_id": "11715655",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "BR",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0826新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsodasaga",
|
||||||
|
"adping_id": "8460883",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "BR",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0826新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsodasaga",
|
||||||
|
"adping_id": "11715811",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "TH",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0826新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsodasaga",
|
||||||
|
"adping_id": "6951600",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "TH",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0826新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.uma.musicvk",
|
||||||
|
"adping_id": "11690183",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "CPI订单,Install=New devicesKPI:new users>50%, cvr>0.5%(soft); 可用log in,play tracks, purchase事件优化质量",
|
||||||
|
"remark": "0826新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.uma.musicvk",
|
||||||
|
"adping_id": "2783561",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "CPI订单,Install=New devicesKPI:new users>50%, cvr>0.5%(soft); 可用log in,play tracks, purchase事件优化质量",
|
||||||
|
"remark": "0826新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.amazon.mShop.android.shopping",
|
||||||
|
"adping_id": "11729820",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "AE",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.amazon.mShop.android.shopping",
|
||||||
|
"adping_id": "11729927",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "ZA",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.amazon.mShop.android.shopping",
|
||||||
|
"adping_id": "11729830",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "BR",
|
||||||
|
"platform": "BIGO",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "bigo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.amazon.mShop.android.shopping",
|
||||||
|
"adping_id": "7572369",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "AE",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.amazon.mShop.android.shopping",
|
||||||
|
"adping_id": "6425889",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "ZA",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.amazon.mShop.android.shopping",
|
||||||
|
"adping_id": "10813123",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "黄政",
|
||||||
|
"geo": "BR",
|
||||||
|
"platform": "BIGO",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "bigo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.esprit.rpg.lttlefirykng",
|
||||||
|
"adping_id": "11655596",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "BIGO",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0827新上",
|
||||||
|
"channel": "bigo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.esprit.rpg.lttlefirykng",
|
||||||
|
"adping_id": "11763482",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "",
|
||||||
|
"geo": "RU",
|
||||||
|
"platform": "BIGO",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0827新上",
|
||||||
|
"channel": "bigo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsaga",
|
||||||
|
"adping_id": "8057746",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "MY",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0828新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsaga",
|
||||||
|
"adping_id": "5464039",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "詹涵粤",
|
||||||
|
"geo": "MY",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0828新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsaga",
|
||||||
|
"adping_id": "91407542",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "",
|
||||||
|
"geo": "ID",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.king.candycrushsaga",
|
||||||
|
"adping_id": "91535229",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "",
|
||||||
|
"geo": "ID",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.kwai.bulldog",
|
||||||
|
"adping_id": "11836152",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "",
|
||||||
|
"geo": "ID",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0831新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.kwai.bulldog",
|
||||||
|
"adping_id": "7815836",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "",
|
||||||
|
"geo": "ID",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0831新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.kotak811mobilebankingapp.instantsavingsupiscanandpayrecharge",
|
||||||
|
"adping_id": "11862336",
|
||||||
|
"group": "实验组",
|
||||||
|
"owner": "谭超",
|
||||||
|
"geo": "IN",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0901新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkg": "com.kotak811mobilebankingapp.instantsavingsupiscanandpayrecharge",
|
||||||
|
"adping_id": "91399439",
|
||||||
|
"group": "对照组",
|
||||||
|
"owner": "谭超",
|
||||||
|
"geo": "IN",
|
||||||
|
"platform": "MTG",
|
||||||
|
"status": "Active",
|
||||||
|
"kpi": "",
|
||||||
|
"remark": "0901新上",
|
||||||
|
"channel": "mintegral"
|
||||||
|
}
|
||||||
|
]
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<title>Campaign 表现</title>
|
||||||
|
<style>
|
||||||
|
:root{--bg:#f4f6f8;--panel:#fff;--text:#17212b;--muted:#687481;--line:#e4e9ee;--brand:#1769e0;--good:#16825d;--warn:#c46a08}
|
||||||
|
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--text);font:14px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC",sans-serif}
|
||||||
|
main{max-width:1500px;margin:auto;padding:28px}.head{display:flex;justify-content:space-between;gap:24px;align-items:flex-end;margin-bottom:20px}
|
||||||
|
h1{font-size:28px;margin:0 0 4px}.sub,.fresh{color:var(--muted)}.fresh{text-align:right}.panel{background:var(--panel);border:1px solid var(--line);border-radius:12px;box-shadow:0 1px 2px #16202a0a}
|
||||||
|
.filters{display:grid;grid-template-columns:repeat(7,minmax(130px,1fr));gap:12px;padding:16px;margin-bottom:16px}.field label{display:block;color:var(--muted);font-size:12px;margin-bottom:5px}
|
||||||
|
select,input{width:100%;height:36px;border:1px solid #cfd7df;border-radius:7px;background:#fff;padding:0 9px;color:var(--text)}
|
||||||
|
.cards{display:grid;grid-template-columns:repeat(7,1fr);gap:12px;margin-bottom:16px}.card{padding:16px}.card .label{color:var(--muted);font-size:12px}.card .value{font-size:23px;font-weight:650;margin-top:5px;font-variant-numeric:tabular-nums}
|
||||||
|
.grid{display:grid;grid-template-columns:1.15fr .85fr;gap:16px;margin-bottom:16px}.chart{padding:18px;min-height:310px}.title{font-size:16px;font-weight:650;margin-bottom:12px}
|
||||||
|
svg{width:100%;height:245px}.axis{stroke:#d8dfe6}.spend-line{fill:none;stroke:var(--brand);stroke-width:2.5}.conv-line{fill:none;stroke:var(--good);stroke-width:2.5}.legend{display:flex;gap:18px;color:var(--muted);font-size:12px}.dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:5px}
|
||||||
|
.barrow{display:grid;grid-template-columns:minmax(160px,1.4fr) 3fr 90px;gap:10px;align-items:center;margin:10px 0}.barlabel{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.track{height:12px;background:#eef2f5;border-radius:8px;overflow:hidden}.fill{height:100%;background:var(--brand);border-radius:8px}.num{text-align:right;font-variant-numeric:tabular-nums}
|
||||||
|
.table-panel{padding:18px}.table-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}.table-note{color:var(--muted);font-size:12px}.table-wrap{overflow:auto;max-height:640px;border:1px solid var(--line);border-radius:8px}
|
||||||
|
table{width:100%;border-collapse:collapse;white-space:nowrap}th{position:sticky;top:0;background:#f7f9fb;color:#52606d;text-align:left;font-size:12px;z-index:1}th,td{padding:9px 10px;border-bottom:1px solid var(--line)}td.num,th.num{text-align:right}tbody tr:hover{background:#f7faff}.control{color:#536171}.experiment{color:#7b3fc6}.empty{padding:48px;text-align:center;color:var(--muted)}
|
||||||
|
.foot{margin-top:14px;color:var(--muted);font-size:12px}.status{display:inline-block;padding:2px 7px;border-radius:9px;background:#e8f5ef;color:var(--good)}
|
||||||
|
@media(max-width:1050px){.filters{grid-template-columns:repeat(3,1fr)}.cards{grid-template-columns:repeat(3,1fr)}.grid{grid-template-columns:1fr}}
|
||||||
|
@media(max-width:640px){main{padding:14px}.head{display:block}.fresh{text-align:left;margin-top:8px}.filters,.cards{grid-template-columns:1fr 1fr}.card .value{font-size:19px}}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body><main>
|
||||||
|
<div class="head"><div><h1>Campaign 表现</h1><div class="sub">按日期、组别和 Campaign 查看投放效果</div></div><div class="fresh" id="fresh">正在加载数据…</div></div>
|
||||||
|
<section class="panel filters">
|
||||||
|
<div class="field"><label>日期</label><select id="date"></select></div>
|
||||||
|
<div class="field"><label>pkg</label><select id="pkg"></select></div>
|
||||||
|
<div class="field"><label>GEO</label><select id="geo"></select></div>
|
||||||
|
<div class="field"><label>渠道</label><select id="source"></select></div>
|
||||||
|
<div class="field"><label>组别</label><select id="group"></select></div>
|
||||||
|
<div class="field"><label>订单状态(G列)</label><select id="status"></select></div>
|
||||||
|
<div class="field"><label>Campaign / adping ID</label><input id="search" placeholder="搜索"></div>
|
||||||
|
</section>
|
||||||
|
<section class="cards" id="cards"></section>
|
||||||
|
<section class="grid">
|
||||||
|
<div class="panel chart"><div class="title">每日趋势</div><div class="legend"><span><i class="dot" style="background:#1769e0"></i>Spend</span><span><i class="dot" style="background:#16825d"></i>Conversions</span></div><svg id="trend" viewBox="0 0 720 245" preserveAspectRatio="none"></svg></div>
|
||||||
|
<div class="panel chart"><div class="title">Campaign 花费排名</div><div id="ranking"></div></div>
|
||||||
|
</section>
|
||||||
|
<section class="panel table-panel"><div class="table-head"><div class="title" style="margin:0">Detail</div><div class="table-note" id="count"></div></div><div class="table-wrap"><table><thead><tr><th>Date</th><th>组别</th><th>Campaign name</th><th>pkg</th><th>GEO</th><th>渠道</th><th>adping ID</th><th>KPI 事件</th><th class="num">Impression</th><th class="num">Click</th><th class="num">Conversions</th><th class="num">Spend</th><th class="num">CTR</th><th class="num">CVR</th><th class="num">CPA</th></tr></thead><tbody id="body"></tbody></table></div></section>
|
||||||
|
<div class="foot">数据源:Tableau · DSP Daily Data。组别、GEO、渠道、状态和 KPI 来自 Campaign info;订单状态以 G 列为准。对照组统一显示为 General campaign。比率均使用汇总后的分子与分母重新计算。</div>
|
||||||
|
</main><script>
|
||||||
|
const $=id=>document.getElementById(id), dims=['date','pkg','geo','source','group','status']; let all=[];
|
||||||
|
const n=(v,d=0)=>Number(v||0).toLocaleString('en-US',{minimumFractionDigits:d,maximumFractionDigits:d});
|
||||||
|
const rate=(a,b)=>b?a/b:0, pct=v=>(100*v).toFixed(2)+'%', money=v=>'$'+n(v,2);
|
||||||
|
function options(id,values,preferred){const el=$(id), old=el.value; el.innerHTML='<option value="">All</option>'+[...new Set(values.filter(Boolean))].sort().map(v=>`<option>${v}</option>`).join(''); el.value=old&&values.includes(old)?old:(preferred||'')}
|
||||||
|
function filtered(){const q=$('search').value.trim().toLowerCase();return all.filter(r=>dims.every(k=>!$(k).value||String(r[k])===$(k).value)&&(!q||(`${r.campaign} ${r.adpingId}`).toLowerCase().includes(q)))}
|
||||||
|
function aggregate(rows,keys){const m=new Map;for(const r of rows){const k=keys.map(x=>r[x]).join('\u0001');if(!m.has(k))m.set(k,{...Object.fromEntries(keys.map(x=>[x,r[x]])),impression:0,click:0,conversions:0,spend:0,kpi:r.kpi||''});const o=m.get(k);for(const x of ['impression','click','conversions','spend'])o[x]+=+r[x]||0}return [...m.values()]}
|
||||||
|
function cards(rows){const t=aggregate(rows,[])[0]||{impression:0,click:0,conversions:0,spend:0};const vals=[['Spend',money(t.spend)],['Conversions',n(t.conversions)],['CPA',t.conversions?money(t.spend/t.conversions):'—'],['Impression',n(t.impression)],['Click',n(t.click)],['CTR',pct(rate(t.click,t.impression))],['CVR',pct(rate(t.conversions,t.click))]];$('cards').innerHTML=vals.map(x=>`<div class="panel card"><div class="label">${x[0]}</div><div class="value">${x[1]}</div></div>`).join('')}
|
||||||
|
function trend(rows){const d=aggregate(rows,['date']).sort((a,b)=>a.date.localeCompare(b.date)),svg=$('trend');if(!d.length){svg.innerHTML='';return}const W=720,H=245,p=28,maxS=Math.max(...d.map(x=>x.spend),1),maxC=Math.max(...d.map(x=>x.conversions),1),x=i=>p+(W-p*2)*(d.length===1?.5:i/(d.length-1)),path=(key,max)=>d.map((r,i)=>(i?'L':'M')+x(i).toFixed(1)+' '+(H-p-(H-p*2)*r[key]/max).toFixed(1)).join(' ');const labels=d.filter((_,i)=>i===0||i===d.length-1||i===Math.floor(d.length/2)).map((r,i,a)=>`<text x="${x(d.indexOf(r))}" y="238" text-anchor="middle" fill="#74808c" font-size="11">${r.date.slice(5)}</text>`).join('');svg.innerHTML=`<line class="axis" x1="${p}" y1="${H-p}" x2="${W-p}" y2="${H-p}"/><path class="spend-line" d="${path('spend',maxS)}"/><path class="conv-line" d="${path('conversions',maxC)}"/>${labels}`}
|
||||||
|
function ranking(rows){const d=aggregate(rows,['campaign']).sort((a,b)=>b.spend-a.spend).slice(0,10),max=d[0]?.spend||1;$('ranking').innerHTML=d.length?d.map(r=>`<div class="barrow" title="${r.campaign}"><div class="barlabel">${r.campaign}</div><div class="track"><div class="fill" style="width:${100*r.spend/max}%"></div></div><div class="num">${money(r.spend)}</div></div>`).join(''):'<div class="empty">暂无数据</div>'}
|
||||||
|
function table(rows){const d=aggregate(rows,['date','group','campaign','pkg','geo','source','adpingId','kpi']).sort((a,b)=>b.date.localeCompare(a.date)||(a.group==='对照组'?-1:1)-(b.group==='对照组'?-1:1)||b.spend-a.spend);$('count').textContent=`${n(d.length)} 行`;$('body').innerHTML=d.slice(0,2000).map(r=>`<tr><td>${r.date}</td><td class="${r.group==='对照组'?'control':'experiment'}">${r.group}</td><td>${r.campaign}</td><td>${r.pkg}</td><td>${r.geo}</td><td>${r.source}</td><td>${r.adpingId}</td><td>${r.kpi||'—'}</td><td class="num">${n(r.impression)}</td><td class="num">${n(r.click)}</td><td class="num">${n(r.conversions)}</td><td class="num">${money(r.spend)}</td><td class="num">${pct(rate(r.click,r.impression))}</td><td class="num">${pct(rate(r.conversions,r.click))}</td><td class="num">${r.conversions?money(r.spend/r.conversions):'—'}</td></tr>`).join('')||'<tr><td colspan="15" class="empty">当前筛选没有数据</td></tr>'}
|
||||||
|
function render(){const rows=filtered();cards(rows);trend(rows);ranking(rows);table(rows)}
|
||||||
|
fetch('data.json',{cache:'no-store'}).then(r=>r.ok?r.json():Promise.reject()).then(d=>{all=d.rows||[];dims.forEach(k=>options(k,all.map(r=>r[k]),k==='status'?'Active':''));$('fresh').innerHTML=`数据截至 <strong>${d.latestDate||'—'}</strong><br>更新于 ${new Date(d.generatedAt).toLocaleString('zh-CN',{hour12:false})}`;dims.forEach(k=>$(k).addEventListener('change',render));$('search').addEventListener('input',render);render()}).catch(()=>{$('fresh').textContent='数据加载失败';$('body').innerHTML='<tr><td colspan="15" class="empty">无法读取 data.json</td></tr>'});
|
||||||
|
</script></body></html>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
1
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# AgentStage runs this hourly. The guard below refreshes once after 12:00 Asia/Shanghai.
|
||||||
|
export TZ=Asia/Shanghai
|
||||||
|
hour="$(date +%H)"
|
||||||
|
target_date="$(date -v-1d +%F 2>/dev/null || date -d yesterday +%F)"
|
||||||
|
if [ "$hour" -lt 12 ]; then exit 0; fi
|
||||||
|
|
||||||
|
: "${TABLEAU_COOKIE:?Set TABLEAU_COOKIE in the AgentStage runner secret environment}"
|
||||||
|
base_url="${TABLEAU_CSV_URL:-https://mars.ushareit.org/views/DSPSpend/DSPDailyData.csv}"
|
||||||
|
tmp_file="$(mktemp)"
|
||||||
|
trap 'rm -f "$tmp_file"' EXIT
|
||||||
|
|
||||||
|
pkg_csv="$(python3 -c 'import json; d=json.load(open("campaign_config.json")); print(",".join(sorted({r["pkg"] for r in d if r["status"].lower()=="active"})))')"
|
||||||
|
query="?:showVizHome=no&dt=${target_date}&pkg=${pkg_csv}&维度1=pkg&维度2=campaign_name&Source=展开&source=bigo,kwai,mintegral"
|
||||||
|
curl -fsSL --cookie "$TABLEAU_COOKIE" "${base_url}${query}" -o "$tmp_file"
|
||||||
|
|
||||||
|
python3 - "$tmp_file" "$target_date" <<'PY'
|
||||||
|
import csv, io, json, re, sys
|
||||||
|
from datetime import datetime
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
|
src, target = sys.argv[1:]
|
||||||
|
raw = open(src, 'rb').read()
|
||||||
|
if b'<html' in raw[:1000].lower(): raise SystemExit('Tableau authentication redirected to HTML')
|
||||||
|
text = raw.decode('utf-16') if raw.startswith((b'\xff\xfe', b'\xfe\xff')) else raw.decode('utf-8-sig')
|
||||||
|
delimiter = '\t' if text.count('\t') > text.count(',') else ','
|
||||||
|
incoming = list(csv.DictReader(io.StringIO(text), delimiter=delimiter))
|
||||||
|
config = json.load(open('campaign_config.json', encoding='utf-8'))
|
||||||
|
by_id = {str(r['adping_id']): r for r in config}
|
||||||
|
|
||||||
|
def num(v):
|
||||||
|
try: return float(str(v or '0').replace(',', '').replace('%', ''))
|
||||||
|
except ValueError: return 0
|
||||||
|
|
||||||
|
rows=[]
|
||||||
|
for r in incoming:
|
||||||
|
m=re.match(r'^(\d+)', r.get('维度2',''))
|
||||||
|
if not m or m.group(1) not in by_id: continue
|
||||||
|
c=by_id[m.group(1)]; group=c['group']
|
||||||
|
source=(r.get('Source') or c['channel']).lower()
|
||||||
|
rows.append({'date':target,'pkg':c['pkg'],'geo':c['geo'],'source':source,'group':group,
|
||||||
|
'adpingId':c['adping_id'],'campaign':'General campaign' if group=='对照组' else r.get('维度2',''),
|
||||||
|
'status':c['status'],'kpi':c['kpi'],'impression':num(r.get('impression')),'click':num(r.get('click')),
|
||||||
|
'conversions':num(r.get('conversions')),'spend':num(r.get('spend'))})
|
||||||
|
if not rows: raise SystemExit('No valid Tableau rows; data.json preserved')
|
||||||
|
old=json.load(open('data.json',encoding='utf-8')) if __import__('os').path.exists('data.json') else {'rows':[]}
|
||||||
|
old['rows']=[r for r in old.get('rows',[]) if r.get('date')!=target]+rows
|
||||||
|
old['latestDate']=max(r['date'] for r in old['rows'])
|
||||||
|
old['generatedAt']=datetime.now(ZoneInfo('Asia/Shanghai')).isoformat()
|
||||||
|
old['source']='DSP Daily Data / Campaign info'
|
||||||
|
with open('data.json.tmp','w',encoding='utf-8') as f: json.dump(old,f,ensure_ascii=False,separators=(',',':'))
|
||||||
|
__import__('os').replace('data.json.tmp','data.json')
|
||||||
|
PY
|
||||||
Reference in New Issue
Block a user