Add campaign experiment and control reporting
This commit is contained in:
@@ -16,7 +16,7 @@ RAW_CSV="$TMP_DIR/tableau.csv"
|
||||
if [ -n "${SOURCE_CSV:-}" ]; then
|
||||
cp "$SOURCE_CSV" "$RAW_CSV"
|
||||
else
|
||||
TABLEAU_URL=${TABLEAU_CSV_URL:-'https://mars.ushareit.org/views/DSPSpend/DSPDailyData.csv?:showVizHome=no&%E7%BB%B4%E5%BA%A61=pkg'}
|
||||
TABLEAU_URL=${TABLEAU_CSV_URL:-'https://mars.ushareit.org/views/DSPSpend/DSPDailyData.csv?:showVizHome=no&%E7%BB%B4%E5%BA%A61=pkg&%E7%BB%B4%E5%BA%A62=adping_id'}
|
||||
if [ -n "${TABLEAU_COOKIE:-}" ]; then
|
||||
curl --fail --silent --show-error --location \
|
||||
--cookie "$TABLEAU_COOKIE" "$TABLEAU_URL" --output "$RAW_CSV"
|
||||
@@ -25,7 +25,7 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
python3 - "$RAW_CSV" "$ROOT_DIR/data.json" <<'PY'
|
||||
python3 - "$RAW_CSV" "$ROOT_DIR/campaigns.csv" "$ROOT_DIR/data.json" <<'PY'
|
||||
import csv
|
||||
import datetime as dt
|
||||
import io
|
||||
@@ -34,7 +34,8 @@ import pathlib
|
||||
import sys
|
||||
|
||||
source_path = pathlib.Path(sys.argv[1])
|
||||
output_path = pathlib.Path(sys.argv[2])
|
||||
campaign_path = pathlib.Path(sys.argv[2])
|
||||
output_path = pathlib.Path(sys.argv[3])
|
||||
raw = source_path.read_bytes()
|
||||
head = raw[:500].lower()
|
||||
if b"<html" in head or b"tableau server" in head:
|
||||
@@ -48,26 +49,10 @@ else:
|
||||
sample = text[:4096]
|
||||
delimiter = "\t" if sample.count("\t") > sample.count(",") else ","
|
||||
reader = csv.DictReader(io.StringIO(text), delimiter=delimiter)
|
||||
|
||||
active_pkgs = [
|
||||
"com.alibaba.aliexpresshd",
|
||||
"com.edadeal.android",
|
||||
"com.fxpro.direct.application",
|
||||
"com.king.candycrushsaga",
|
||||
"com.krom.android",
|
||||
"com.vitastudio.mahjong",
|
||||
"com.yandex.bank",
|
||||
"daily.number.match.free.puzzle",
|
||||
"ru.aliexpress.buyer",
|
||||
"ru.kinopoisk",
|
||||
"ru.ozon.app.android",
|
||||
"tech.im",
|
||||
"com.esprit.rpg.cntrctfft",
|
||||
"com.uma.musicvk",
|
||||
"com.amazon.mShop.android.shopping",
|
||||
"com.esprit.rpg.lttlefirykng",
|
||||
]
|
||||
active = set(active_pkgs)
|
||||
with campaign_path.open(encoding="utf-8-sig", newline="") as f:
|
||||
campaigns = list(csv.DictReader(f))
|
||||
campaign_by_key = {(r["pkg"], r["adping_id"]): r for r in campaigns if r["status"] == "Active"}
|
||||
active_pkgs = sorted({r["pkg"] for r in campaigns if r["status"] == "Active"})
|
||||
|
||||
def pick(row, *names):
|
||||
for name in names:
|
||||
@@ -84,16 +69,23 @@ def number(value):
|
||||
except ValueError:
|
||||
return 0.0
|
||||
|
||||
daily_map = {}
|
||||
campaign_daily_map = {}
|
||||
for row in reader:
|
||||
pkg = pick(row, "维度1", "pkg", "Pkg").strip()
|
||||
if pkg not in active:
|
||||
adping_id = pick(row, "维度2", "adping_id", "adpingid").strip()
|
||||
campaign = campaign_by_key.get((pkg, adping_id))
|
||||
if not campaign:
|
||||
continue
|
||||
date = pick(row, "dt1", "dt", "date").strip()
|
||||
if not date:
|
||||
continue
|
||||
key = (date, pkg)
|
||||
item = daily_map.setdefault(key, {"date": date, "pkg": pkg, "impression": 0, "click": 0, "conversion": 0, "spend": 0.0})
|
||||
key = (date, pkg, adping_id)
|
||||
item = campaign_daily_map.setdefault(key, {
|
||||
"date": date, "pkg": pkg, "adping_id": adping_id,
|
||||
"group": campaign["group"], "geo": campaign["geo"],
|
||||
"platform": campaign["platform"], "owner": campaign["owner"],
|
||||
"impression": 0, "click": 0, "conversion": 0, "spend": 0.0,
|
||||
})
|
||||
item["impression"] += round(number(pick(row, "impression", "Impression")))
|
||||
item["click"] += round(number(pick(row, "click", "Click")))
|
||||
item["conversion"] += round(number(pick(row, "conversions", "conversion", "Conversion")))
|
||||
@@ -112,6 +104,13 @@ def metrics(item):
|
||||
item["ecpi"] = spend / conv if conv else None
|
||||
return item
|
||||
|
||||
campaign_daily = [metrics(v) for _, v in sorted(campaign_daily_map.items())]
|
||||
daily_map = {}
|
||||
for row in campaign_daily:
|
||||
key = (row["date"], row["pkg"])
|
||||
item = daily_map.setdefault(key, {"date": row["date"], "pkg": row["pkg"], "impression": 0, "click": 0, "conversion": 0, "spend": 0.0})
|
||||
for field in ("impression", "click", "conversion", "spend"):
|
||||
item[field] += row[field]
|
||||
daily = [metrics(v) for _, v in sorted(daily_map.items())]
|
||||
summary = []
|
||||
for pkg in active_pkgs:
|
||||
@@ -133,6 +132,8 @@ payload = {
|
||||
"date_start": dates[0] if dates else None,
|
||||
"date_end": dates[-1] if dates else None,
|
||||
"active_pkg_count": len(active_pkgs),
|
||||
"active_campaign_count": len(campaigns),
|
||||
"campaign_with_data_count": len({(r["pkg"], r["adping_id"]) for r in campaign_daily}),
|
||||
"pkg_with_data_count": sum(1 for x in summary if x["has_data"]),
|
||||
"definitions": {
|
||||
"CTR": "click / impression",
|
||||
@@ -144,10 +145,11 @@ payload = {
|
||||
},
|
||||
"summary": summary,
|
||||
"daily": daily,
|
||||
"campaigns": campaigns,
|
||||
"campaign_daily": campaign_daily,
|
||||
}
|
||||
|
||||
tmp = output_path.with_suffix(".json.tmp")
|
||||
tmp.write_text(json.dumps(payload, ensure_ascii=False, separators=(",", ":")), encoding="utf-8")
|
||||
tmp.replace(output_path)
|
||||
PY
|
||||
|
||||
|
||||
Reference in New Issue
Block a user