[{"data":1,"prerenderedAt":1614},["ShallowReactive",2],{"article-alternates":3,"article-\u002Fen\u002Fdata\u002Fmarketing-mix-modeling-robyn-practical-setup":13},{"i18nKey":4,"paths":5},"data-005-2026-05",{"de":6,"en":7,"es":8,"fr":9,"it":10,"ru":11,"tr":12},"\u002Fde\u002Fdata\u002Frobyn-marketing-mix-modeling-praktik-kurulum","\u002Fen\u002Fdata\u002Fmarketing-mix-modeling-robyn-practical-setup","\u002Fes\u002Fdata\u002Frobyn-marketing-mix-modeling-guia-practica","\u002Ffr\u002Fdata\u002Frobyn-marketing-mix-modeling-praktik-kurulum","\u002Fit\u002Fdata\u002Frobyn-marketing-mix-modeling-pratico-setup","\u002Fru\u002Fdata\u002Frobyn-marketing-mix-modeling-setup","\u002Ftr\u002Fdata\u002Fmarketing-mix-modeling-robyn-ile-pratik-kurulum",{"_path":7,"_dir":14,"_draft":15,"_partial":15,"_locale":16,"title":17,"description":18,"publishedAt":19,"modifiedAt":19,"category":14,"i18nKey":4,"tags":20,"readingTime":26,"author":27,"body":28,"_type":1608,"_id":1609,"_source":1610,"_file":1611,"_stem":1612,"_extension":1613},"data",false,"","Marketing Mix Modeling: Practical Setup with Robyn","Deploy Meta's open-source MMM library Robyn on BigQuery to model saturation curves, adstock decay, and holdout validation for accurate channel ROI attribution.","2026-05-17",[21,22,23,24,25],"marketing-mix-modeling","robyn","meta","adstock","saturation-curve",8,"Roibase",{"type":29,"children":30,"toc":1598},"root",[31,39,46,51,56,61,67,72,81,91,111,116,124,142,147,153,158,163,187,195,203,208,216,281,286,293,429,434,440,445,450,458,618,626,644,649,655,660,703,711,1346,1359,1365,1370,1375,1383,1562,1567,1572,1576,1592],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36],{"type":37,"value":38},"text","Attribution window has collapsed to 7 days, cookie consent rejection exceeds 40%, and multi-touch cross-channel contribution has become unmeasurable. In 2026, the performance marketer's single reliable tool is aggregate econometric modeling — Marketing Mix Modeling. Meta's Robyn library, open-sourced in 2021, made this process production-ready for the first time. How to interpret saturation curves, what adstock decay means, at what intervals holdout validation operates — this post walks through deploying Robyn on BigQuery data stack to answer these questions.",{"type":32,"tag":40,"props":41,"children":43},"h2",{"id":42},"what-robyn-is-and-what-it-isnt",[44],{"type":37,"value":45},"What Robyn Is, and What It Isn't",{"type":32,"tag":33,"props":47,"children":48},{},[49],{"type":37,"value":50},"Robyn is an R library released open-source by Facebook Marketing Science. Its purpose: to regress weekly or daily channel spend plus external macro variables (holidays, seasonality, price) against sales metrics. Output: each channel's ROAS, saturation level, lag effect (adstock), and optimal budget allocation.",{"type":32,"tag":33,"props":52,"children":53},{},[54],{"type":37,"value":55},"What it isn't: it is not last-click attribution, doesn't track user-level conversion paths. Uses no personal data, awaits no cookie signals. It employs aggregate time series regression with non-linear transformations tuned via Nevergrad hyperparameter optimization — scanning complex saturation functions rather than fitting Ridge or Lasso.",{"type":32,"tag":33,"props":57,"children":58},{},[59],{"type":37,"value":60},"Standard MMM processes model ~36 data points monthly. Robyn works at daily granularity — minimum 104 weeks (2 years) recommended. Below 52 weeks, variance stays high and confidence intervals unreliable.",{"type":32,"tag":40,"props":62,"children":64},{"id":63},"saturation-curve-s-curve-and-hill-function",[65],{"type":37,"value":66},"Saturation Curve: S-Curve and Hill Function",{"type":32,"tag":33,"props":68,"children":69},{},[70],{"type":37,"value":71},"At Robyn's core sit two saturation transformations: Adbudg (S-curve) and Hill. Both encode the assumption of diminishing marginal returns. Every additional 1,000 units spent on a channel won't yield the same response as the first 1,000.",{"type":32,"tag":33,"props":73,"children":74},{},[75],{"type":32,"tag":76,"props":77,"children":78},"strong",{},[79],{"type":37,"value":80},"Hill transformation formula:",{"type":32,"tag":82,"props":83,"children":85},"pre",{"code":84},"y = K * (x^alpha) \u002F (S^alpha + x^alpha)\n",[86],{"type":32,"tag":87,"props":88,"children":89},"code",{"__ignoreMap":16},[90],{"type":37,"value":84},{"type":32,"tag":92,"props":93,"children":94},"ul",{},[95,101,106],{"type":32,"tag":96,"props":97,"children":98},"li",{},[99],{"type":37,"value":100},"K: maximum response (asymptote)",{"type":32,"tag":96,"props":102,"children":103},{},[104],{"type":37,"value":105},"S: half-saturation point (spend reaches 50% of K response)",{"type":32,"tag":96,"props":107,"children":108},{},[109],{"type":37,"value":110},"alpha: curve steepness (alpha > 1 = S-curve, alpha \u003C 1 = concave)",{"type":32,"tag":33,"props":112,"children":113},{},[114],{"type":37,"value":115},"Robyn optimizes alpha and S for each channel via Nevergrad. Tests 10,000+ combinations, selects the best fit using lowest NRMSE (normalized root mean squared error).",{"type":32,"tag":33,"props":117,"children":118},{},[119],{"type":32,"tag":76,"props":120,"children":121},{},[122],{"type":37,"value":123},"Practical interpretation:",{"type":32,"tag":92,"props":125,"children":126},{},[127,132,137],{"type":32,"tag":96,"props":128,"children":129},{},[130],{"type":37,"value":131},"If Google Ads returns S = 50,000 units, weekly spend at 50,000 reaches half your response potential.",{"type":32,"tag":96,"props":133,"children":134},{},[135],{"type":37,"value":136},"If alpha = 2.5, the curve is steeply S-shaped: below 50,000 units returns are low, above it they plateau slowly.",{"type":32,"tag":96,"props":138,"children":139},{},[140],{"type":37,"value":141},"Budget optimizer uses these curves to answer \"raise Google from 50,000 to 60,000 or Facebook from 30,000 to 40,000?\" — answering via marginal response comparison.",{"type":32,"tag":33,"props":143,"children":144},{},[145],{"type":37,"value":146},"Real-world patterns: search budgets typically concave (alpha \u003C 1, limited demand), display\u002Fvideo convex (alpha > 1, unlimited inventory but finite attention).",{"type":32,"tag":40,"props":148,"children":150},{"id":149},"adstock-decay-modeling-lagged-effects",[151],{"type":37,"value":152},"Adstock Decay: Modeling Lagged Effects",{"type":32,"tag":33,"props":154,"children":155},{},[156],{"type":37,"value":157},"Marketing spend impacts sales same-day but effects can linger weeks. TV drives brand recall for 3 weeks after air date; paid social peaks within 7 days. Adstock mathematically encodes this carryover and decay.",{"type":32,"tag":33,"props":159,"children":160},{},[161],{"type":37,"value":162},"Robyn offers two adstock transformations:",{"type":32,"tag":164,"props":165,"children":166},"ol",{},[167,177],{"type":32,"tag":96,"props":168,"children":169},{},[170,175],{"type":32,"tag":76,"props":171,"children":172},{},[173],{"type":37,"value":174},"Geometric adstock:",{"type":37,"value":176}," exponential decay. Theta parameter (0–1). Theta = 0.5 means last week's effect carries 50% into this week.",{"type":32,"tag":96,"props":178,"children":179},{},[180,185],{"type":32,"tag":76,"props":181,"children":182},{},[183],{"type":37,"value":184},"Weibull adstock:",{"type":37,"value":186}," more flexible — peak delay plus long tail. Parameters: shape (k) and scale (lambda). Preferred for TV-like channels with delayed peak effects.",{"type":32,"tag":33,"props":188,"children":189},{},[190],{"type":32,"tag":76,"props":191,"children":192},{},[193],{"type":37,"value":194},"Geometric adstock formula:",{"type":32,"tag":82,"props":196,"children":198},{"code":197},"adstocked_t = spend_t + theta * adstocked_(t-1)\n",[199],{"type":32,"tag":87,"props":200,"children":201},{"__ignoreMap":16},[202],{"type":37,"value":197},{"type":32,"tag":33,"props":204,"children":205},{},[206],{"type":37,"value":207},"Robyn optimizes theta (or k, lambda) per channel via grid search. User specifies theta range in hyperparameters.json (e.g., 0–0.7), model finds best theta.",{"type":32,"tag":33,"props":209,"children":210},{},[211],{"type":32,"tag":76,"props":212,"children":213},{},[214],{"type":37,"value":215},"What you configure:",{"type":32,"tag":82,"props":217,"children":221},{"code":218,"language":219,"meta":16,"className":220,"style":16},"hyperparameters \u003C- list(\n  google_ads_S = c(0.3, 3),      # adstock theta range\n  google_ads_alphas = c(0.5, 3), # saturation alpha range\n  facebook_ads_S = c(0.1, 2),\n  facebook_ads_alphas = c(1, 5)\n)\n","r","language-r shiki shiki-themes github-dark",[222],{"type":32,"tag":87,"props":223,"children":224},{"__ignoreMap":16},[225,236,245,254,263,272],{"type":32,"tag":226,"props":227,"children":230},"span",{"class":228,"line":229},"line",1,[231],{"type":32,"tag":226,"props":232,"children":233},{},[234],{"type":37,"value":235},"hyperparameters \u003C- list(\n",{"type":32,"tag":226,"props":237,"children":239},{"class":228,"line":238},2,[240],{"type":32,"tag":226,"props":241,"children":242},{},[243],{"type":37,"value":244},"  google_ads_S = c(0.3, 3),      # adstock theta range\n",{"type":32,"tag":226,"props":246,"children":248},{"class":228,"line":247},3,[249],{"type":32,"tag":226,"props":250,"children":251},{},[252],{"type":37,"value":253},"  google_ads_alphas = c(0.5, 3), # saturation alpha range\n",{"type":32,"tag":226,"props":255,"children":257},{"class":228,"line":256},4,[258],{"type":32,"tag":226,"props":259,"children":260},{},[261],{"type":37,"value":262},"  facebook_ads_S = c(0.1, 2),\n",{"type":32,"tag":226,"props":264,"children":266},{"class":228,"line":265},5,[267],{"type":32,"tag":226,"props":268,"children":269},{},[270],{"type":37,"value":271},"  facebook_ads_alphas = c(1, 5)\n",{"type":32,"tag":226,"props":273,"children":275},{"class":228,"line":274},6,[276],{"type":32,"tag":226,"props":277,"children":278},{},[279],{"type":37,"value":280},")\n",{"type":32,"tag":33,"props":282,"children":283},{},[284],{"type":37,"value":285},"Result: Google Ads theta = 0.4, Facebook = 0.2 means Google effect persists longer. Budget planner accounts for this — one-quarter of Google spend still works 2 weeks out; Facebook's effect ends in 1 week.",{"type":32,"tag":287,"props":288,"children":290},"h3",{"id":289},"code-block-simple-adstock-transformation-r",[291],{"type":37,"value":292},"Code Block: Simple Adstock Transformation (R)",{"type":32,"tag":82,"props":294,"children":296},{"code":295,"language":219,"meta":16,"className":220,"style":16},"apply_geometric_adstock \u003C- function(spend, theta) {\n  adstocked \u003C- numeric(length(spend))\n  adstocked[1] \u003C- spend[1]\n  for (t in 2:length(spend)) {\n    adstocked[t] \u003C- spend[t] + theta * adstocked[t - 1]\n  }\n  return(adstocked)\n}\n\n# Example: Google Ads spend\ngoogle_spend \u003C- c(10000, 15000, 12000, 8000, 20000)\ntheta_google \u003C- 0.5\nadstocked_google \u003C- apply_geometric_adstock(google_spend, theta_google)\nprint(adstocked_google)\n# [1] 10000.0 20000.0 22000.0 19000.0 29500.0\n",[297],{"type":32,"tag":87,"props":298,"children":299},{"__ignoreMap":16},[300,308,316,324,332,340,348,357,365,375,384,393,402,411,420],{"type":32,"tag":226,"props":301,"children":302},{"class":228,"line":229},[303],{"type":32,"tag":226,"props":304,"children":305},{},[306],{"type":37,"value":307},"apply_geometric_adstock \u003C- function(spend, theta) {\n",{"type":32,"tag":226,"props":309,"children":310},{"class":228,"line":238},[311],{"type":32,"tag":226,"props":312,"children":313},{},[314],{"type":37,"value":315},"  adstocked \u003C- numeric(length(spend))\n",{"type":32,"tag":226,"props":317,"children":318},{"class":228,"line":247},[319],{"type":32,"tag":226,"props":320,"children":321},{},[322],{"type":37,"value":323},"  adstocked[1] \u003C- spend[1]\n",{"type":32,"tag":226,"props":325,"children":326},{"class":228,"line":256},[327],{"type":32,"tag":226,"props":328,"children":329},{},[330],{"type":37,"value":331},"  for (t in 2:length(spend)) {\n",{"type":32,"tag":226,"props":333,"children":334},{"class":228,"line":265},[335],{"type":32,"tag":226,"props":336,"children":337},{},[338],{"type":37,"value":339},"    adstocked[t] \u003C- spend[t] + theta * adstocked[t - 1]\n",{"type":32,"tag":226,"props":341,"children":342},{"class":228,"line":274},[343],{"type":32,"tag":226,"props":344,"children":345},{},[346],{"type":37,"value":347},"  }\n",{"type":32,"tag":226,"props":349,"children":351},{"class":228,"line":350},7,[352],{"type":32,"tag":226,"props":353,"children":354},{},[355],{"type":37,"value":356},"  return(adstocked)\n",{"type":32,"tag":226,"props":358,"children":359},{"class":228,"line":26},[360],{"type":32,"tag":226,"props":361,"children":362},{},[363],{"type":37,"value":364},"}\n",{"type":32,"tag":226,"props":366,"children":368},{"class":228,"line":367},9,[369],{"type":32,"tag":226,"props":370,"children":372},{"emptyLinePlaceholder":371},true,[373],{"type":37,"value":374},"\n",{"type":32,"tag":226,"props":376,"children":378},{"class":228,"line":377},10,[379],{"type":32,"tag":226,"props":380,"children":381},{},[382],{"type":37,"value":383},"# Example: Google Ads spend\n",{"type":32,"tag":226,"props":385,"children":387},{"class":228,"line":386},11,[388],{"type":32,"tag":226,"props":389,"children":390},{},[391],{"type":37,"value":392},"google_spend \u003C- c(10000, 15000, 12000, 8000, 20000)\n",{"type":32,"tag":226,"props":394,"children":396},{"class":228,"line":395},12,[397],{"type":32,"tag":226,"props":398,"children":399},{},[400],{"type":37,"value":401},"theta_google \u003C- 0.5\n",{"type":32,"tag":226,"props":403,"children":405},{"class":228,"line":404},13,[406],{"type":32,"tag":226,"props":407,"children":408},{},[409],{"type":37,"value":410},"adstocked_google \u003C- apply_geometric_adstock(google_spend, theta_google)\n",{"type":32,"tag":226,"props":412,"children":414},{"class":228,"line":413},14,[415],{"type":32,"tag":226,"props":416,"children":417},{},[418],{"type":37,"value":419},"print(adstocked_google)\n",{"type":32,"tag":226,"props":421,"children":423},{"class":228,"line":422},15,[424],{"type":32,"tag":226,"props":425,"children":426},{},[427],{"type":37,"value":428},"# [1] 10000.0 20000.0 22000.0 19000.0 29500.0\n",{"type":32,"tag":33,"props":430,"children":431},{},[432],{"type":37,"value":433},"Inside Robyn, this logic runs C++-optimized, but the principle is identical.",{"type":32,"tag":40,"props":435,"children":437},{"id":436},"holdout-validation-model-reliability-test",[438],{"type":37,"value":439},"Holdout Validation: Model Reliability Test",{"type":32,"tag":33,"props":441,"children":442},{},[443],{"type":37,"value":444},"Robyn risks overfitting while improving model fit. 10 channels + 5 macro variables + saturation and adstock parameters per channel → 30+ degrees of freedom. On 104 data points, that's excessive freedom.",{"type":32,"tag":33,"props":446,"children":447},{},[448],{"type":37,"value":449},"Robyn uses holdout validation: excludes final N weeks from training, model learns from past data, predicts on holdout period, compares to actual values via MAPE (mean absolute percentage error).",{"type":32,"tag":33,"props":451,"children":452},{},[453],{"type":32,"tag":76,"props":454,"children":455},{},[456],{"type":37,"value":457},"Holdout definition in Robyn:",{"type":32,"tag":82,"props":459,"children":461},{"code":460,"language":219,"meta":16,"className":220,"style":16},"InputCollect \u003C- robyn_inputs(\n  dt_input = df_marketing,\n  dep_var = \"revenue\",\n  paid_media_spends = c(\"google_ads\", \"facebook_ads\", \"tiktok_ads\"),\n  window_start = \"2024-01-01\",\n  window_end = \"2026-04-30\",\n  adstock = \"geometric\",\n  prophet_vars = c(\"trend\", \"season\", \"holiday\"),\n  prophet_country = \"US\"\n)\n\n# Holdout: final 8 weeks\nOutputModels \u003C- robyn_run(\n  InputCollect = InputCollect,\n  iterations = 2000,\n  trials = 5,\n  ts_validation = TRUE,\n  ts_holdout = 8  # final 8 weeks as test set\n)\n",[462],{"type":32,"tag":87,"props":463,"children":464},{"__ignoreMap":16},[465,473,481,489,497,505,513,521,529,537,544,551,559,567,575,583,592,601,610],{"type":32,"tag":226,"props":466,"children":467},{"class":228,"line":229},[468],{"type":32,"tag":226,"props":469,"children":470},{},[471],{"type":37,"value":472},"InputCollect \u003C- robyn_inputs(\n",{"type":32,"tag":226,"props":474,"children":475},{"class":228,"line":238},[476],{"type":32,"tag":226,"props":477,"children":478},{},[479],{"type":37,"value":480},"  dt_input = df_marketing,\n",{"type":32,"tag":226,"props":482,"children":483},{"class":228,"line":247},[484],{"type":32,"tag":226,"props":485,"children":486},{},[487],{"type":37,"value":488},"  dep_var = \"revenue\",\n",{"type":32,"tag":226,"props":490,"children":491},{"class":228,"line":256},[492],{"type":32,"tag":226,"props":493,"children":494},{},[495],{"type":37,"value":496},"  paid_media_spends = c(\"google_ads\", \"facebook_ads\", \"tiktok_ads\"),\n",{"type":32,"tag":226,"props":498,"children":499},{"class":228,"line":265},[500],{"type":32,"tag":226,"props":501,"children":502},{},[503],{"type":37,"value":504},"  window_start = \"2024-01-01\",\n",{"type":32,"tag":226,"props":506,"children":507},{"class":228,"line":274},[508],{"type":32,"tag":226,"props":509,"children":510},{},[511],{"type":37,"value":512},"  window_end = \"2026-04-30\",\n",{"type":32,"tag":226,"props":514,"children":515},{"class":228,"line":350},[516],{"type":32,"tag":226,"props":517,"children":518},{},[519],{"type":37,"value":520},"  adstock = \"geometric\",\n",{"type":32,"tag":226,"props":522,"children":523},{"class":228,"line":26},[524],{"type":32,"tag":226,"props":525,"children":526},{},[527],{"type":37,"value":528},"  prophet_vars = c(\"trend\", \"season\", \"holiday\"),\n",{"type":32,"tag":226,"props":530,"children":531},{"class":228,"line":367},[532],{"type":32,"tag":226,"props":533,"children":534},{},[535],{"type":37,"value":536},"  prophet_country = \"US\"\n",{"type":32,"tag":226,"props":538,"children":539},{"class":228,"line":377},[540],{"type":32,"tag":226,"props":541,"children":542},{},[543],{"type":37,"value":280},{"type":32,"tag":226,"props":545,"children":546},{"class":228,"line":386},[547],{"type":32,"tag":226,"props":548,"children":549},{"emptyLinePlaceholder":371},[550],{"type":37,"value":374},{"type":32,"tag":226,"props":552,"children":553},{"class":228,"line":395},[554],{"type":32,"tag":226,"props":555,"children":556},{},[557],{"type":37,"value":558},"# Holdout: final 8 weeks\n",{"type":32,"tag":226,"props":560,"children":561},{"class":228,"line":404},[562],{"type":32,"tag":226,"props":563,"children":564},{},[565],{"type":37,"value":566},"OutputModels \u003C- robyn_run(\n",{"type":32,"tag":226,"props":568,"children":569},{"class":228,"line":413},[570],{"type":32,"tag":226,"props":571,"children":572},{},[573],{"type":37,"value":574},"  InputCollect = InputCollect,\n",{"type":32,"tag":226,"props":576,"children":577},{"class":228,"line":422},[578],{"type":32,"tag":226,"props":579,"children":580},{},[581],{"type":37,"value":582},"  iterations = 2000,\n",{"type":32,"tag":226,"props":584,"children":586},{"class":228,"line":585},16,[587],{"type":32,"tag":226,"props":588,"children":589},{},[590],{"type":37,"value":591},"  trials = 5,\n",{"type":32,"tag":226,"props":593,"children":595},{"class":228,"line":594},17,[596],{"type":32,"tag":226,"props":597,"children":598},{},[599],{"type":37,"value":600},"  ts_validation = TRUE,\n",{"type":32,"tag":226,"props":602,"children":604},{"class":228,"line":603},18,[605],{"type":32,"tag":226,"props":606,"children":607},{},[608],{"type":37,"value":609},"  ts_holdout = 8  # final 8 weeks as test set\n",{"type":32,"tag":226,"props":611,"children":613},{"class":228,"line":612},19,[614],{"type":32,"tag":226,"props":615,"children":616},{},[617],{"type":37,"value":280},{"type":32,"tag":33,"props":619,"children":620},{},[621],{"type":32,"tag":76,"props":622,"children":623},{},[624],{"type":37,"value":625},"Result interpretation:",{"type":32,"tag":92,"props":627,"children":628},{},[629,634,639],{"type":32,"tag":96,"props":630,"children":631},{},[632],{"type":37,"value":633},"NRMSE train \u003C 0.10, NRMSE holdout \u003C 0.15 → model reliable.",{"type":32,"tag":96,"props":635,"children":636},{},[637],{"type":37,"value":638},"NRMSE train = 0.05, holdout = 0.30 → overfit; narrow hyperparameter range.",{"type":32,"tag":96,"props":640,"children":641},{},[642],{"type":37,"value":643},"Decomp.RSSD (response sum of squared differences): what fraction of revenue's variance channels explain. 0.6+ good, 0.8+ excellent.",{"type":32,"tag":33,"props":645,"children":646},{},[647],{"type":37,"value":648},"Robyn runs 5 trials simultaneously (Nevergrad's different random seeds), 2000 iterations per trial, surfaces top 10 models on Pareto frontier. User selects one model based on business constraints (e.g., \"Google ROAS must stay above 3\").",{"type":32,"tag":40,"props":650,"children":652},{"id":651},"robyn-on-bigquery-pipeline-architecture",[653],{"type":37,"value":654},"Robyn on BigQuery: Pipeline Architecture",{"type":32,"tag":33,"props":656,"children":657},{},[658],{"type":37,"value":659},"Robyn runs in R but sources data from BigQuery. Typical stack:",{"type":32,"tag":164,"props":661,"children":662},{},[663,673,683,693],{"type":32,"tag":96,"props":664,"children":665},{},[666,671],{"type":32,"tag":76,"props":667,"children":668},{},[669],{"type":37,"value":670},"BigQuery data warehouse:",{"type":37,"value":672}," daily spend table (spend_daily), conversion table (conversions_daily), macro variables (holidays, weather, competitor pricing).",{"type":32,"tag":96,"props":674,"children":675},{},[676,681],{"type":32,"tag":76,"props":677,"children":678},{},[679],{"type":37,"value":680},"dbt transformation:",{"type":37,"value":682}," join and aggregate. Convert to weekly rows, create channel spend columns.",{"type":32,"tag":96,"props":684,"children":685},{},[686,691],{"type":32,"tag":76,"props":687,"children":688},{},[689],{"type":37,"value":690},"R script (Cloud Run or Vertex AI):",{"type":37,"value":692}," fetch from BigQuery via bigrquery, feed to Robyn, write model output back to BigQuery.",{"type":32,"tag":96,"props":694,"children":695},{},[696,701],{"type":32,"tag":76,"props":697,"children":698},{},[699],{"type":37,"value":700},"Looker Studio dashboard:",{"type":37,"value":702}," visualize model output — channel ROAS, optimal budget split, saturation charts.",{"type":32,"tag":33,"props":704,"children":705},{},[706],{"type":32,"tag":76,"props":707,"children":708},{},[709],{"type":37,"value":710},"dbt model example (marketing_mix_weekly.sql):",{"type":32,"tag":82,"props":712,"children":716},{"code":713,"language":714,"meta":16,"className":715,"style":16},"WITH spend_agg AS (\n  SELECT\n    DATE_TRUNC(spend_date, WEEK) AS week_start,\n    SUM(CASE WHEN channel = 'google_ads' THEN spend ELSE 0 END) AS google_ads_spend,\n    SUM(CASE WHEN channel = 'facebook_ads' THEN spend ELSE 0 END) AS facebook_ads_spend,\n    SUM(CASE WHEN channel = 'tiktok_ads' THEN spend ELSE 0 END) AS tiktok_ads_spend\n  FROM `project.dataset.spend_daily`\n  WHERE spend_date BETWEEN '2024-01-01' AND '2026-04-30'\n  GROUP BY 1\n),\nrevenue_agg AS (\n  SELECT\n    DATE_TRUNC(conversion_date, WEEK) AS week_start,\n    SUM(revenue) AS total_revenue\n  FROM `project.dataset.conversions_daily`\n  WHERE conversion_date BETWEEN '2024-01-01' AND '2026-04-30'\n  GROUP BY 1\n)\nSELECT\n  s.week_start,\n  s.google_ads_spend,\n  s.facebook_ads_spend,\n  s.tiktok_ads_spend,\n  r.total_revenue\nFROM spend_agg s\nLEFT JOIN revenue_agg r USING (week_start)\nORDER BY week_start\n","sql","language-sql shiki shiki-themes github-dark",[717],{"type":32,"tag":87,"props":718,"children":719},{"__ignoreMap":16},[720,745,753,780,858,923,988,1001,1034,1047,1055,1071,1078,1102,1123,1135,1163,1174,1181,1189,1213,1234,1255,1276,1294,1308,1332],{"type":32,"tag":226,"props":721,"children":722},{"class":228,"line":229},[723,729,735,740],{"type":32,"tag":226,"props":724,"children":726},{"style":725},"--shiki-default:#F97583",[727],{"type":37,"value":728},"WITH",{"type":32,"tag":226,"props":730,"children":732},{"style":731},"--shiki-default:#E1E4E8",[733],{"type":37,"value":734}," spend_agg ",{"type":32,"tag":226,"props":736,"children":737},{"style":725},[738],{"type":37,"value":739},"AS",{"type":32,"tag":226,"props":741,"children":742},{"style":731},[743],{"type":37,"value":744}," (\n",{"type":32,"tag":226,"props":746,"children":747},{"class":228,"line":238},[748],{"type":32,"tag":226,"props":749,"children":750},{"style":725},[751],{"type":37,"value":752},"  SELECT\n",{"type":32,"tag":226,"props":754,"children":755},{"class":228,"line":247},[756,761,766,771,775],{"type":32,"tag":226,"props":757,"children":758},{"style":731},[759],{"type":37,"value":760},"    DATE_TRUNC(spend_date, ",{"type":32,"tag":226,"props":762,"children":763},{"style":725},[764],{"type":37,"value":765},"WEEK",{"type":32,"tag":226,"props":767,"children":768},{"style":731},[769],{"type":37,"value":770},") ",{"type":32,"tag":226,"props":772,"children":773},{"style":725},[774],{"type":37,"value":739},{"type":32,"tag":226,"props":776,"children":777},{"style":731},[778],{"type":37,"value":779}," week_start,\n",{"type":32,"tag":226,"props":781,"children":782},{"class":228,"line":256},[783,789,794,799,804,809,814,820,825,830,835,840,845,849,853],{"type":32,"tag":226,"props":784,"children":786},{"style":785},"--shiki-default:#79B8FF",[787],{"type":37,"value":788},"    SUM",{"type":32,"tag":226,"props":790,"children":791},{"style":731},[792],{"type":37,"value":793},"(",{"type":32,"tag":226,"props":795,"children":796},{"style":725},[797],{"type":37,"value":798},"CASE",{"type":32,"tag":226,"props":800,"children":801},{"style":725},[802],{"type":37,"value":803}," WHEN",{"type":32,"tag":226,"props":805,"children":806},{"style":731},[807],{"type":37,"value":808}," channel ",{"type":32,"tag":226,"props":810,"children":811},{"style":725},[812],{"type":37,"value":813},"=",{"type":32,"tag":226,"props":815,"children":817},{"style":816},"--shiki-default:#9ECBFF",[818],{"type":37,"value":819}," 'google_ads'",{"type":32,"tag":226,"props":821,"children":822},{"style":725},[823],{"type":37,"value":824}," THEN",{"type":32,"tag":226,"props":826,"children":827},{"style":731},[828],{"type":37,"value":829}," spend ",{"type":32,"tag":226,"props":831,"children":832},{"style":725},[833],{"type":37,"value":834},"ELSE",{"type":32,"tag":226,"props":836,"children":837},{"style":785},[838],{"type":37,"value":839}," 0",{"type":32,"tag":226,"props":841,"children":842},{"style":725},[843],{"type":37,"value":844}," END",{"type":32,"tag":226,"props":846,"children":847},{"style":731},[848],{"type":37,"value":770},{"type":32,"tag":226,"props":850,"children":851},{"style":725},[852],{"type":37,"value":739},{"type":32,"tag":226,"props":854,"children":855},{"style":731},[856],{"type":37,"value":857}," google_ads_spend,\n",{"type":32,"tag":226,"props":859,"children":860},{"class":228,"line":265},[861,865,869,873,877,881,885,890,894,898,902,906,910,914,918],{"type":32,"tag":226,"props":862,"children":863},{"style":785},[864],{"type":37,"value":788},{"type":32,"tag":226,"props":866,"children":867},{"style":731},[868],{"type":37,"value":793},{"type":32,"tag":226,"props":870,"children":871},{"style":725},[872],{"type":37,"value":798},{"type":32,"tag":226,"props":874,"children":875},{"style":725},[876],{"type":37,"value":803},{"type":32,"tag":226,"props":878,"children":879},{"style":731},[880],{"type":37,"value":808},{"type":32,"tag":226,"props":882,"children":883},{"style":725},[884],{"type":37,"value":813},{"type":32,"tag":226,"props":886,"children":887},{"style":816},[888],{"type":37,"value":889}," 'facebook_ads'",{"type":32,"tag":226,"props":891,"children":892},{"style":725},[893],{"type":37,"value":824},{"type":32,"tag":226,"props":895,"children":896},{"style":731},[897],{"type":37,"value":829},{"type":32,"tag":226,"props":899,"children":900},{"style":725},[901],{"type":37,"value":834},{"type":32,"tag":226,"props":903,"children":904},{"style":785},[905],{"type":37,"value":839},{"type":32,"tag":226,"props":907,"children":908},{"style":725},[909],{"type":37,"value":844},{"type":32,"tag":226,"props":911,"children":912},{"style":731},[913],{"type":37,"value":770},{"type":32,"tag":226,"props":915,"children":916},{"style":725},[917],{"type":37,"value":739},{"type":32,"tag":226,"props":919,"children":920},{"style":731},[921],{"type":37,"value":922}," facebook_ads_spend,\n",{"type":32,"tag":226,"props":924,"children":925},{"class":228,"line":274},[926,930,934,938,942,946,950,955,959,963,967,971,975,979,983],{"type":32,"tag":226,"props":927,"children":928},{"style":785},[929],{"type":37,"value":788},{"type":32,"tag":226,"props":931,"children":932},{"style":731},[933],{"type":37,"value":793},{"type":32,"tag":226,"props":935,"children":936},{"style":725},[937],{"type":37,"value":798},{"type":32,"tag":226,"props":939,"children":940},{"style":725},[941],{"type":37,"value":803},{"type":32,"tag":226,"props":943,"children":944},{"style":731},[945],{"type":37,"value":808},{"type":32,"tag":226,"props":947,"children":948},{"style":725},[949],{"type":37,"value":813},{"type":32,"tag":226,"props":951,"children":952},{"style":816},[953],{"type":37,"value":954}," 'tiktok_ads'",{"type":32,"tag":226,"props":956,"children":957},{"style":725},[958],{"type":37,"value":824},{"type":32,"tag":226,"props":960,"children":961},{"style":731},[962],{"type":37,"value":829},{"type":32,"tag":226,"props":964,"children":965},{"style":725},[966],{"type":37,"value":834},{"type":32,"tag":226,"props":968,"children":969},{"style":785},[970],{"type":37,"value":839},{"type":32,"tag":226,"props":972,"children":973},{"style":725},[974],{"type":37,"value":844},{"type":32,"tag":226,"props":976,"children":977},{"style":731},[978],{"type":37,"value":770},{"type":32,"tag":226,"props":980,"children":981},{"style":725},[982],{"type":37,"value":739},{"type":32,"tag":226,"props":984,"children":985},{"style":731},[986],{"type":37,"value":987}," tiktok_ads_spend\n",{"type":32,"tag":226,"props":989,"children":990},{"class":228,"line":350},[991,996],{"type":32,"tag":226,"props":992,"children":993},{"style":725},[994],{"type":37,"value":995},"  FROM",{"type":32,"tag":226,"props":997,"children":998},{"style":816},[999],{"type":37,"value":1000}," `project.dataset.spend_daily`\n",{"type":32,"tag":226,"props":1002,"children":1003},{"class":228,"line":26},[1004,1009,1014,1019,1024,1029],{"type":32,"tag":226,"props":1005,"children":1006},{"style":725},[1007],{"type":37,"value":1008},"  WHERE",{"type":32,"tag":226,"props":1010,"children":1011},{"style":731},[1012],{"type":37,"value":1013}," spend_date ",{"type":32,"tag":226,"props":1015,"children":1016},{"style":725},[1017],{"type":37,"value":1018},"BETWEEN",{"type":32,"tag":226,"props":1020,"children":1021},{"style":816},[1022],{"type":37,"value":1023}," '2024-01-01'",{"type":32,"tag":226,"props":1025,"children":1026},{"style":725},[1027],{"type":37,"value":1028}," AND",{"type":32,"tag":226,"props":1030,"children":1031},{"style":816},[1032],{"type":37,"value":1033}," '2026-04-30'\n",{"type":32,"tag":226,"props":1035,"children":1036},{"class":228,"line":367},[1037,1042],{"type":32,"tag":226,"props":1038,"children":1039},{"style":725},[1040],{"type":37,"value":1041},"  GROUP BY",{"type":32,"tag":226,"props":1043,"children":1044},{"style":785},[1045],{"type":37,"value":1046}," 1\n",{"type":32,"tag":226,"props":1048,"children":1049},{"class":228,"line":377},[1050],{"type":32,"tag":226,"props":1051,"children":1052},{"style":731},[1053],{"type":37,"value":1054},"),\n",{"type":32,"tag":226,"props":1056,"children":1057},{"class":228,"line":386},[1058,1063,1067],{"type":32,"tag":226,"props":1059,"children":1060},{"style":731},[1061],{"type":37,"value":1062},"revenue_agg ",{"type":32,"tag":226,"props":1064,"children":1065},{"style":725},[1066],{"type":37,"value":739},{"type":32,"tag":226,"props":1068,"children":1069},{"style":731},[1070],{"type":37,"value":744},{"type":32,"tag":226,"props":1072,"children":1073},{"class":228,"line":395},[1074],{"type":32,"tag":226,"props":1075,"children":1076},{"style":725},[1077],{"type":37,"value":752},{"type":32,"tag":226,"props":1079,"children":1080},{"class":228,"line":404},[1081,1086,1090,1094,1098],{"type":32,"tag":226,"props":1082,"children":1083},{"style":731},[1084],{"type":37,"value":1085},"    DATE_TRUNC(conversion_date, ",{"type":32,"tag":226,"props":1087,"children":1088},{"style":725},[1089],{"type":37,"value":765},{"type":32,"tag":226,"props":1091,"children":1092},{"style":731},[1093],{"type":37,"value":770},{"type":32,"tag":226,"props":1095,"children":1096},{"style":725},[1097],{"type":37,"value":739},{"type":32,"tag":226,"props":1099,"children":1100},{"style":731},[1101],{"type":37,"value":779},{"type":32,"tag":226,"props":1103,"children":1104},{"class":228,"line":413},[1105,1109,1114,1118],{"type":32,"tag":226,"props":1106,"children":1107},{"style":785},[1108],{"type":37,"value":788},{"type":32,"tag":226,"props":1110,"children":1111},{"style":731},[1112],{"type":37,"value":1113},"(revenue) ",{"type":32,"tag":226,"props":1115,"children":1116},{"style":725},[1117],{"type":37,"value":739},{"type":32,"tag":226,"props":1119,"children":1120},{"style":731},[1121],{"type":37,"value":1122}," total_revenue\n",{"type":32,"tag":226,"props":1124,"children":1125},{"class":228,"line":422},[1126,1130],{"type":32,"tag":226,"props":1127,"children":1128},{"style":725},[1129],{"type":37,"value":995},{"type":32,"tag":226,"props":1131,"children":1132},{"style":816},[1133],{"type":37,"value":1134}," `project.dataset.conversions_daily`\n",{"type":32,"tag":226,"props":1136,"children":1137},{"class":228,"line":585},[1138,1142,1147,1151,1155,1159],{"type":32,"tag":226,"props":1139,"children":1140},{"style":725},[1141],{"type":37,"value":1008},{"type":32,"tag":226,"props":1143,"children":1144},{"style":731},[1145],{"type":37,"value":1146}," conversion_date ",{"type":32,"tag":226,"props":1148,"children":1149},{"style":725},[1150],{"type":37,"value":1018},{"type":32,"tag":226,"props":1152,"children":1153},{"style":816},[1154],{"type":37,"value":1023},{"type":32,"tag":226,"props":1156,"children":1157},{"style":725},[1158],{"type":37,"value":1028},{"type":32,"tag":226,"props":1160,"children":1161},{"style":816},[1162],{"type":37,"value":1033},{"type":32,"tag":226,"props":1164,"children":1165},{"class":228,"line":594},[1166,1170],{"type":32,"tag":226,"props":1167,"children":1168},{"style":725},[1169],{"type":37,"value":1041},{"type":32,"tag":226,"props":1171,"children":1172},{"style":785},[1173],{"type":37,"value":1046},{"type":32,"tag":226,"props":1175,"children":1176},{"class":228,"line":603},[1177],{"type":32,"tag":226,"props":1178,"children":1179},{"style":731},[1180],{"type":37,"value":280},{"type":32,"tag":226,"props":1182,"children":1183},{"class":228,"line":612},[1184],{"type":32,"tag":226,"props":1185,"children":1186},{"style":725},[1187],{"type":37,"value":1188},"SELECT\n",{"type":32,"tag":226,"props":1190,"children":1192},{"class":228,"line":1191},20,[1193,1198,1203,1208],{"type":32,"tag":226,"props":1194,"children":1195},{"style":785},[1196],{"type":37,"value":1197},"  s",{"type":32,"tag":226,"props":1199,"children":1200},{"style":731},[1201],{"type":37,"value":1202},".",{"type":32,"tag":226,"props":1204,"children":1205},{"style":785},[1206],{"type":37,"value":1207},"week_start",{"type":32,"tag":226,"props":1209,"children":1210},{"style":731},[1211],{"type":37,"value":1212},",\n",{"type":32,"tag":226,"props":1214,"children":1216},{"class":228,"line":1215},21,[1217,1221,1225,1230],{"type":32,"tag":226,"props":1218,"children":1219},{"style":785},[1220],{"type":37,"value":1197},{"type":32,"tag":226,"props":1222,"children":1223},{"style":731},[1224],{"type":37,"value":1202},{"type":32,"tag":226,"props":1226,"children":1227},{"style":785},[1228],{"type":37,"value":1229},"google_ads_spend",{"type":32,"tag":226,"props":1231,"children":1232},{"style":731},[1233],{"type":37,"value":1212},{"type":32,"tag":226,"props":1235,"children":1237},{"class":228,"line":1236},22,[1238,1242,1246,1251],{"type":32,"tag":226,"props":1239,"children":1240},{"style":785},[1241],{"type":37,"value":1197},{"type":32,"tag":226,"props":1243,"children":1244},{"style":731},[1245],{"type":37,"value":1202},{"type":32,"tag":226,"props":1247,"children":1248},{"style":785},[1249],{"type":37,"value":1250},"facebook_ads_spend",{"type":32,"tag":226,"props":1252,"children":1253},{"style":731},[1254],{"type":37,"value":1212},{"type":32,"tag":226,"props":1256,"children":1258},{"class":228,"line":1257},23,[1259,1263,1267,1272],{"type":32,"tag":226,"props":1260,"children":1261},{"style":785},[1262],{"type":37,"value":1197},{"type":32,"tag":226,"props":1264,"children":1265},{"style":731},[1266],{"type":37,"value":1202},{"type":32,"tag":226,"props":1268,"children":1269},{"style":785},[1270],{"type":37,"value":1271},"tiktok_ads_spend",{"type":32,"tag":226,"props":1273,"children":1274},{"style":731},[1275],{"type":37,"value":1212},{"type":32,"tag":226,"props":1277,"children":1279},{"class":228,"line":1278},24,[1280,1285,1289],{"type":32,"tag":226,"props":1281,"children":1282},{"style":785},[1283],{"type":37,"value":1284},"  r",{"type":32,"tag":226,"props":1286,"children":1287},{"style":731},[1288],{"type":37,"value":1202},{"type":32,"tag":226,"props":1290,"children":1291},{"style":785},[1292],{"type":37,"value":1293},"total_revenue\n",{"type":32,"tag":226,"props":1295,"children":1297},{"class":228,"line":1296},25,[1298,1303],{"type":32,"tag":226,"props":1299,"children":1300},{"style":725},[1301],{"type":37,"value":1302},"FROM",{"type":32,"tag":226,"props":1304,"children":1305},{"style":731},[1306],{"type":37,"value":1307}," spend_agg s\n",{"type":32,"tag":226,"props":1309,"children":1311},{"class":228,"line":1310},26,[1312,1317,1322,1327],{"type":32,"tag":226,"props":1313,"children":1314},{"style":725},[1315],{"type":37,"value":1316},"LEFT JOIN",{"type":32,"tag":226,"props":1318,"children":1319},{"style":731},[1320],{"type":37,"value":1321}," revenue_agg r ",{"type":32,"tag":226,"props":1323,"children":1324},{"style":725},[1325],{"type":37,"value":1326},"USING",{"type":32,"tag":226,"props":1328,"children":1329},{"style":731},[1330],{"type":37,"value":1331}," (week_start)\n",{"type":32,"tag":226,"props":1333,"children":1335},{"class":228,"line":1334},27,[1336,1341],{"type":32,"tag":226,"props":1337,"children":1338},{"style":725},[1339],{"type":37,"value":1340},"ORDER BY",{"type":32,"tag":226,"props":1342,"children":1343},{"style":731},[1344],{"type":37,"value":1345}," week_start\n",{"type":32,"tag":33,"props":1347,"children":1348},{},[1349,1351,1357],{"type":37,"value":1350},"This table is materialized in BigQuery; Robyn's R script fetches it via ",{"type":32,"tag":87,"props":1352,"children":1354},{"className":1353},[],[1355],{"type":37,"value":1356},"bigrquery::bq_table_download()",{"type":37,"value":1358},". Model output (weekly channel contribution) writes back to BigQuery — BI tools read from there.",{"type":32,"tag":40,"props":1360,"children":1362},{"id":1361},"budget-optimizer-pareto-optimal-allocation",[1363],{"type":37,"value":1364},"Budget Optimizer: Pareto-Optimal Allocation",{"type":32,"tag":33,"props":1366,"children":1367},{},[1368],{"type":37,"value":1369},"After model fit, Robyn runs a second module: budget allocator. Inputs: total budget (e.g., 500,000 units\u002Fweek), channel spend constraints (e.g., Google minimum 50,000). Output: optimal allocation maximizing ROAS.",{"type":32,"tag":33,"props":1371,"children":1372},{},[1373],{"type":37,"value":1374},"Algorithm: takes derivative of each channel's saturation curve (marginal ROAS), shifts spend until marginal ROAS equalizes across channels. This is Lagrange multiplier optimization.",{"type":32,"tag":33,"props":1376,"children":1377},{},[1378],{"type":32,"tag":76,"props":1379,"children":1380},{},[1381],{"type":37,"value":1382},"Sample output table:",{"type":32,"tag":1384,"props":1385,"children":1386},"table",{},[1387,1426],{"type":32,"tag":1388,"props":1389,"children":1390},"thead",{},[1391],{"type":32,"tag":1392,"props":1393,"children":1394},"tr",{},[1395,1401,1406,1411,1416,1421],{"type":32,"tag":1396,"props":1397,"children":1398},"th",{},[1399],{"type":37,"value":1400},"Channel",{"type":32,"tag":1396,"props":1402,"children":1403},{},[1404],{"type":37,"value":1405},"Current Spend",{"type":32,"tag":1396,"props":1407,"children":1408},{},[1409],{"type":37,"value":1410},"Optimal Spend",{"type":32,"tag":1396,"props":1412,"children":1413},{},[1414],{"type":37,"value":1415},"Delta",{"type":32,"tag":1396,"props":1417,"children":1418},{},[1419],{"type":37,"value":1420},"Current ROAS",{"type":32,"tag":1396,"props":1422,"children":1423},{},[1424],{"type":37,"value":1425},"Optimal ROAS",{"type":32,"tag":1427,"props":1428,"children":1429},"tbody",{},[1430,1464,1496,1529],{"type":32,"tag":1392,"props":1431,"children":1432},{},[1433,1439,1444,1449,1454,1459],{"type":32,"tag":1434,"props":1435,"children":1436},"td",{},[1437],{"type":37,"value":1438},"Google Ads",{"type":32,"tag":1434,"props":1440,"children":1441},{},[1442],{"type":37,"value":1443},"200,000",{"type":32,"tag":1434,"props":1445,"children":1446},{},[1447],{"type":37,"value":1448},"180,000",{"type":32,"tag":1434,"props":1450,"children":1451},{},[1452],{"type":37,"value":1453},"-20,000",{"type":32,"tag":1434,"props":1455,"children":1456},{},[1457],{"type":37,"value":1458},"4.2",{"type":32,"tag":1434,"props":1460,"children":1461},{},[1462],{"type":37,"value":1463},"4.5",{"type":32,"tag":1392,"props":1465,"children":1466},{},[1467,1472,1477,1481,1486,1491],{"type":32,"tag":1434,"props":1468,"children":1469},{},[1470],{"type":37,"value":1471},"Facebook Ads",{"type":32,"tag":1434,"props":1473,"children":1474},{},[1475],{"type":37,"value":1476},"150,000",{"type":32,"tag":1434,"props":1478,"children":1479},{},[1480],{"type":37,"value":1443},{"type":32,"tag":1434,"props":1482,"children":1483},{},[1484],{"type":37,"value":1485},"+50,000",{"type":32,"tag":1434,"props":1487,"children":1488},{},[1489],{"type":37,"value":1490},"3.8",{"type":32,"tag":1434,"props":1492,"children":1493},{},[1494],{"type":37,"value":1495},"4.1",{"type":32,"tag":1392,"props":1497,"children":1498},{},[1499,1504,1509,1514,1519,1524],{"type":32,"tag":1434,"props":1500,"children":1501},{},[1502],{"type":37,"value":1503},"TikTok Ads",{"type":32,"tag":1434,"props":1505,"children":1506},{},[1507],{"type":37,"value":1508},"100,000",{"type":32,"tag":1434,"props":1510,"children":1511},{},[1512],{"type":37,"value":1513},"120,000",{"type":32,"tag":1434,"props":1515,"children":1516},{},[1517],{"type":37,"value":1518},"+20,000",{"type":32,"tag":1434,"props":1520,"children":1521},{},[1522],{"type":37,"value":1523},"3.5",{"type":32,"tag":1434,"props":1525,"children":1526},{},[1527],{"type":37,"value":1528},"3.9",{"type":32,"tag":1392,"props":1530,"children":1531},{},[1532,1537,1542,1547,1552,1557],{"type":32,"tag":1434,"props":1533,"children":1534},{},[1535],{"type":37,"value":1536},"Display",{"type":32,"tag":1434,"props":1538,"children":1539},{},[1540],{"type":37,"value":1541},"50,000",{"type":32,"tag":1434,"props":1543,"children":1544},{},[1545],{"type":37,"value":1546},"0",{"type":32,"tag":1434,"props":1548,"children":1549},{},[1550],{"type":37,"value":1551},"-50,000",{"type":32,"tag":1434,"props":1553,"children":1554},{},[1555],{"type":37,"value":1556},"1.2",{"type":32,"tag":1434,"props":1558,"children":1559},{},[1560],{"type":37,"value":1561},"—",{"type":32,"tag":33,"props":1563,"children":1564},{},[1565],{"type":37,"value":1566},"Interpretation: Display channel returns 1.2 ROAS even well below saturation — eliminate it. Google already at saturation threshold; trim 20,000 to boost ROAS. Facebook remains on curve's linear slope; increased budget is efficient.",{"type":32,"tag":33,"props":1568,"children":1569},{},[1570],{"type":37,"value":1571},"This table reaches CFO; Robyn's SQL output appears in Looker visualization. Decision-making becomes data-driven — \"increase Facebook by 50,000 this month\" is now model output, not intuition.",{"type":32,"tag":1573,"props":1574,"children":1575},"hr",{},[],{"type":32,"tag":33,"props":1577,"children":1578},{},[1579,1581,1590],{"type":37,"value":1580},"Deploying Robyn requires 2 years of weekly granular data, R environment, BigQuery connection, and 4–6 hours of hyperparameter tuning. Once production, refresh monthly (add 4 new weeks, slide holdout window). Saturation curve and adstock parameters drift over time — holidays lower Facebook theta, Black Friday lifts Google Ads alpha. Robyn doesn't auto-capture this, but higher retrain frequency does. When ",{"type":32,"tag":1582,"props":1583,"children":1587},"a",{"href":1584,"rel":1585},"https:\u002F\u002Fwww.roibase.com.tr\u002Fen\u002Ffirstparty",[1586],"nofollow",[1588],{"type":37,"value":1589},"first-party data architecture",{"type":37,"value":1591}," is solid on BigQuery, Robyn sits atop it, operationalizing aggregate MMM. In the cookieless era, econometric models replace attribution as necessity — Robyn is the first open-source tool making that shift production-viable.",{"type":32,"tag":1593,"props":1594,"children":1595},"style",{},[1596],{"type":37,"value":1597},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":16,"searchDepth":247,"depth":247,"links":1599},[1600,1601,1602,1605,1606,1607],{"id":42,"depth":238,"text":45},{"id":63,"depth":238,"text":66},{"id":149,"depth":238,"text":152,"children":1603},[1604],{"id":289,"depth":247,"text":292},{"id":436,"depth":238,"text":439},{"id":651,"depth":238,"text":654},{"id":1361,"depth":238,"text":1364},"markdown","content:en:data:marketing-mix-modeling-robyn-practical-setup.md","content","en\u002Fdata\u002Fmarketing-mix-modeling-robyn-practical-setup.md","en\u002Fdata\u002Fmarketing-mix-modeling-robyn-practical-setup","md",1778997828780]