[{"data":1,"prerenderedAt":1044},["ShallowReactive",2],{"article-alternates":3,"article-\u002Fit\u002Fdata\u002Frobyn-marketing-mix-modeling-setup-pratico":13},{"i18nKey":4,"paths":5},"data-005-2026-06",{"de":6,"en":7,"es":8,"fr":9,"it":10,"ru":11,"tr":12},"\u002Fde\u002Fdata\u002Fmarketing-mix-modeling-robyn-praktische-einrichtung","\u002Fen\u002Fdata\u002Fmarketing-mix-modeling-practical-setup-with-robyn","\u002Fes\u002Fdata\u002Fmarketing-mix-modeling-robyn-setup-practico","\u002Ffr\u002Fdata\u002Frobyn-marketing-mix-modeling-guide","\u002Fit\u002Fdata\u002Frobyn-marketing-mix-modeling-setup-pratico","\u002Fru\u002Fdata\u002Fmarketing-mix-modeling-robyn-prakticheskaya-setup","\u002Ftr\u002Fdata\u002Fmarketing-mix-modeling-robyn-ile-pratik-kurulum",{"_path":10,"_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":1038,"_id":1039,"_source":1040,"_file":1041,"_stem":1042,"_extension":1043},"data",false,"","Marketing Mix Modeling: Configurazione Pratica con Robyn","Framework MMM open-source di Meta Robyn: configurare saturazione, adstock e holdout validation con codice R e struttura dati corretta.","2026-06-05",[21,22,23,24,25],"marketing-mix-modeling","robyn","adstock","saturation-curve","incrementality",8,"Roibase",{"type":29,"children":30,"toc":1030},"root",[31,47,54,59,98,110,116,121,232,240,307,320,344,350,362,370,391,396,404,422,516,521,527,547,748,760,765,819,824,830,856,869,938,950,956,975,995,1007,1019,1024],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36,39,45],{"type":37,"value":38},"text","Nel mondo della misurazione post-cookie, l'attribution perde segnale ogni giorno. Con iOS 17.4 e persino SKAdNetwork che fatica a mostrare il vero ROAS, i proprietari di budget di marketing si rivolgono ai modelli econometrici per misurare il vero contributo dei canali. Il Marketing Mix Modeling (MMM), metodo statistico sviluppato negli anni Sessanta per la pubblicità televisiva, nel 2026 ritorna al centro insieme a server-side measurement e first-party data lake. ",{"type":32,"tag":40,"props":41,"children":42},"strong",{},[43],{"type":37,"value":44},"Robyn",{"type":37,"value":46},", rilasciato da Meta come open-source nel 2021, ha accelerato l'applicazione di questa metodologia basata su regressione aggiungendo machine learning moderno e ottimizzazione bayesiana.",{"type":32,"tag":48,"props":49,"children":51},"h2",{"id":50},"perché-mmm-è-critico-adesso",[52],{"type":37,"value":53},"Perché MMM è critico adesso",{"type":32,"tag":33,"props":55,"children":56},{},[57],{"type":37,"value":58},"Mentre il modello di last-click attribution crolla con la perdita dei cookie, anche l'attribution multi-touch (MTA) diventa inutilizzabile dopo GDPR e ATT perché richiede dati a livello di evento. L'attribution data-driven di Google Analytics 4 si basa sul machine learning ma funziona solo nell'ecosistema Google. Tuttavia, il 60% del budget di marketing rimane fuori da Google: Meta, TikTok, display programmatico, TV offline, sponsorizzazioni.",{"type":32,"tag":33,"props":60,"children":61},{},[62,64,69,71,76,78,82,84,89,91,96],{"type":37,"value":63},"MMM si basa su dati ",{"type":32,"tag":40,"props":65,"children":66},{},[67],{"type":37,"value":68},"aggregati",{"type":37,"value":70}," settimanali o giornalieri invece del tracking a livello utente. Il modello di regressione estrae la relazione tra la spesa di ogni canale e le vendite (o conversioni). Il modello poggia su due assunzioni fondamentali: ",{"type":32,"tag":40,"props":72,"children":73},{},[74],{"type":37,"value":75},"saturazione",{"type":37,"value":77}," (maggiore spesa produce rendimenti marginali decrescenti) e ",{"type":32,"tag":40,"props":79,"children":80},{},[81],{"type":37,"value":23},{"type":37,"value":83}," (la pubblicità di oggi impatta le prossime settimane). Queste assunzioni sono statistiche ma riflettono la realtà commerciale. Robyn mira a trovare automaticamente questi due parametri attraverso ottimizzazione bayesiana degli iperparametri. Dalle versioni 2024 in poi (v3.11+), l'aggiunta di ",{"type":32,"tag":40,"props":85,"children":86},{},[87],{"type":37,"value":88},"ridge regression",{"type":37,"value":90}," e ",{"type":32,"tag":40,"props":92,"children":93},{},[94],{"type":37,"value":95},"decomposizione time-series con Prophet",{"type":37,"value":97}," ha aumentato l'accuratezza stagionale del modello.",{"type":32,"tag":33,"props":99,"children":100},{},[101,103,108],{"type":37,"value":102},"Un'altra caratteristica critica di Robyn è la ",{"type":32,"tag":40,"props":104,"children":105},{},[106],{"type":37,"value":107},"holdout validation",{"type":37,"value":109},": addestra il modello con i dati passati di 12 settimane e prevede le successive 4 settimane per misurare l'errore fuori campione. Questo previene l'overfitting e dimostra che il modello apprende veramente i canali. Le soluzioni MMM di Google (Meridian) e Facebook usano approcci simili ma sono closed-source e costose. Robyn offre accesso gratuito alla stessa metodologia.",{"type":32,"tag":48,"props":111,"children":113},{"id":112},"struttura-dati-e-preparazione",[114],{"type":37,"value":115},"Struttura dati e preparazione",{"type":32,"tag":33,"props":117,"children":118},{},[119],{"type":37,"value":120},"Per eseguire Robyn, il formato dati richiesto è: ogni riga è un'unità di tempo (giorno o settimana), ogni colonna è la spesa di un canale o una metrica di conversione. Si consigliano minimo 104 settimane (2 anni) perché l'importanza statistica dei coefficienti di regressione dipende dalla dimensione del campione. Con meno di 52 settimane avrai problemi di convergenza del modello.",{"type":32,"tag":122,"props":123,"children":127},"pre",{"code":124,"language":125,"meta":16,"className":126,"style":16},"# Esempio di struttura dati — aggregato settimanale estratto da BigQuery\ndf \u003C- data.frame(\n  DATE = seq.Date(from = as.Date(\"2024-01-01\"), by = \"week\", length.out = 104),\n  revenue = runif(104, 80000, 150000),\n  google_search_spend = runif(104, 5000, 15000),\n  meta_spend = runif(104, 8000, 20000),\n  tiktok_spend = runif(104, 2000, 8000),\n  tv_grp = runif(104, 50, 200),\n  organic_sessions = runif(104, 10000, 30000),\n  competitor_index = runif(104, 0.8, 1.2)\n)\n","r","language-r shiki shiki-themes github-dark",[128],{"type":32,"tag":129,"props":130,"children":131},"code",{"__ignoreMap":16},[132,143,152,161,170,179,188,197,205,214,223],{"type":32,"tag":133,"props":134,"children":137},"span",{"class":135,"line":136},"line",1,[138],{"type":32,"tag":133,"props":139,"children":140},{},[141],{"type":37,"value":142},"# Esempio di struttura dati — aggregato settimanale estratto da BigQuery\n",{"type":32,"tag":133,"props":144,"children":146},{"class":135,"line":145},2,[147],{"type":32,"tag":133,"props":148,"children":149},{},[150],{"type":37,"value":151},"df \u003C- data.frame(\n",{"type":32,"tag":133,"props":153,"children":155},{"class":135,"line":154},3,[156],{"type":32,"tag":133,"props":157,"children":158},{},[159],{"type":37,"value":160},"  DATE = seq.Date(from = as.Date(\"2024-01-01\"), by = \"week\", length.out = 104),\n",{"type":32,"tag":133,"props":162,"children":164},{"class":135,"line":163},4,[165],{"type":32,"tag":133,"props":166,"children":167},{},[168],{"type":37,"value":169},"  revenue = runif(104, 80000, 150000),\n",{"type":32,"tag":133,"props":171,"children":173},{"class":135,"line":172},5,[174],{"type":32,"tag":133,"props":175,"children":176},{},[177],{"type":37,"value":178},"  google_search_spend = runif(104, 5000, 15000),\n",{"type":32,"tag":133,"props":180,"children":182},{"class":135,"line":181},6,[183],{"type":32,"tag":133,"props":184,"children":185},{},[186],{"type":37,"value":187},"  meta_spend = runif(104, 8000, 20000),\n",{"type":32,"tag":133,"props":189,"children":191},{"class":135,"line":190},7,[192],{"type":32,"tag":133,"props":193,"children":194},{},[195],{"type":37,"value":196},"  tiktok_spend = runif(104, 2000, 8000),\n",{"type":32,"tag":133,"props":198,"children":199},{"class":135,"line":26},[200],{"type":32,"tag":133,"props":201,"children":202},{},[203],{"type":37,"value":204},"  tv_grp = runif(104, 50, 200),\n",{"type":32,"tag":133,"props":206,"children":208},{"class":135,"line":207},9,[209],{"type":32,"tag":133,"props":210,"children":211},{},[212],{"type":37,"value":213},"  organic_sessions = runif(104, 10000, 30000),\n",{"type":32,"tag":133,"props":215,"children":217},{"class":135,"line":216},10,[218],{"type":32,"tag":133,"props":219,"children":220},{},[221],{"type":37,"value":222},"  competitor_index = runif(104, 0.8, 1.2)\n",{"type":32,"tag":133,"props":224,"children":226},{"class":135,"line":225},11,[227],{"type":32,"tag":133,"props":228,"children":229},{},[230],{"type":37,"value":231},")\n",{"type":32,"tag":33,"props":233,"children":234},{},[235],{"type":32,"tag":40,"props":236,"children":237},{},[238],{"type":37,"value":239},"Dettagli importanti:",{"type":32,"tag":241,"props":242,"children":243},"ul",{},[244,258,263,275,302],{"type":32,"tag":245,"props":246,"children":247},"li",{},[248,250,256],{"type":37,"value":249},"La colonna ",{"type":32,"tag":129,"props":251,"children":253},{"className":252},[],[254],{"type":37,"value":255},"DATE",{"type":37,"value":257}," deve essere di classe Date, non stringa",{"type":32,"tag":245,"props":259,"children":260},{},[261],{"type":37,"value":262},"Revenue o conversion entra nel modello come variabile target (variabile dipendente)",{"type":32,"tag":245,"props":264,"children":265},{},[266,268,273],{"type":37,"value":267},"I canali (google_search_spend, meta_spend) sono colonne di ",{"type":32,"tag":40,"props":269,"children":270},{},[271],{"type":37,"value":272},"paid media",{"type":37,"value":274}," — a questi si applica adstock e saturazione",{"type":32,"tag":245,"props":276,"children":277},{},[278,280,286,287,293,295,300],{"type":37,"value":279},"Variabili come ",{"type":32,"tag":129,"props":281,"children":283},{"className":282},[],[284],{"type":37,"value":285},"organic_sessions",{"type":37,"value":90},{"type":32,"tag":129,"props":288,"children":290},{"className":289},[],[291],{"type":37,"value":292},"competitor_index",{"type":37,"value":294}," sono ",{"type":32,"tag":40,"props":296,"children":297},{},[298],{"type":37,"value":299},"variabili organiche \u002F di controllo",{"type":37,"value":301}," — non viene applicata la trasformazione, sono usate per dedurre il baseline",{"type":32,"tag":245,"props":303,"children":304},{},[305],{"type":37,"value":306},"Se hai dati di canali offline come TV, normalizza come GRP, reach o minuti visualizzati",{"type":32,"tag":33,"props":308,"children":309},{},[310,312,318],{"type":37,"value":311},"Robyn non funziona con etichette manuali come \"facebook_spend\"; tu definisci i nomi delle colonne ma devi specificare esplicitamente nella funzione ",{"type":32,"tag":129,"props":313,"children":315},{"className":314},[],[316],{"type":37,"value":317},"InputCollect()",{"type":37,"value":319}," quali colonne sono paid e quali organiche.",{"type":32,"tag":33,"props":321,"children":322},{},[323,325,334,336,342],{"type":37,"value":324},"Se non hai ",{"type":32,"tag":326,"props":327,"children":331},"a",{"href":328,"rel":329},"https:\u002F\u002Fwww.roibase.com.tr\u002Fit\u002Ffirstparty",[330],"nofollow",[332],{"type":37,"value":333},"costruito un'architettura di dati first-party",{"type":37,"value":335},", raccogliere questi dati è difficile. Server-side GTM, esportazione raw GA4, API di Meta \u002F Google Ads, dati di vendita da CRM — devi unirli tutti in BigQuery e fare il rollup settimanale. Quando costruiamo questa pipeline ETL con dbt, produciamo una tabella ",{"type":32,"tag":129,"props":337,"children":339},{"className":338},[],[340],{"type":37,"value":341},"fact_marketing_weekly",{"type":37,"value":343}," pronta per MMM.",{"type":32,"tag":48,"props":345,"children":347},{"id":346},"configurazione-di-saturazione-e-adstock",[348],{"type":37,"value":349},"Configurazione di saturazione e adstock",{"type":32,"tag":33,"props":351,"children":352},{},[353,355,360],{"type":37,"value":354},"La forza di Robyn è poter ottimizzare ",{"type":32,"tag":40,"props":356,"children":357},{},[358],{"type":37,"value":359},"separatamente",{"type":37,"value":361}," la curva di saturazione e i parametri di adstock decay per ogni canale. La saturazione è modellata con la funzione Hill:",{"type":32,"tag":122,"props":363,"children":365},{"code":364},"effect = spend^alpha \u002F (spend^alpha + half_saturation^alpha)\n",[366],{"type":32,"tag":129,"props":367,"children":368},{"__ignoreMap":16},[369],{"type":37,"value":364},{"type":32,"tag":33,"props":371,"children":372},{},[373,375,381,383,389],{"type":37,"value":374},"Il parametro ",{"type":32,"tag":129,"props":376,"children":378},{"className":377},[],[379],{"type":37,"value":380},"alpha",{"type":37,"value":382}," determina la concavità della curva, ",{"type":32,"tag":129,"props":384,"children":386},{"className":385},[],[387],{"type":37,"value":388},"half_saturation",{"type":37,"value":390}," determina il livello di spesa dove l'effetto raggiunge il punto mediano. Canali basati su intent come Google Search saturano presto (alpha basso, half_saturation basso). Canali di brand awareness (TV, YouTube) saturano tardi.",{"type":32,"tag":33,"props":392,"children":393},{},[394],{"type":37,"value":395},"L'adstock modella l'effetto della spesa passata su quella odierna. L'adstock geometrico è il più comune:",{"type":32,"tag":122,"props":397,"children":399},{"code":398},"adstocked_spend[t] = spend[t] + theta * adstocked_spend[t-1]\n",[400],{"type":32,"tag":129,"props":401,"children":402},{"__ignoreMap":16},[403],{"type":37,"value":398},{"type":32,"tag":33,"props":405,"children":406},{},[407,413,415,420],{"type":32,"tag":129,"props":408,"children":410},{"className":409},[],[411],{"type":37,"value":412},"theta",{"type":37,"value":414}," (tra 0 e 1) è la velocità di decay. Per TV è alto (0.7-0.9 — l'effetto dura settimane), per search è basso (0.1-0.3 — l'effetto finisce subito). Robyn trova questi parametri tramite ottimizzazione Nevergrad, ma tu devi fornire il ",{"type":32,"tag":40,"props":416,"children":417},{},[418],{"type":37,"value":419},"range precedente",{"type":37,"value":421},":",{"type":32,"tag":122,"props":423,"children":425},{"code":424,"language":125,"meta":16,"className":126,"style":16},"hyperparameters \u003C- list(\n  google_search_spend_alphas = c(0.5, 1.5),\n  google_search_spend_gammas = c(0.1, 0.4), # adstock decay\n  google_search_spend_thetas = c(0, 0.3),   # adstock theta\n  meta_spend_alphas = c(0.5, 2.0),\n  meta_spend_gammas = c(0.3, 0.8),\n  meta_spend_thetas = c(0.2, 0.6),\n  tv_grp_alphas = c(1.0, 3.0),\n  tv_grp_gammas = c(0.5, 0.9),\n  tv_grp_thetas = c(0.6, 0.9)\n)\n",[426],{"type":32,"tag":129,"props":427,"children":428},{"__ignoreMap":16},[429,437,445,453,461,469,477,485,493,501,509],{"type":32,"tag":133,"props":430,"children":431},{"class":135,"line":136},[432],{"type":32,"tag":133,"props":433,"children":434},{},[435],{"type":37,"value":436},"hyperparameters \u003C- list(\n",{"type":32,"tag":133,"props":438,"children":439},{"class":135,"line":145},[440],{"type":32,"tag":133,"props":441,"children":442},{},[443],{"type":37,"value":444},"  google_search_spend_alphas = c(0.5, 1.5),\n",{"type":32,"tag":133,"props":446,"children":447},{"class":135,"line":154},[448],{"type":32,"tag":133,"props":449,"children":450},{},[451],{"type":37,"value":452},"  google_search_spend_gammas = c(0.1, 0.4), # adstock decay\n",{"type":32,"tag":133,"props":454,"children":455},{"class":135,"line":163},[456],{"type":32,"tag":133,"props":457,"children":458},{},[459],{"type":37,"value":460},"  google_search_spend_thetas = c(0, 0.3),   # adstock theta\n",{"type":32,"tag":133,"props":462,"children":463},{"class":135,"line":172},[464],{"type":32,"tag":133,"props":465,"children":466},{},[467],{"type":37,"value":468},"  meta_spend_alphas = c(0.5, 2.0),\n",{"type":32,"tag":133,"props":470,"children":471},{"class":135,"line":181},[472],{"type":32,"tag":133,"props":473,"children":474},{},[475],{"type":37,"value":476},"  meta_spend_gammas = c(0.3, 0.8),\n",{"type":32,"tag":133,"props":478,"children":479},{"class":135,"line":190},[480],{"type":32,"tag":133,"props":481,"children":482},{},[483],{"type":37,"value":484},"  meta_spend_thetas = c(0.2, 0.6),\n",{"type":32,"tag":133,"props":486,"children":487},{"class":135,"line":26},[488],{"type":32,"tag":133,"props":489,"children":490},{},[491],{"type":37,"value":492},"  tv_grp_alphas = c(1.0, 3.0),\n",{"type":32,"tag":133,"props":494,"children":495},{"class":135,"line":207},[496],{"type":32,"tag":133,"props":497,"children":498},{},[499],{"type":37,"value":500},"  tv_grp_gammas = c(0.5, 0.9),\n",{"type":32,"tag":133,"props":502,"children":503},{"class":135,"line":216},[504],{"type":32,"tag":133,"props":505,"children":506},{},[507],{"type":37,"value":508},"  tv_grp_thetas = c(0.6, 0.9)\n",{"type":32,"tag":133,"props":510,"children":511},{"class":135,"line":225},[512],{"type":32,"tag":133,"props":513,"children":514},{},[515],{"type":37,"value":231},{"type":32,"tag":33,"props":517,"children":518},{},[519],{"type":37,"value":520},"Devi definire questi range con conoscenza del dominio. Se dai range completamente casuali il modello diverge o trova coefficienti insensati (come TV con effetto negativo). La documentazione di Robyn suggerisce range default ma testali sui tuoi dati prima di usarli.",{"type":32,"tag":48,"props":522,"children":524},{"id":523},"addestramento-del-modello-e-holdout-validation",[525],{"type":37,"value":526},"Addestramento del modello e holdout validation",{"type":32,"tag":33,"props":528,"children":529},{},[530,532,538,540,545],{"type":37,"value":531},"Per eseguire Robyn usi la funzione ",{"type":32,"tag":129,"props":533,"children":535},{"className":534},[],[536],{"type":37,"value":537},"robyn_run()",{"type":37,"value":539},". Dentro usa la libreria ",{"type":32,"tag":40,"props":541,"children":542},{},[543],{"type":37,"value":544},"Nevergrad",{"type":37,"value":546}," e l'ottimizzazione bayesiana per trovare la miglior combinazione di iperparametri. Un run tipico significa 2000 iterazioni × 10 trial = 20.000 addestramentimodello. Su un MacBook M1 con 8 core impiega ~15 minuti.",{"type":32,"tag":122,"props":548,"children":550},{"code":549,"language":125,"meta":16,"className":126,"style":16},"library(Robyn)\n\nInputCollect \u003C- robyn_inputs(\n  dt_input = df,\n  date_var = \"DATE\",\n  dep_var = \"revenue\",\n  dep_var_type = \"revenue\",\n  paid_media_vars = c(\"google_search_spend\", \"meta_spend\", \"tiktok_spend\"),\n  paid_media_spends = c(\"google_search_spend\", \"meta_spend\", \"tiktok_spend\"),\n  organic_vars = c(\"organic_sessions\"),\n  prophet_vars = c(\"trend\", \"season\", \"holiday\"),\n  window_start = \"2024-01-01\",\n  window_end = \"2025-12-31\",\n  adstock = \"geometric\",\n  hyperparameters = hyperparameters\n)\n\nOutputModels \u003C- robyn_run(\n  InputCollect = InputCollect,\n  iterations = 2000,\n  trials = 10,\n  outputs = FALSE\n)\n",[551],{"type":32,"tag":129,"props":552,"children":553},{"__ignoreMap":16},[554,562,571,579,587,595,603,611,619,627,635,643,652,661,670,679,687,695,704,713,722,731,740],{"type":32,"tag":133,"props":555,"children":556},{"class":135,"line":136},[557],{"type":32,"tag":133,"props":558,"children":559},{},[560],{"type":37,"value":561},"library(Robyn)\n",{"type":32,"tag":133,"props":563,"children":564},{"class":135,"line":145},[565],{"type":32,"tag":133,"props":566,"children":568},{"emptyLinePlaceholder":567},true,[569],{"type":37,"value":570},"\n",{"type":32,"tag":133,"props":572,"children":573},{"class":135,"line":154},[574],{"type":32,"tag":133,"props":575,"children":576},{},[577],{"type":37,"value":578},"InputCollect \u003C- robyn_inputs(\n",{"type":32,"tag":133,"props":580,"children":581},{"class":135,"line":163},[582],{"type":32,"tag":133,"props":583,"children":584},{},[585],{"type":37,"value":586},"  dt_input = df,\n",{"type":32,"tag":133,"props":588,"children":589},{"class":135,"line":172},[590],{"type":32,"tag":133,"props":591,"children":592},{},[593],{"type":37,"value":594},"  date_var = \"DATE\",\n",{"type":32,"tag":133,"props":596,"children":597},{"class":135,"line":181},[598],{"type":32,"tag":133,"props":599,"children":600},{},[601],{"type":37,"value":602},"  dep_var = \"revenue\",\n",{"type":32,"tag":133,"props":604,"children":605},{"class":135,"line":190},[606],{"type":32,"tag":133,"props":607,"children":608},{},[609],{"type":37,"value":610},"  dep_var_type = \"revenue\",\n",{"type":32,"tag":133,"props":612,"children":613},{"class":135,"line":26},[614],{"type":32,"tag":133,"props":615,"children":616},{},[617],{"type":37,"value":618},"  paid_media_vars = c(\"google_search_spend\", \"meta_spend\", \"tiktok_spend\"),\n",{"type":32,"tag":133,"props":620,"children":621},{"class":135,"line":207},[622],{"type":32,"tag":133,"props":623,"children":624},{},[625],{"type":37,"value":626},"  paid_media_spends = c(\"google_search_spend\", \"meta_spend\", \"tiktok_spend\"),\n",{"type":32,"tag":133,"props":628,"children":629},{"class":135,"line":216},[630],{"type":32,"tag":133,"props":631,"children":632},{},[633],{"type":37,"value":634},"  organic_vars = c(\"organic_sessions\"),\n",{"type":32,"tag":133,"props":636,"children":637},{"class":135,"line":225},[638],{"type":32,"tag":133,"props":639,"children":640},{},[641],{"type":37,"value":642},"  prophet_vars = c(\"trend\", \"season\", \"holiday\"),\n",{"type":32,"tag":133,"props":644,"children":646},{"class":135,"line":645},12,[647],{"type":32,"tag":133,"props":648,"children":649},{},[650],{"type":37,"value":651},"  window_start = \"2024-01-01\",\n",{"type":32,"tag":133,"props":653,"children":655},{"class":135,"line":654},13,[656],{"type":32,"tag":133,"props":657,"children":658},{},[659],{"type":37,"value":660},"  window_end = \"2025-12-31\",\n",{"type":32,"tag":133,"props":662,"children":664},{"class":135,"line":663},14,[665],{"type":32,"tag":133,"props":666,"children":667},{},[668],{"type":37,"value":669},"  adstock = \"geometric\",\n",{"type":32,"tag":133,"props":671,"children":673},{"class":135,"line":672},15,[674],{"type":32,"tag":133,"props":675,"children":676},{},[677],{"type":37,"value":678},"  hyperparameters = hyperparameters\n",{"type":32,"tag":133,"props":680,"children":682},{"class":135,"line":681},16,[683],{"type":32,"tag":133,"props":684,"children":685},{},[686],{"type":37,"value":231},{"type":32,"tag":133,"props":688,"children":690},{"class":135,"line":689},17,[691],{"type":32,"tag":133,"props":692,"children":693},{"emptyLinePlaceholder":567},[694],{"type":37,"value":570},{"type":32,"tag":133,"props":696,"children":698},{"class":135,"line":697},18,[699],{"type":32,"tag":133,"props":700,"children":701},{},[702],{"type":37,"value":703},"OutputModels \u003C- robyn_run(\n",{"type":32,"tag":133,"props":705,"children":707},{"class":135,"line":706},19,[708],{"type":32,"tag":133,"props":709,"children":710},{},[711],{"type":37,"value":712},"  InputCollect = InputCollect,\n",{"type":32,"tag":133,"props":714,"children":716},{"class":135,"line":715},20,[717],{"type":32,"tag":133,"props":718,"children":719},{},[720],{"type":37,"value":721},"  iterations = 2000,\n",{"type":32,"tag":133,"props":723,"children":725},{"class":135,"line":724},21,[726],{"type":32,"tag":133,"props":727,"children":728},{},[729],{"type":37,"value":730},"  trials = 10,\n",{"type":32,"tag":133,"props":732,"children":734},{"class":135,"line":733},22,[735],{"type":32,"tag":133,"props":736,"children":737},{},[738],{"type":37,"value":739},"  outputs = FALSE\n",{"type":32,"tag":133,"props":741,"children":743},{"class":135,"line":742},23,[744],{"type":32,"tag":133,"props":745,"children":746},{},[747],{"type":37,"value":231},{"type":32,"tag":33,"props":749,"children":750},{},[751,753,758],{"type":37,"value":752},"Dopo l'addestramento del modello mostra le soluzioni ",{"type":32,"tag":40,"props":754,"children":755},{},[756],{"type":37,"value":757},"Pareto-ottimali",{"type":37,"value":759},". Robyn ottimizza due metriche: NRMSE (normalized root mean square error) e RSSD di decomposizione (residual sum of squared differences). Ogni modello sulla frontiera di Pareto rappresenta un trade-off: uno ha fit buono ma decomposizione cattiva, l'altro il contrario. Tu scegli manualmente il modello più ragionevole.",{"type":32,"tag":33,"props":761,"children":762},{},[763],{"type":37,"value":764},"Per holdout validation, metti da parte le ultime 4-8 settimane. Robyn lo fa automaticamente:",{"type":32,"tag":122,"props":766,"children":768},{"code":767,"language":125,"meta":16,"className":126,"style":16},"robyn_refresh(\n  robyn_object = OutputModels,\n  dt_input = df_new, # Refresh con nuovi dati\n  refresh_steps = 4,\n  refresh_mode = \"manual\"\n)\n",[769],{"type":32,"tag":129,"props":770,"children":771},{"__ignoreMap":16},[772,780,788,796,804,812],{"type":32,"tag":133,"props":773,"children":774},{"class":135,"line":136},[775],{"type":32,"tag":133,"props":776,"children":777},{},[778],{"type":37,"value":779},"robyn_refresh(\n",{"type":32,"tag":133,"props":781,"children":782},{"class":135,"line":145},[783],{"type":32,"tag":133,"props":784,"children":785},{},[786],{"type":37,"value":787},"  robyn_object = OutputModels,\n",{"type":32,"tag":133,"props":789,"children":790},{"class":135,"line":154},[791],{"type":32,"tag":133,"props":792,"children":793},{},[794],{"type":37,"value":795},"  dt_input = df_new, # Refresh con nuovi dati\n",{"type":32,"tag":133,"props":797,"children":798},{"class":135,"line":163},[799],{"type":32,"tag":133,"props":800,"children":801},{},[802],{"type":37,"value":803},"  refresh_steps = 4,\n",{"type":32,"tag":133,"props":805,"children":806},{"class":135,"line":172},[807],{"type":32,"tag":133,"props":808,"children":809},{},[810],{"type":37,"value":811},"  refresh_mode = \"manual\"\n",{"type":32,"tag":133,"props":813,"children":814},{"class":135,"line":181},[815],{"type":32,"tag":133,"props":816,"children":817},{},[818],{"type":37,"value":231},{"type":32,"tag":33,"props":820,"children":821},{},[822],{"type":37,"value":823},"Se l'holdout MAPE (mean absolute percentage error) è sotto il 10%, il modello è affidabile. Sopra il 20% è pericoloso — segnale di overfitting o variabili mancanti.",{"type":32,"tag":48,"props":825,"children":827},{"id":826},"interpretazione-degli-output-e-ottimizzazione-del-budget",[828],{"type":37,"value":829},"Interpretazione degli output e ottimizzazione del budget",{"type":32,"tag":33,"props":831,"children":832},{},[833,835,840,842,847,849,854],{"type":37,"value":834},"L'output più critico di Robyn è la tabella ",{"type":32,"tag":40,"props":836,"children":837},{},[838],{"type":37,"value":839},"channel contribution",{"type":37,"value":841},". Mostra la percentuale di contributo alla revenue di ogni canale e il suo ",{"type":32,"tag":40,"props":843,"children":844},{},[845],{"type":37,"value":846},"ROAS",{"type":37,"value":848}," (return on ad spend). Ma attenzione: questi sono valori ROAS storici, non ",{"type":32,"tag":40,"props":850,"children":851},{},[852],{"type":37,"value":853},"ROAS marginale",{"type":37,"value":855},". L'ROAS marginale mostra quanto ricavo genera il prossimo 1.000 euro di spesa ed è calcolato dalla derivata della curva di saturazione.",{"type":32,"tag":33,"props":857,"children":858},{},[859,861,867],{"type":37,"value":860},"La funzione ",{"type":32,"tag":129,"props":862,"children":864},{"className":863},[],[865],{"type":37,"value":866},"budget_allocator()",{"type":37,"value":868}," di Robyn ridistribuisce il budget corrente in base alle curve di saturazione. Se Google Search è saturo, sposta budget extra a Meta o TikTok. Questa ottimizzazione trova il punto sulla curva di risposta dove il rendimento marginale è equalizzato (economia 101: MR₁ = MR₂).",{"type":32,"tag":122,"props":870,"children":872},{"code":871,"language":125,"meta":16,"className":126,"style":16},"AllocatorCollect \u003C- robyn_allocator(\n  robyn_object = OutputModels,\n  select_model = \"1_100_2\", # Model ID scelto da Pareto\n  scenario = \"max_response_expected_spend\",\n  channel_constr_low = c(0.7, 0.7, 0.5), # Minimo 70% Google, 70% Meta, 50% TikTok\n  channel_constr_up = c(1.5, 2.0, 3.0),  # Limiti di aumento massimo\n  expected_spend = 100000\n)\n",[873],{"type":32,"tag":129,"props":874,"children":875},{"__ignoreMap":16},[876,884,891,899,907,915,923,931],{"type":32,"tag":133,"props":877,"children":878},{"class":135,"line":136},[879],{"type":32,"tag":133,"props":880,"children":881},{},[882],{"type":37,"value":883},"AllocatorCollect \u003C- robyn_allocator(\n",{"type":32,"tag":133,"props":885,"children":886},{"class":135,"line":145},[887],{"type":32,"tag":133,"props":888,"children":889},{},[890],{"type":37,"value":787},{"type":32,"tag":133,"props":892,"children":893},{"class":135,"line":154},[894],{"type":32,"tag":133,"props":895,"children":896},{},[897],{"type":37,"value":898},"  select_model = \"1_100_2\", # Model ID scelto da Pareto\n",{"type":32,"tag":133,"props":900,"children":901},{"class":135,"line":163},[902],{"type":32,"tag":133,"props":903,"children":904},{},[905],{"type":37,"value":906},"  scenario = \"max_response_expected_spend\",\n",{"type":32,"tag":133,"props":908,"children":909},{"class":135,"line":172},[910],{"type":32,"tag":133,"props":911,"children":912},{},[913],{"type":37,"value":914},"  channel_constr_low = c(0.7, 0.7, 0.5), # Minimo 70% Google, 70% Meta, 50% TikTok\n",{"type":32,"tag":133,"props":916,"children":917},{"class":135,"line":181},[918],{"type":32,"tag":133,"props":919,"children":920},{},[921],{"type":37,"value":922},"  channel_constr_up = c(1.5, 2.0, 3.0),  # Limiti di aumento massimo\n",{"type":32,"tag":133,"props":924,"children":925},{"class":135,"line":190},[926],{"type":32,"tag":133,"props":927,"children":928},{},[929],{"type":37,"value":930},"  expected_spend = 100000\n",{"type":32,"tag":133,"props":932,"children":933},{"class":135,"line":26},[934],{"type":32,"tag":133,"props":935,"children":936},{},[937],{"type":37,"value":231},{"type":32,"tag":33,"props":939,"children":940},{},[941,943,948],{"type":37,"value":942},"L'output mostra come distribuire il budget corrente di 100.000 euro per ottenere il ricavo ottimale. Ma è una raccomandazione statica — nella realtà cambiano creative refresh, competitor activity, stagionalità. Per questo devi ",{"type":32,"tag":40,"props":944,"children":945},{},[946],{"type":37,"value":947},"refresh l'MMM mensilmente",{"type":37,"value":949},".",{"type":32,"tag":48,"props":951,"children":953},{"id":952},"trade-off-e-limiti",[954],{"type":37,"value":955},"Trade-off e limiti",{"type":32,"tag":33,"props":957,"children":958},{},[959,961,966,968,973],{"type":37,"value":960},"MMM, a differenza dell'attribution, funziona a ",{"type":32,"tag":40,"props":962,"children":963},{},[964],{"type":37,"value":965},"livello aggregato",{"type":37,"value":967},". Non puoi usarlo per la personalizzazione. Per Google Search non puoi vedere quale parola chiave performa meglio — puoi solo misurare il contributo complessivo di Search. Inoltre il modello è suscettibile al problema ",{"type":32,"tag":40,"props":969,"children":970},{},[971],{"type":37,"value":972},"correlazione ≠ causalità",{"type":37,"value":974},": se le vendite aumentano d'estate e anche tu aumenti la spesa TV d'estate, il modello potrebbe dare troppo credito a TV.",{"type":32,"tag":33,"props":976,"children":977},{},[978,980,985,987,993],{"type":37,"value":979},"Per risolvere questo, devi ",{"type":32,"tag":40,"props":981,"children":982},{},[983],{"type":37,"value":984},"validare l'MMM con test di incrementalità",{"type":37,"value":986},". Misuri il vero effetto causale con geo-lift o holdout test e lo confronti con i risultati MMM. Robyn può includere i risultati di incrementalità come parametro di ",{"type":32,"tag":129,"props":988,"children":990},{"className":989},[],[991],{"type":37,"value":992},"calibration",{"type":37,"value":994}," — funziona come prior bayesiano e avvicina il modello alla realtà.",{"type":32,"tag":33,"props":996,"children":997},{},[998,1000,1005],{"type":37,"value":999},"Un'altra difficoltà è l'",{"type":32,"tag":40,"props":1001,"children":1002},{},[1003],{"type":37,"value":1004},"aggiunta di nuovi canali",{"type":37,"value":1006},". Se apri un nuovo canale (es. Snapchat) con soli 8 settimane di dati, Robyn non può imparare la curva di saturazione di quel canale. In questo caso devi impostare prior manuali o escludere le prime 12 settimane dal modello e aggiungerlo dopo.",{"type":32,"tag":33,"props":1008,"children":1009},{},[1010,1012,1017],{"type":37,"value":1011},"Infine, MMM è ",{"type":32,"tag":40,"props":1013,"children":1014},{},[1015],{"type":37,"value":1016},"più potente quando unisce offline e online",{"type":37,"value":1018},". Se non includi nel modello la spesa di canali offline come TV, outdoor, sponsorizzazioni, il modello dà troppo credito ai canali online (bias della variabile omessa). Robyn è flessibile: accetta variabili proxy come GRP, reach, o persino brand search volume.",{"type":32,"tag":33,"props":1020,"children":1021},{},[1022],{"type":37,"value":1023},"Una pipeline MMM costruita correttamente trasforma il planning del budget marketing da gioco di ipotesi a ingegneria basata su evidenze. Robyn lo rende accessibile come open-source — ma la struttura dati, il tuning degli iperparametri e la validazione dell'incrementalità richiedono ancora expertise umana. I team che investono in regressione econometrica al posto dell'attribution nel mondo senza cookie saranno 12 mesi avanti ai competitor nel 2027.",{"type":32,"tag":1025,"props":1026,"children":1027},"style",{},[1028],{"type":37,"value":1029},"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":154,"depth":154,"links":1031},[1032,1033,1034,1035,1036,1037],{"id":50,"depth":145,"text":53},{"id":112,"depth":145,"text":115},{"id":346,"depth":145,"text":349},{"id":523,"depth":145,"text":526},{"id":826,"depth":145,"text":829},{"id":952,"depth":145,"text":955},"markdown","content:it:data:robyn-marketing-mix-modeling-setup-pratico.md","content","it\u002Fdata\u002Frobyn-marketing-mix-modeling-setup-pratico.md","it\u002Fdata\u002Frobyn-marketing-mix-modeling-setup-pratico","md",1782050755587]