livingbio / gstudio 內部產品導覽

Glia Ad Network
產品與資料模型導覽

給外包資料分析師的入門文件——GliaCloud 影音廣告聯播網怎麼運作、資料怎麼流、錢怎麼分。

來源:livingbio/gstudio(ad / report / publisher / accounting / payment 更新:2026-07-21 對象:不熟悉 ad tech 產業術語的資料分析師
← 回文件首頁
00

一句話定位

TL;DR

GliaCloud 提供一個可嵌入媒體(publisher)文章頁的影音播放器,播放器向 Google Ad Manager(GAM)、Prebid header bidding 供應商、以及 60+ 家區域型廣告聯播網 發送廣告請求,用 waterfall/即時競價決定播出哪支廣告、賺取廣告營收,再依合約比例分潤給媒體。gstudio 這個 repo 同時是「文章轉影片」內容生產工具,也是這整套廣告聯播網的後台——本文件只講後者。

換句話說:媒體不需要自己去談廣告、串接十幾個廣告平台的 SDK,把 GliaCloud 的播放器嵌進頁面,GliaCloud 就代為處理廣告競價、政策合規(ads.txt / sellers.json)、營收拆帳與付款。這是一個典型的 video ad network(影音廣告聯播網)商業模式:對媒體是「一站式影音變現」,對廣告主/廣告平台是「一個可以買到大量優質影音版位的供應商」。


01

商業模式與營收流程

錢的流向,由右到左依序被切分:

100
Demand 付的原始金額
− margin
IVT 無效流量預扣
= 淨營收
Glia 入帳(revenue_shard)
× share%
分潤給媒體 / Agency

Demand(廣告平台)先依 CPM/eCPM 付費 → 依 Demand 設定的 margin 預扣一部分 → 得到 Glia 真正入帳的 revenue_shard → 再依 Channel 的 share%(分潤比例)算出媒體應得的淨營收。margin 是因應 IVT(Invalid Traffic)事後被廣告平台追討(clawback)的風險,先保守預扣一部分不計入淨營收。

結算與付款是月結、以 Agency(對外簽約單位)為單位進行:

Slot 產生流量

播放器在頁面上曝光、發送廣告請求

Demand 出價得標

GAM waterfall/Prebid 競價後由某個 demand 得標並回報營收

定期拉報表

60+ 家 demand 的原始 report 定期匯入,寫進 Performance(各 demand 頻率不同,相關 cron 記錄各自設定)

月結算分潤

依 Channel share% 算出媒體淨營收,彙總到 Agency

Payment Notice

每個 Agency 每月一張,觸發實際匯款


02

核心資料實體與階層關係

整個系統可以看成一條由「誰付錢」到「誰收錢」的階層鏈。上層是商業/合約關係,下層是實際發送廣告請求的技術單位:

01
Agency
對外簽約、收付款的單位(媒體集團 / 代理商 / 單一大型媒體)
02
Channel
分潤結算單位,掛在 Agency 底下,決定 share%
03
Account
一個媒體站台,存 domain、ads.txt 狀態、GAM MCM child publisher 資訊
04
Slot
頁面上的播放器嵌入版位(float/story/AMP…)
05
SlotSetting
Slot 的一個設定版本(流量分配比例),報表實際對這層計費
06
AdUnit
把 Slot 接到某個 Placement 的中介,帶 traffic% 分流
07
Placement
某種廣告格式/通路設定(GAM Video、Prebid Outstream、Standard tag…)
08
Demand
廣告需求方品牌本身(Google AdX、FreakOut、Sparteo… 60+ 家)

每一層在系統裡負責的事情不同,整理如下:

實體白話角色誰在維護對應顆粒度
Agency簽約與收付款的商業單位,每月產出一張 Payment NoticeBD / AM
Channel分潤比例(share%)的設定單位;一個 Agency 可以有多個 ChannelBD / AM
Account一個媒體網站,帶 ads.txt/MCM child publisher 等合規資訊AM / RD站台
Slot頁面上的一個播放器版位,name 建立後不可改(報表 key)RD / AM版位
SlotSettingSlot 的設定版本;PerformanceAdUnitMetric 都對這層計費RD版位 × 版本
AdUnit連接 Slot 與 Placement,決定分多少流量給這個 demand 通路RD / AM版位 × 通路
Placement某個廣告格式的設定(GAM / Prebid / Standard,依技術類型分好幾種子類別)RD / AM通路
Demand廣告聯播網品牌本身,帶自己的 ads.txt 樣板與 IVT 預扣比例(margin)BD廣告平台

03

廣告投放機制

以下依「使用者打開頁面、播放器實際發送廣告請求」的即時發生順序來寫。

1. 決定用哪個 SlotSetting 版本

一個 Slot 底下可能同時存在好幾個 SlotSetting 版本:一個當作 control(現行版本),其他是 ExperimentSetting(實驗組),各自帶一個 traffic 權重(0~100)。Slot 發布給 player 的設定(Slot.entity_model)會把 traffic > 0 的版本全部列出來,player 載入頁面時依權重從這份清單挑一個版本來服務這次瀏覽——挑到哪個版本,接下來就照那個版本當下已經算好的 ad unit 順序繼續往下走。

2. Waterfall(廣告序列播放機制)

一個版位(Slot)底下的 SlotSetting 可以同時掛好幾個 demand 通路(AdUnit),每個 AdUnit 依 priority 排出順序、分組(groupId)。播放器初始化後會依序試打廣告請求:先打優先權最高的一組,該組沒有廣告回應(no fill)才往下一組打,逐層往下——這就是「waterfall」名稱的由來。播放時機(waterfall_mode:interval/pre-roll/mid-roll)、每輪間隔秒數,以及最多試幾輪(maxRounds/maxFalls)都可以設定。

3. 輪到 Prebid AdUnit 時:Header Bidding

waterfall 裡有一種 AdUnit 類型是 Prebid(GamPrebidVideoAdUnitStandardPrebidVideoAdUnit 等):輪到它那一組時,會同時向多個 SSP/DSP(Magnite、Openx、InMobi 等)發起即時競價,出價最高者成交——同一組裡原本要一個個問的多家 demand,改成同時比價,避免漏接願意出更高價的買家。

4. 輪到 GAM AdUnit 時:Google Ad Manager 與 MCM

waterfall 裡另一種常見的 AdUnit 類型會直接打 Google Ad Manager,由 GAM 依 LineItem/底價決定播出哪支廣告。Glia 同時營運兩個獨立的 GAM 網路,各自也跑一套 MCM(Multiple Customer Management),代表規模不足以自己申請 AdX/GAM 的「child publisher」去賣廣告版位:

Network網路代碼角色
Glia Publisher21818843116Glia 自己直營的 GAM 帳號;廣告版位依 GAM 的 inventory_management 設定分兩種 demand:Glia AdExchange Direct(版位庫存直接算在這個 network 自己名下)與 Glia MCM(版位委派給某個 MCM child publisher)
Dormknight22825748039另一個獨立的 GAM 帳號;同樣依 inventory_management 分成 Dormknight AdExchange DirectDormknight MCM 兩種 demand

MCM 媒體要先通過一套上線審核,才會有 demand 可以打——審核流程跟卡關會怎樣,寫在「合規與監控機制」一節。


04

版位自動優化

版位自動優化,指的是系統自動調整版位設定(廣告排序、要不要繼續跑某個設定)來提高營收,而這件事是透過實驗系統做到的。實驗系統是用真實流量做 A/B 測試的機制:把一個版位的一小部分流量分給新設定(實驗組 ExperimentSetting),其餘留在現行設定(control),兩邊同時跑、直接比營收成效。實驗組的設定會由以下兩個排程任務依成效數據持續自動調整:

Yield 優化(自動排序演算法)

排程任務 ad.tasks.UpdateDynamicExperimentAlgorithm(cron id 40)會套用掛在 ExperimentSetting 上的 ExperimentFunction——一段後台可編輯的排序演算法,依歷史 RPM/eCPM 把 ad units 重新排序,讓歷史表現好的通路排前面優先搶單,也可以排除掉後段低效的通路(要不要排除、門檻多少都是演算法程式碼裡自己決定,因實驗而異)。目標很單純:在每一次曝光上,盡量賣到最高的價錢。這個排程多久重跑一次,就在上面 cron id 40 那筆記錄裡調整。

停損檢查(Auto-pause)

排程任務 ad.tasks.UpdateExperimentTraffic(cron id 41)會比較每個 ExperimentSetting 跟它 control 在同一段觀察期的 RPM/CPM 等指標:每個實驗組可以設定 AutoPauseCondition(累計自實驗開始,或只看最近一天,門檻在後台設定),一旦成效比 control 差到觸發門檻,系統就自動把該實驗組的 traffic 砍到 0(停用,不會再被挑中服務任何頁面瀏覽),並發 Slack 通知。


05

營收報表資料模型

最核心的事實表是 Performance,一列資料的顆粒度是:

Performance 的一列 =

SlotSetting × time_unit_date(日)× Demand × purpose

欄位意義
ad_request_shard廣告請求數(fill rate 的分母)
ad_impr_shard實際曝光數
revenue_rawDemand 回報的原始金額(未扣 IVT 預扣)
revenue_shardrevenue_raw × margin,扣掉 IVT 預扣、再扣事後回溯調整(rebate)後,Glia 實際入帳的金額。margin 套用順序是 Account 覆寫 > MCM Child Publisher 覆寫 > Demand 預設值:同一個 Account 底下所有 Slot 對同一個 demand 用同一個 margin,但不同 Account 之間即使是同一個 demand,margin 也可能不同
purpose區分同一格資料是「正常營收」還是「事後回溯調整(rebate)」

更細顆粒(per ad unit)的 AdUnitMetric 才有現成算好的 eCPMRPMfill_rate 欄位;Performance 本身不存這些比率,要自己用 revenue/impression/request 算。

資料怎麼進來的:兩段式匯入

60+ 個 driver 拉原始報表

向各 demand 平台拉 revenue/impression,寫進 BigQuery;各 demand 頻率不同,相關 cron 記錄各自設定

拆分回 Slot 層級

依播放器端事件比例(如 ad.start 次數),把 demand 層級的營收拆分攤回各個 slot

寫回 Performance

排程讀回 BigQuery,upsert 進 Django 的 Performance

這 60+ 家 driver 涵蓋 Google GAM/AdX、日本/東南亞區域型影音聯播網(FreakOut、Fluct、Aniview)、Prebid 供應商(Magnite、Openx、InMobi)、以及多家歐洲/全球型影音聯播網(Sparteo、SmartAdServer、ShowHeroes)——反映 GliaCloud 是一個橫跨多國市場、同時對接 waterfall 與 header bidding 的區域型影音聯播網。

容易混淆

report/ app 只管廣告營收與投放,跟 analytics/ app(Instagram/Facebook 貼文的社群經營成效)是完全不同的兩件事,只是剛好都叫「數據」。


06

分潤與付款流程

月結時,先在 Channel 層算淨營收:net_revenue = gross_revenue × share / 100。同一個 Agency 底下所有 Channel 的淨營收加總後,系統自動產生一張 PaymentNotice(每個 Agency 每月一張)。若加總金額低於該 Agency 設定的 min_payment 門檻,就不會觸發付款,金額會累積到下個月。

為什麼有三間法人?

法人用途
GliaCloud(台灣)本地媒體合約,TWD 計價模板
SG Dormknight(新加坡)海外合約,USD/JPY 計價模板
BVI Dormknight(英屬維京群島)海外合約,USD/JPY 計價模板

每個 Agency 綁定一個 contract_entity,決定用哪個法人簽約、開哪一種付款模板(幣別/稅務格式)——目的是讓海外媒體的合約與付款不必全部走台灣公司,簡化跨境稅務與匯款流程。

Rebate(回溯調整)

部分 Agency 有「上月總 gross revenue 達到某個級距,就退一定比例回饋金」的自動 rebate 設定(金額級距 → 回饋 %),每月結算時會反推回「分潤前」金額計算,確保分潤(share)套用後金額仍然正確。


07

合規與監控機制

ads.txt/sellers.json 是 IAB 制定的反詐騙標準,用來對抗「假冒媒體賣廣告版位」:ads.txt 由媒體自己公開宣告「哪些廣告平台有權賣我的版位」;sellers.json 反過來,由廣告平台公開列出「我代理哪些賣方」。廣告主的競價系統下單前會核對兩者是否對得起來——對不起來,廣告平台就悄悄不出價,不會報錯,只會讓某個 demand 的營收無聲無息掉到 0。這也是為什麼系統有一整組自動檢查,各自的執行頻率都在後台 Cron 設定裡調整(連結見下表各筆):

Checker檢查什麼
check_adstxt媒體實際 ads.txt 跟 GAM 授權報表是否一致
check_sellers_jsonMCM parent 的 sellers.json 是否有新增/異動的賣方
check_lineitemGAM line item 是否被誤設成「對整個 Run of Network 投放」
check_mcm_ad_tag_urlMCM child publisher 的廣告標籤網路代碼是否正確
check_placement_mirror_slots該有對應 mirror placement 的版位是否都建好,避免漏掛 demand
check_std_ad_tag_url非 GAM 的標準 VAST 廣告標籤格式是否正確
detect_ad_abnormal拿當下數據跟過去 7 天/前兩週同星期中位數比對,抓「營收突然異常下降」(Dormknight/Gliacloud 各分 Daily/Hourly,共 4 筆記錄)

此外,GamViolation 會匯入 Google 寄來的政策違規報告,追蹤哪些站台/頁面被 Google 停止投放(政策違規、可疑流量等),提供 AM 主動處理。

MCM 媒體上線審核

媒體要能真正吃到 MCM demand(見「廣告投放機制」一節),得先通過一套審核流程,一關卡住就沒有 MCM 營收:

  1. 邀請(Invitation):Glia 發出 MCM 邀請,媒體接受
  2. Google 帳號審核:Google 端做身份與地址驗證(ID verification/mail PIN)
  3. 網站審核(Site approval):媒體的每個網域都要單獨送審,通過 AdX 政策檢查
  4. Readiness:帳號、網站、驗證都過了,狀態才會變成 READY,這時才真的能吃到 AdX demand

這是分析媒體「為什麼這個月營收突然跟其他 slot 落差很大」時第一個該查的地方。


08

名詞表

名詞白話解釋
Account一個媒體站台,掛在某個 Agency 底下
Agency對外簽約、收付款的商業單位,每月一張 Payment Notice
Channel分潤結算單位(決定 share%)。注意:report app 裡也有一個同名但已棄用的 Channel model,實際在用的是 publisher app 那個
Slot頁面上的播放器嵌入點;name 建立後不可改
SlotSettingSlot 的一個設定版本;報表實際對這層計費
AdUnit把 Slot 接到 Placement 的中介,決定分多少流量(traffic%)給這個通路
Placement某種廣告格式/通路設定(GAM Video、Prebid Outstream、Standard tag…)
Demand廣告聯播網品牌本身(Google AdX、FreakOut、Sparteo…60+ 家)
LineItemGAM/Prebid 裡具體的出價/合約設定(CPM、起訖時間)
Waterfall依優先權分組、依序試打廣告請求的機制:一組沒回應才往下一組打,跟 Header Bidding 的同時競價相對
Header Bidding / Prebid讓多個 demand 在 waterfall 跑之前先同時競價一次
Experiment 系統SlotSetting 的 A/B 測試框架:一個 control(現行版本)搭配多個 ExperimentSetting(實驗組),成效比 control 差到門檻會自動停用(traffic 砍到 0)
MCMGoogle 讓大帳號代管中小型媒體的機制,Glia Publisher 與 Dormknight 兩個 network 各自有一套(Glia MCM / Dormknight MCM),都扮演 parent 角色
ads.txt媒體公開宣告「哪些平台有權賣我版位」的文字檔(IAB 標準)
sellers.json廣告平台公開列出「我代理哪些賣方」的 JSON 檔,跟 ads.txt 互相對照
revenue_rawDemand 回報的原始金額(未扣 IVT 預扣)
revenue_shard扣掉 IVT 預扣(margin)/rebate 後,實際入帳的營收
marginDemand 層針對 IVT(無效流量)風險的預扣保留比例;跟 Channel 的 share(分潤)是完全不同層的概念,兩者疊加才是媒體最終拿到多少
shareChannel 的分潤比例(0~100%),net_revenue = gross × share/100
PaymentNotice每個 Agency 每月一張的對帳/付款通知單,是實際觸發匯款的單位

09

給分析師的實務提醒

踩坑筆記

  • 看 Slot 層級的長期趨勢時要小心:同一個 Slot 底下可能換過好幾個 SlotSetting(例如流量分配比例改版),營收其實是掛在 SlotSetting 上,不是 Slot 本身。
  • Payment Notice 產生後,那個月份的 Performance 資料會被鎖住不可再改——回填或修正歷史資料前先確認是否已經結過帳。
  • revenue_shard 是「Glia 入帳後」的金額,要算「媒體實際拿到的錢」還要再乘上 Channel 的 share%;同一個 Channel 底下不同使用者(user)看到的分潤比例還可能被個別覆寫,不等於 Channel 本身的 share。
  • Glia Publisher 與 Dormknight 是兩個完全獨立的 GAM network(不同網路代碼、不同計價幣別),同一個 Account 理論上可以同時掛兩邊——拉報表時務必確認 demand 名稱對到正確的網路(「Glia MCM」vs「Dormknight MCM」)。
  • 某個 demand 的營收無預警掉到 0,多半不是流量問題,先查 ads.txt/sellers.json 的自動檢查紀錄。
  • 各 demand 的報表匯入頻率與延遲天數不同(常見延遲 1~3 天),懷疑某個 demand 的資料缺漏或還沒進來時,先到匯入排程的後台設定查該 demand 的實際排程。