[{"data":1,"prerenderedAt":1050},["ShallowReactive",2],{"article-alternates":3,"article-\u002Fes\u002Fdata\u002Fmarketing-mix-modeling-robyn-setup-practico":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":8,"_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":1044,"_id":1045,"_source":1046,"_file":1047,"_stem":1048,"_extension":1049},"data",false,"","Marketing Mix Modeling: Configuración Práctica con Robyn","El framework MMM de código abierto de Meta, Robyn, con saturación, adstock y validación holdout usando código R y estructura de datos correcta.","2026-06-05",[21,22,23,24,25],"marketing-mix-modeling","robyn","adstock","saturation-curve","incrementality",8,"Roibase",{"type":29,"children":30,"toc":1036},"root",[31,47,54,59,98,110,116,121,232,240,307,328,350,356,368,376,397,402,410,428,522,527,533,553,754,766,771,825,830,836,862,875,944,956,962,981,1001,1013,1025,1030],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36,39,45],{"type":37,"value":38},"text","En el mundo de la medición post-cookie, la atribución pierde señal cada día. Con iOS 17.4 y SKAdNetwork teniendo dificultades para mostrar el verdadero ROAS, los dueños de presupuesto de marketing se giran hacia modelos econométricos para medir la verdadera contribución de cada canal. Marketing Mix Modeling (MMM), método estadístico desarrollado en los años 60 para publicidad televisiva, vuelve al centro del escenario en 2026 junto a server-side measurement y data lakes de first-party. ",{"type":32,"tag":40,"props":41,"children":42},"strong",{},[43],{"type":37,"value":44},"Robyn",{"type":37,"value":46},", lanzado como código abierto por Meta en 2021, acelera esta metodología basada en regresión añadiendo aprendizaje automático moderno y optimización bayesiana.",{"type":32,"tag":48,"props":49,"children":51},"h2",{"id":50},"por-qué-mmm-es-crítico-ahora",[52],{"type":37,"value":53},"Por qué MMM es crítico ahora",{"type":32,"tag":33,"props":55,"children":56},{},[57],{"type":37,"value":58},"El modelo de atribución last-click colapsa con la pérdida de cookies, mientras que la atribución multi-touch (MTA) se vuelve inutilizable post-GDPR y ATT por requerir datos a nivel de evento. La atribución data-driven de Google Analytics 4 se basa en aprendizaje automático pero solo funciona dentro del ecosistema de Google. Sin embargo, el 60% del presupuesto de marketing sigue siendo gastado fuera de Google: Meta, TikTok, display programático, TV offline, patrocinios.",{"type":32,"tag":33,"props":60,"children":61},{},[62,64,69,71,76,78,82,84,89,91,96],{"type":37,"value":63},"MMM se basa en datos ",{"type":32,"tag":40,"props":65,"children":66},{},[67],{"type":37,"value":68},"agregados",{"type":37,"value":70}," a nivel semanal o diario, no en rastreo a nivel de usuario. El modelo de regresión extrae la relación entre el gasto de cada canal y las ventas (o conversiones). El modelo descansa en dos suposiciones fundamentales: ",{"type":32,"tag":40,"props":72,"children":73},{},[74],{"type":37,"value":75},"saturación",{"type":37,"value":77}," (el gasto creciente genera retornos marginales decrecientes) y ",{"type":32,"tag":40,"props":79,"children":80},{},[81],{"type":37,"value":23},{"type":37,"value":83}," (el anuncio de hoy afecta a las semanas futuras). Estas suposiciones son estadísticas pero reflejan realidad comercial. Robyn busca encontrar automáticamente estos dos parámetros mediante optimización bayesiana de hiperparámetros. En versiones posteriores a 2024 (v3.11+), se añadió ",{"type":32,"tag":40,"props":85,"children":86},{},[87],{"type":37,"value":88},"ridge regression",{"type":37,"value":90}," y ",{"type":32,"tag":40,"props":92,"children":93},{},[94],{"type":37,"value":95},"descomposición de series temporales Prophet",{"type":37,"value":97},", aumentando la precisión estacional del modelo.",{"type":32,"tag":33,"props":99,"children":100},{},[101,103,108],{"type":37,"value":102},"Otra característica crítica de Robyn es la ",{"type":32,"tag":40,"props":104,"children":105},{},[106],{"type":37,"value":107},"validación holdout",{"type":37,"value":109},": entrena el modelo con datos de 12 semanas anteriores y predice las siguientes 4 semanas para medir el error out-of-sample. Este elemento previene overfitting y demuestra que el modelo realmente está aprendiendo los canales. Las soluciones MMM de Meridian de Google y las antiguas de Facebook usan enfoques similares pero son closed-source y costosas. Robyn proporciona acceso gratuito a la misma metodología.",{"type":32,"tag":48,"props":111,"children":113},{"id":112},"estructura-de-datos-y-preparación",[114],{"type":37,"value":115},"Estructura de datos y preparación",{"type":32,"tag":33,"props":117,"children":118},{},[119],{"type":37,"value":120},"El formato de datos que necesita Robyn es el siguiente: cada fila es una unidad de tiempo (día o semana), cada columna es un gasto de canal o métrica de conversión. Se recomiendan mínimo 104 semanas (2 años) porque la significación estadística de los coeficientes de regresión depende del tamaño de la muestra. Con menos de 52 semanas experimentarás problemas de convergencia del modelo.",{"type":32,"tag":122,"props":123,"children":127},"pre",{"code":124,"language":125,"meta":16,"className":126,"style":16},"# Estructura de datos de ejemplo — agrega semanal extraída de 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},"# Estructura de datos de ejemplo — agrega semanal extraída de 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},"Detalles importantes:",{"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 columna ",{"type":32,"tag":129,"props":251,"children":253},{"className":252},[],[254],{"type":37,"value":255},"DATE",{"type":37,"value":257}," debe estar en clase Date, no string",{"type":32,"tag":245,"props":259,"children":260},{},[261],{"type":37,"value":262},"Revenue o conversion entra en el modelo como variable objetivo (variable dependiente)",{"type":32,"tag":245,"props":264,"children":265},{},[266,268,273],{"type":37,"value":267},"Los canales (google_search_spend, meta_spend) son columnas de medios ",{"type":32,"tag":40,"props":269,"children":270},{},[271],{"type":37,"value":272},"pagados",{"type":37,"value":274}," — se les aplica adstock y saturación",{"type":32,"tag":245,"props":276,"children":277},{},[278,280,286,287,293,295,300],{"type":37,"value":279},"Variables como ",{"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}," son variables ",{"type":32,"tag":40,"props":296,"children":297},{},[298],{"type":37,"value":299},"orgánicas \u002F de control",{"type":37,"value":301}," — no se les aplica transformación de saturación, se usan para extracción de baseline",{"type":32,"tag":245,"props":303,"children":304},{},[305],{"type":37,"value":306},"Si tienes datos de canal offline como TV, normaliza como GRP, reach o minutos visualizados",{"type":32,"tag":33,"props":308,"children":309},{},[310,312,318,320,326],{"type":37,"value":311},"Robyn no trabaja con etiquetas manuales como ",{"type":32,"tag":129,"props":313,"children":315},{"className":314},[],[316],{"type":37,"value":317},"facebook_spend",{"type":37,"value":319},"; definen los nombres de columna tú mismo pero debes especificar explícitamente en la función ",{"type":32,"tag":129,"props":321,"children":323},{"className":322},[],[324],{"type":37,"value":325},"InputCollect()",{"type":37,"value":327}," qué columnas son paid y cuáles son organic.",{"type":32,"tag":33,"props":329,"children":330},{},[331,340,342,348],{"type":32,"tag":332,"props":333,"children":337},"a",{"href":334,"rel":335},"https:\u002F\u002Fwww.roibase.com.tr\u002Fes\u002Ffirstparty",[336],"nofollow",[338],{"type":37,"value":339},"La arquitectura de datos first-party",{"type":37,"value":341}," es difícil de implementar si no la has construido. Server-side GTM, exportación raw de GA4, APIs de Meta\u002FGoogle Ads, datos de ventas del sistema CRM — necesitas combinarlos en BigQuery y hacer rollup semanal. Cuando configuramos este pipeline ETL con dbt, generamos la tabla ",{"type":32,"tag":129,"props":343,"children":345},{"className":344},[],[346],{"type":37,"value":347},"fact_marketing_weekly",{"type":37,"value":349}," lista para MMM.",{"type":32,"tag":48,"props":351,"children":353},{"id":352},"configuración-de-saturación-y-adstock",[354],{"type":37,"value":355},"Configuración de saturación y adstock",{"type":32,"tag":33,"props":357,"children":358},{},[359,361,366],{"type":37,"value":360},"La fortaleza de Robyn es que puede optimizar ",{"type":32,"tag":40,"props":362,"children":363},{},[364],{"type":37,"value":365},"por separado",{"type":37,"value":367}," la curva de saturación y los parámetros de decay de adstock para cada canal. La saturación se modela con la función de Hill:",{"type":32,"tag":122,"props":369,"children":371},{"code":370},"effect = spend^alpha \u002F (spend^alpha + half_saturation^alpha)\n",[372],{"type":32,"tag":129,"props":373,"children":374},{"__ignoreMap":16},[375],{"type":37,"value":370},{"type":32,"tag":33,"props":377,"children":378},{},[379,381,387,389,395],{"type":37,"value":380},"El parámetro ",{"type":32,"tag":129,"props":382,"children":384},{"className":383},[],[385],{"type":37,"value":386},"alpha",{"type":37,"value":388}," determina la concavidad de la curva, ",{"type":32,"tag":129,"props":390,"children":392},{"className":391},[],[393],{"type":37,"value":394},"half_saturation",{"type":37,"value":396}," determina el nivel de gasto donde el efecto alcanza su punto medio. Los canales basados en intención como Google Search saturan temprano (alpha bajo, half_saturation bajo). Los canales de conciencia de marca (TV, YouTube) saturan tarde.",{"type":32,"tag":33,"props":398,"children":399},{},[400],{"type":37,"value":401},"Adstock modela el efecto del gasto pasado en el presente. El adstock geométrico es la forma más común:",{"type":32,"tag":122,"props":403,"children":405},{"code":404},"adstocked_spend[t] = spend[t] + theta * adstocked_spend[t-1]\n",[406],{"type":32,"tag":129,"props":407,"children":408},{"__ignoreMap":16},[409],{"type":37,"value":404},{"type":32,"tag":33,"props":411,"children":412},{},[413,419,421,426],{"type":32,"tag":129,"props":414,"children":416},{"className":415},[],[417],{"type":37,"value":418},"theta",{"type":37,"value":420}," (entre 0 y 1) es la velocidad de decay. Para TV el theta es alto (0.7-0.9 — el efecto dura semanas), para search es bajo (0.1-0.3 — el efecto termina rápido). Robyn encuentra estos parámetros mediante optimización Nevergrad, pero tú debes proporcionar el ",{"type":32,"tag":40,"props":422,"children":423},{},[424],{"type":37,"value":425},"rango anterior",{"type":37,"value":427},":",{"type":32,"tag":122,"props":429,"children":431},{"code":430,"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",[432],{"type":32,"tag":129,"props":433,"children":434},{"__ignoreMap":16},[435,443,451,459,467,475,483,491,499,507,515],{"type":32,"tag":133,"props":436,"children":437},{"class":135,"line":136},[438],{"type":32,"tag":133,"props":439,"children":440},{},[441],{"type":37,"value":442},"hyperparameters \u003C- list(\n",{"type":32,"tag":133,"props":444,"children":445},{"class":135,"line":145},[446],{"type":32,"tag":133,"props":447,"children":448},{},[449],{"type":37,"value":450},"  google_search_spend_alphas = c(0.5, 1.5),\n",{"type":32,"tag":133,"props":452,"children":453},{"class":135,"line":154},[454],{"type":32,"tag":133,"props":455,"children":456},{},[457],{"type":37,"value":458},"  google_search_spend_gammas = c(0.1, 0.4), # adstock decay\n",{"type":32,"tag":133,"props":460,"children":461},{"class":135,"line":163},[462],{"type":32,"tag":133,"props":463,"children":464},{},[465],{"type":37,"value":466},"  google_search_spend_thetas = c(0, 0.3),   # adstock theta\n",{"type":32,"tag":133,"props":468,"children":469},{"class":135,"line":172},[470],{"type":32,"tag":133,"props":471,"children":472},{},[473],{"type":37,"value":474},"  meta_spend_alphas = c(0.5, 2.0),\n",{"type":32,"tag":133,"props":476,"children":477},{"class":135,"line":181},[478],{"type":32,"tag":133,"props":479,"children":480},{},[481],{"type":37,"value":482},"  meta_spend_gammas = c(0.3, 0.8),\n",{"type":32,"tag":133,"props":484,"children":485},{"class":135,"line":190},[486],{"type":32,"tag":133,"props":487,"children":488},{},[489],{"type":37,"value":490},"  meta_spend_thetas = c(0.2, 0.6),\n",{"type":32,"tag":133,"props":492,"children":493},{"class":135,"line":26},[494],{"type":32,"tag":133,"props":495,"children":496},{},[497],{"type":37,"value":498},"  tv_grp_alphas = c(1.0, 3.0),\n",{"type":32,"tag":133,"props":500,"children":501},{"class":135,"line":207},[502],{"type":32,"tag":133,"props":503,"children":504},{},[505],{"type":37,"value":506},"  tv_grp_gammas = c(0.5, 0.9),\n",{"type":32,"tag":133,"props":508,"children":509},{"class":135,"line":216},[510],{"type":32,"tag":133,"props":511,"children":512},{},[513],{"type":37,"value":514},"  tv_grp_thetas = c(0.6, 0.9)\n",{"type":32,"tag":133,"props":516,"children":517},{"class":135,"line":225},[518],{"type":32,"tag":133,"props":519,"children":520},{},[521],{"type":37,"value":231},{"type":32,"tag":33,"props":523,"children":524},{},[525],{"type":37,"value":526},"Debes determinar estos rangos con conocimiento del dominio. Si los das completamente al azar, el modelo diverge o encuentra coeficientes sin sentido (como un efecto negativo de TV). La documentación de Robyn ofrece recomendaciones de rangos por defecto pero no los uses sin probar en tus datos primero.",{"type":32,"tag":48,"props":528,"children":530},{"id":529},"entrenamiento-del-modelo-y-validación-holdout",[531],{"type":37,"value":532},"Entrenamiento del modelo y validación holdout",{"type":32,"tag":33,"props":534,"children":535},{},[536,538,544,546,551],{"type":37,"value":537},"Para ejecutar Robyn usas la función ",{"type":32,"tag":129,"props":539,"children":541},{"className":540},[],[542],{"type":37,"value":543},"robyn_run()",{"type":37,"value":545},". Internamente, la librería ",{"type":32,"tag":40,"props":547,"children":548},{},[549],{"type":37,"value":550},"Nevergrad",{"type":37,"value":552}," busca la mejor combinación de hiperparámetros mediante optimización bayesiana. Una ejecución típica significa 2000 iteraciones x 10 trials = 20,000 entrenamientos de modelo. En MacBook M1 con 8 cores toma ~15 minutos.",{"type":32,"tag":122,"props":554,"children":556},{"code":555,"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",[557],{"type":32,"tag":129,"props":558,"children":559},{"__ignoreMap":16},[560,568,577,585,593,601,609,617,625,633,641,649,658,667,676,685,693,701,710,719,728,737,746],{"type":32,"tag":133,"props":561,"children":562},{"class":135,"line":136},[563],{"type":32,"tag":133,"props":564,"children":565},{},[566],{"type":37,"value":567},"library(Robyn)\n",{"type":32,"tag":133,"props":569,"children":570},{"class":135,"line":145},[571],{"type":32,"tag":133,"props":572,"children":574},{"emptyLinePlaceholder":573},true,[575],{"type":37,"value":576},"\n",{"type":32,"tag":133,"props":578,"children":579},{"class":135,"line":154},[580],{"type":32,"tag":133,"props":581,"children":582},{},[583],{"type":37,"value":584},"InputCollect \u003C- robyn_inputs(\n",{"type":32,"tag":133,"props":586,"children":587},{"class":135,"line":163},[588],{"type":32,"tag":133,"props":589,"children":590},{},[591],{"type":37,"value":592},"  dt_input = df,\n",{"type":32,"tag":133,"props":594,"children":595},{"class":135,"line":172},[596],{"type":32,"tag":133,"props":597,"children":598},{},[599],{"type":37,"value":600},"  date_var = \"DATE\",\n",{"type":32,"tag":133,"props":602,"children":603},{"class":135,"line":181},[604],{"type":32,"tag":133,"props":605,"children":606},{},[607],{"type":37,"value":608},"  dep_var = \"revenue\",\n",{"type":32,"tag":133,"props":610,"children":611},{"class":135,"line":190},[612],{"type":32,"tag":133,"props":613,"children":614},{},[615],{"type":37,"value":616},"  dep_var_type = \"revenue\",\n",{"type":32,"tag":133,"props":618,"children":619},{"class":135,"line":26},[620],{"type":32,"tag":133,"props":621,"children":622},{},[623],{"type":37,"value":624},"  paid_media_vars = c(\"google_search_spend\", \"meta_spend\", \"tiktok_spend\"),\n",{"type":32,"tag":133,"props":626,"children":627},{"class":135,"line":207},[628],{"type":32,"tag":133,"props":629,"children":630},{},[631],{"type":37,"value":632},"  paid_media_spends = c(\"google_search_spend\", \"meta_spend\", \"tiktok_spend\"),\n",{"type":32,"tag":133,"props":634,"children":635},{"class":135,"line":216},[636],{"type":32,"tag":133,"props":637,"children":638},{},[639],{"type":37,"value":640},"  organic_vars = c(\"organic_sessions\"),\n",{"type":32,"tag":133,"props":642,"children":643},{"class":135,"line":225},[644],{"type":32,"tag":133,"props":645,"children":646},{},[647],{"type":37,"value":648},"  prophet_vars = c(\"trend\", \"season\", \"holiday\"),\n",{"type":32,"tag":133,"props":650,"children":652},{"class":135,"line":651},12,[653],{"type":32,"tag":133,"props":654,"children":655},{},[656],{"type":37,"value":657},"  window_start = \"2024-01-01\",\n",{"type":32,"tag":133,"props":659,"children":661},{"class":135,"line":660},13,[662],{"type":32,"tag":133,"props":663,"children":664},{},[665],{"type":37,"value":666},"  window_end = \"2025-12-31\",\n",{"type":32,"tag":133,"props":668,"children":670},{"class":135,"line":669},14,[671],{"type":32,"tag":133,"props":672,"children":673},{},[674],{"type":37,"value":675},"  adstock = \"geometric\",\n",{"type":32,"tag":133,"props":677,"children":679},{"class":135,"line":678},15,[680],{"type":32,"tag":133,"props":681,"children":682},{},[683],{"type":37,"value":684},"  hyperparameters = hyperparameters\n",{"type":32,"tag":133,"props":686,"children":688},{"class":135,"line":687},16,[689],{"type":32,"tag":133,"props":690,"children":691},{},[692],{"type":37,"value":231},{"type":32,"tag":133,"props":694,"children":696},{"class":135,"line":695},17,[697],{"type":32,"tag":133,"props":698,"children":699},{"emptyLinePlaceholder":573},[700],{"type":37,"value":576},{"type":32,"tag":133,"props":702,"children":704},{"class":135,"line":703},18,[705],{"type":32,"tag":133,"props":706,"children":707},{},[708],{"type":37,"value":709},"OutputModels \u003C- robyn_run(\n",{"type":32,"tag":133,"props":711,"children":713},{"class":135,"line":712},19,[714],{"type":32,"tag":133,"props":715,"children":716},{},[717],{"type":37,"value":718},"  InputCollect = InputCollect,\n",{"type":32,"tag":133,"props":720,"children":722},{"class":135,"line":721},20,[723],{"type":32,"tag":133,"props":724,"children":725},{},[726],{"type":37,"value":727},"  iterations = 2000,\n",{"type":32,"tag":133,"props":729,"children":731},{"class":135,"line":730},21,[732],{"type":32,"tag":133,"props":733,"children":734},{},[735],{"type":37,"value":736},"  trials = 10,\n",{"type":32,"tag":133,"props":738,"children":740},{"class":135,"line":739},22,[741],{"type":32,"tag":133,"props":742,"children":743},{},[744],{"type":37,"value":745},"  outputs = FALSE\n",{"type":32,"tag":133,"props":747,"children":749},{"class":135,"line":748},23,[750],{"type":32,"tag":133,"props":751,"children":752},{},[753],{"type":37,"value":231},{"type":32,"tag":33,"props":755,"children":756},{},[757,759,764],{"type":37,"value":758},"Después del entrenamiento del modelo, muestra las soluciones ",{"type":32,"tag":40,"props":760,"children":761},{},[762],{"type":37,"value":763},"Pareto-óptimas",{"type":37,"value":765},". Robyn optimiza dos métricas: NRMSE (error cuadrático medio normalizado) y RSSD de descomposición (diferencia de suma de residuos al cuadrado). Cada modelo en la frontera de Pareto es un trade-off: uno tiene buen fit pero mala descomposición, otro lo opuesto. Debes seleccionar manualmente el modelo más razonable.",{"type":32,"tag":33,"props":767,"children":768},{},[769],{"type":37,"value":770},"Para validación holdout, reservas las últimas 4-8 semanas. Robyn lo hace automáticamente:",{"type":32,"tag":122,"props":772,"children":774},{"code":773,"language":125,"meta":16,"className":126,"style":16},"robyn_refresh(\n  robyn_object = OutputModels,\n  dt_input = df_new, # Refresh con datos nuevos\n  refresh_steps = 4,\n  refresh_mode = \"manual\"\n)\n",[775],{"type":32,"tag":129,"props":776,"children":777},{"__ignoreMap":16},[778,786,794,802,810,818],{"type":32,"tag":133,"props":779,"children":780},{"class":135,"line":136},[781],{"type":32,"tag":133,"props":782,"children":783},{},[784],{"type":37,"value":785},"robyn_refresh(\n",{"type":32,"tag":133,"props":787,"children":788},{"class":135,"line":145},[789],{"type":32,"tag":133,"props":790,"children":791},{},[792],{"type":37,"value":793},"  robyn_object = OutputModels,\n",{"type":32,"tag":133,"props":795,"children":796},{"class":135,"line":154},[797],{"type":32,"tag":133,"props":798,"children":799},{},[800],{"type":37,"value":801},"  dt_input = df_new, # Refresh con datos nuevos\n",{"type":32,"tag":133,"props":803,"children":804},{"class":135,"line":163},[805],{"type":32,"tag":133,"props":806,"children":807},{},[808],{"type":37,"value":809},"  refresh_steps = 4,\n",{"type":32,"tag":133,"props":811,"children":812},{"class":135,"line":172},[813],{"type":32,"tag":133,"props":814,"children":815},{},[816],{"type":37,"value":817},"  refresh_mode = \"manual\"\n",{"type":32,"tag":133,"props":819,"children":820},{"class":135,"line":181},[821],{"type":32,"tag":133,"props":822,"children":823},{},[824],{"type":37,"value":231},{"type":32,"tag":33,"props":826,"children":827},{},[828],{"type":37,"value":829},"Si el MAPE holdout (error porcentual absoluto medio) está por debajo del 10%, el modelo se considera confiable. Por encima del 20% es peligroso — señal de overfitting o variable faltante.",{"type":32,"tag":48,"props":831,"children":833},{"id":832},"interpretar-salidas-y-optimización-de-presupuesto",[834],{"type":37,"value":835},"Interpretar salidas y optimización de presupuesto",{"type":32,"tag":33,"props":837,"children":838},{},[839,841,846,848,853,855,860],{"type":37,"value":840},"La salida más crítica de Robyn es la tabla de ",{"type":32,"tag":40,"props":842,"children":843},{},[844],{"type":37,"value":845},"channel contribution",{"type":37,"value":847},". Muestra la contribución al revenue de cada canal en porcentaje y su ",{"type":32,"tag":40,"props":849,"children":850},{},[851],{"type":37,"value":852},"ROAS",{"type":37,"value":854}," (retorno sobre gasto en anuncios). Pero atención: estos valores son ROAS histórico, no ",{"type":32,"tag":40,"props":856,"children":857},{},[858],{"type":37,"value":859},"ROAS marginal",{"type":37,"value":861},". El ROAS marginal muestra cuánto revenue adicional generará el siguiente gasto de 1000 TL y se calcula como la derivada de la curva de saturación.",{"type":32,"tag":33,"props":863,"children":864},{},[865,867,873],{"type":37,"value":866},"La función ",{"type":32,"tag":129,"props":868,"children":870},{"className":869},[],[871],{"type":37,"value":872},"budget_allocator()",{"type":37,"value":874}," de Robyn redistribuye el presupuesto existente según las curvas de saturación. Si Google Search está saturado, traslada el presupuesto excedente a Meta o TikTok. Esta optimización encuentra el punto donde el retorno marginal se iguala entre canales (economía 101: MR₁ = MR₂).",{"type":32,"tag":122,"props":876,"children":878},{"code":877,"language":125,"meta":16,"className":126,"style":16},"AllocatorCollect \u003C- robyn_allocator(\n  robyn_object = OutputModels,\n  select_model = \"1_100_2\", # ID del modelo que seleccionaste de Pareto\n  scenario = \"max_response_expected_spend\",\n  channel_constr_low = c(0.7, 0.7, 0.5), # Mínimo 70% Google, 70% Meta, 50% TikTok\n  channel_constr_up = c(1.5, 2.0, 3.0),  # Límites de aumento máximo\n  expected_spend = 100000\n)\n",[879],{"type":32,"tag":129,"props":880,"children":881},{"__ignoreMap":16},[882,890,897,905,913,921,929,937],{"type":32,"tag":133,"props":883,"children":884},{"class":135,"line":136},[885],{"type":32,"tag":133,"props":886,"children":887},{},[888],{"type":37,"value":889},"AllocatorCollect \u003C- robyn_allocator(\n",{"type":32,"tag":133,"props":891,"children":892},{"class":135,"line":145},[893],{"type":32,"tag":133,"props":894,"children":895},{},[896],{"type":37,"value":793},{"type":32,"tag":133,"props":898,"children":899},{"class":135,"line":154},[900],{"type":32,"tag":133,"props":901,"children":902},{},[903],{"type":37,"value":904},"  select_model = \"1_100_2\", # ID del modelo que seleccionaste de Pareto\n",{"type":32,"tag":133,"props":906,"children":907},{"class":135,"line":163},[908],{"type":32,"tag":133,"props":909,"children":910},{},[911],{"type":37,"value":912},"  scenario = \"max_response_expected_spend\",\n",{"type":32,"tag":133,"props":914,"children":915},{"class":135,"line":172},[916],{"type":32,"tag":133,"props":917,"children":918},{},[919],{"type":37,"value":920},"  channel_constr_low = c(0.7, 0.7, 0.5), # Mínimo 70% Google, 70% Meta, 50% TikTok\n",{"type":32,"tag":133,"props":922,"children":923},{"class":135,"line":181},[924],{"type":32,"tag":133,"props":925,"children":926},{},[927],{"type":37,"value":928},"  channel_constr_up = c(1.5, 2.0, 3.0),  # Límites de aumento máximo\n",{"type":32,"tag":133,"props":930,"children":931},{"class":135,"line":190},[932],{"type":32,"tag":133,"props":933,"children":934},{},[935],{"type":37,"value":936},"  expected_spend = 100000\n",{"type":32,"tag":133,"props":938,"children":939},{"class":135,"line":26},[940],{"type":32,"tag":133,"props":941,"children":942},{},[943],{"type":37,"value":231},{"type":32,"tag":33,"props":945,"children":946},{},[947,949,954],{"type":37,"value":948},"La salida muestra cómo distribuir tu presupuesto de 100,000 TL para obtener revenue óptimo. Pero esta es una recomendación estática — en la realidad cambian creative refresh, actividad competitiva, seasonality. Por eso debes hacer refresh de MMM ",{"type":32,"tag":40,"props":950,"children":951},{},[952],{"type":37,"value":953},"mensualmente",{"type":37,"value":955},".",{"type":32,"tag":48,"props":957,"children":959},{"id":958},"trade-offs-y-limitaciones",[960],{"type":37,"value":961},"Trade-offs y limitaciones",{"type":32,"tag":33,"props":963,"children":964},{},[965,967,972,974,979],{"type":37,"value":966},"A diferencia de attribution, MMM trabaja a ",{"type":32,"tag":40,"props":968,"children":969},{},[970],{"type":37,"value":971},"nivel agregado",{"type":37,"value":973},". Esto significa que no puede usarse para personalización. En Google Search, MMM no puede mostrar qué keyword funcionó mejor — solo mide la contribución total de Search. Además, el modelo es vulnerable al problema ",{"type":32,"tag":40,"props":975,"children":976},{},[977],{"type":37,"value":978},"correlation ≠ causation",{"type":37,"value":980},": si las ventas suben en verano y tú también aumentas gasto en TV en verano, el modelo podría dar demasiado crédito a TV.",{"type":32,"tag":33,"props":982,"children":983},{},[984,986,991,993,999],{"type":37,"value":985},"Para resolver esto, debes validar MMM con ",{"type":32,"tag":40,"props":987,"children":988},{},[989],{"type":37,"value":990},"pruebas de incrementalidad",{"type":37,"value":992},". Mide el efecto causal real con geo-lift o holdout test y compáralo con los resultados de MMM. Robyn puede incluir resultados de incrementalidad como parámetro ",{"type":32,"tag":129,"props":994,"children":996},{"className":995},[],[997],{"type":37,"value":998},"calibration",{"type":37,"value":1000}," — esto actúa como prior bayesiano y acerca el modelo a la realidad.",{"type":32,"tag":33,"props":1002,"children":1003},{},[1004,1006,1011],{"type":37,"value":1005},"Otra dificultad es ",{"type":32,"tag":40,"props":1007,"children":1008},{},[1009],{"type":37,"value":1010},"integrar canales nuevos",{"type":37,"value":1012},". Si abres un canal nuevo (por ejemplo Snapchat) y solo tienes 8 semanas de datos, Robyn no puede aprender su curva de saturación. En este caso, debes establecer el prior manualmente o excluir las primeras 12 semanas e integrarlo después.",{"type":32,"tag":33,"props":1014,"children":1015},{},[1016,1018,1023],{"type":37,"value":1017},"Finalmente, MMM es ",{"type":32,"tag":40,"props":1019,"children":1020},{},[1021],{"type":37,"value":1022},"más fuerte cuando combina offline y online",{"type":37,"value":1024},". Si no incluyes el gasto en canales offline como TV, outdoor, patrocinios, el modelo da demasiado crédito a los canales online (sesgo de variable omitida). Robyn es flexible en esto: acepta variables proxy como GRP, reach, o incluso volumen de búsqueda de marca.",{"type":32,"tag":33,"props":1026,"children":1027},{},[1028],{"type":37,"value":1029},"Un pipeline MMM correctamente configurado transforma la planificación presupuestaria del equipo de marketing de un juego de adivinanzas a ingeniería basada en evidencia. Robyn hace accesible esta transformación como código abierto — pero la estructura de datos, tuning de hiperparámetros y validación de incrementalidad requieren experiencia humana. Los equipos que invierten en regresión econométrica en lugar de atribución en 2026 estarán 12 meses adelante de sus competidores en 2027.",{"type":32,"tag":1031,"props":1032,"children":1033},"style",{},[1034],{"type":37,"value":1035},"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":1037},[1038,1039,1040,1041,1042,1043],{"id":50,"depth":145,"text":53},{"id":112,"depth":145,"text":115},{"id":352,"depth":145,"text":355},{"id":529,"depth":145,"text":532},{"id":832,"depth":145,"text":835},{"id":958,"depth":145,"text":961},"markdown","content:es:data:marketing-mix-modeling-robyn-setup-practico.md","content","es\u002Fdata\u002Fmarketing-mix-modeling-robyn-setup-practico.md","es\u002Fdata\u002Fmarketing-mix-modeling-robyn-setup-practico","md",1782079490840]