[{"data":1,"prerenderedAt":3071},["ShallowReactive",2],{"article-alternates":3,"article-\u002Fes\u002Fdata\u002Fdbt-bigquery-modern-stack-marketing-data":10},{"i18nKey":4,"paths":5},"data-002-2026-06",{"es":6,"fr":7,"it":8,"ru":9},"\u002Fes\u002Fdata\u002Fdbt-bigquery-modern-stack-marketing-data","\u002Ffr\u002Fdata\u002Fdbt-bigquery-modern-pazarlama-data-stack","\u002Fit\u002Fdata\u002Fdbt-bigquery-modern-pazarlama-data-stack","\u002Fru\u002Fdata\u002Fdbt-bigquery-sovremenniy-marketing-data-stack",{"_path":6,"_dir":11,"_draft":12,"_partial":12,"_locale":13,"title":14,"description":15,"publishedAt":16,"modifiedAt":16,"category":17,"i18nKey":4,"tags":18,"readingTime":24,"author":25,"body":26,"_type":3065,"_id":3066,"_source":3067,"_file":3068,"_stem":3069,"_extension":3070},"data",false,"","dbt + BigQuery: Modern Marketing Data Stack","Source mapping, modeling layer, semantic layer, exposures: transformar datos de marketing en mecanismo de decisión con arquitectura production-ready.","2026-06-30","verianalizi",[19,20,21,22,23],"dbt","bigquery","data-modeling","semantic-layer","marketing-analytics",8,"Roibase",{"type":27,"children":28,"toc":3052},"root",[29,37,44,66,464,498,547,554,583,962,991,997,1024,1034,1218,1228,1446,1456,1690,1719,1725,1730,2003,2027,2033,2046,2427,2444,2449,2507,2520,2526,2539,2916,2937,2943,2948,3020,3025,3031,3036,3041,3046],{"type":30,"tag":31,"props":32,"children":33},"element","p",{},[34],{"type":35,"value":36},"text","Los equipos de marketing todavía producen reportes con tablas dinámicas de Excel, los equipos de datos reescriben SQL para cada pregunta nueva, los KPI no concuerdan entre departamentos. En 2026, tolerar este escenario es un error de ingeniería. El modern marketing data stack funciona en tres capas: integración de fuentes raw, capa de transformación, capa semántica. dbt + BigQuery ofrece estas tres capas a nivel production-grade — con control de versiones, cobertura de tests, y tracking de linaje incluidos.",{"type":30,"tag":38,"props":39,"children":41},"h2",{"id":40},"source-mapping-transportar-datos-raw-a-zona-segura",[42],{"type":35,"value":43},"Source Mapping: Transportar Datos Raw a Zona Segura",{"type":30,"tag":31,"props":45,"children":46},{},[47,49,56,58,64],{"type":35,"value":48},"Traer datos de marketing a BigQuery parece fácil: herramientas ETL como Fivetran, Stitch, o Airbyte escriben GA4, Meta Ads, Google Ads directamente en el esquema ",{"type":30,"tag":50,"props":51,"children":53},"code",{"className":52},[],[54],{"type":35,"value":55},"raw_",{"type":35,"value":57},". Pero después de 6 meses, cuando el esquema cambia, los modelos downstream explota. Las ",{"type":30,"tag":59,"props":60,"children":61},"strong",{},[62],{"type":35,"value":63},"definiciones de source",{"type":35,"value":65}," de dbt controlan este riesgo.",{"type":30,"tag":67,"props":68,"children":72},"pre",{"className":69,"code":70,"language":71,"meta":13,"style":13},"language-yaml shiki shiki-themes github-dark","# models\u002Fsources.yml\nversion: 2\n\nsources:\n  - name: ga4\n    database: analytics_prod\n    schema: raw_ga4\n    tables:\n      - name: events_*\n        freshness:\n          warn_after: {count: 6, period: hour}\n          error_after: {count: 12, period: hour}\n        loaded_at_field: event_timestamp\n        columns:\n          - name: event_name\n            tests:\n              - not_null\n          - name: user_pseudo_id\n            tests:\n              - not_null\n","yaml",[73],{"type":30,"tag":50,"props":74,"children":75},{"__ignoreMap":13},[76,88,110,120,134,158,176,194,206,228,241,293,339,357,370,392,405,419,440,452],{"type":30,"tag":77,"props":78,"children":81},"span",{"class":79,"line":80},"line",1,[82],{"type":30,"tag":77,"props":83,"children":85},{"style":84},"--shiki-default:#6A737D",[86],{"type":35,"value":87},"# models\u002Fsources.yml\n",{"type":30,"tag":77,"props":89,"children":91},{"class":79,"line":90},2,[92,98,104],{"type":30,"tag":77,"props":93,"children":95},{"style":94},"--shiki-default:#85E89D",[96],{"type":35,"value":97},"version",{"type":30,"tag":77,"props":99,"children":101},{"style":100},"--shiki-default:#E1E4E8",[102],{"type":35,"value":103},": ",{"type":30,"tag":77,"props":105,"children":107},{"style":106},"--shiki-default:#79B8FF",[108],{"type":35,"value":109},"2\n",{"type":30,"tag":77,"props":111,"children":113},{"class":79,"line":112},3,[114],{"type":30,"tag":77,"props":115,"children":117},{"emptyLinePlaceholder":116},true,[118],{"type":35,"value":119},"\n",{"type":30,"tag":77,"props":121,"children":123},{"class":79,"line":122},4,[124,129],{"type":30,"tag":77,"props":125,"children":126},{"style":94},[127],{"type":35,"value":128},"sources",{"type":30,"tag":77,"props":130,"children":131},{"style":100},[132],{"type":35,"value":133},":\n",{"type":30,"tag":77,"props":135,"children":137},{"class":79,"line":136},5,[138,143,148,152],{"type":30,"tag":77,"props":139,"children":140},{"style":100},[141],{"type":35,"value":142},"  - ",{"type":30,"tag":77,"props":144,"children":145},{"style":94},[146],{"type":35,"value":147},"name",{"type":30,"tag":77,"props":149,"children":150},{"style":100},[151],{"type":35,"value":103},{"type":30,"tag":77,"props":153,"children":155},{"style":154},"--shiki-default:#9ECBFF",[156],{"type":35,"value":157},"ga4\n",{"type":30,"tag":77,"props":159,"children":161},{"class":79,"line":160},6,[162,167,171],{"type":30,"tag":77,"props":163,"children":164},{"style":94},[165],{"type":35,"value":166},"    database",{"type":30,"tag":77,"props":168,"children":169},{"style":100},[170],{"type":35,"value":103},{"type":30,"tag":77,"props":172,"children":173},{"style":154},[174],{"type":35,"value":175},"analytics_prod\n",{"type":30,"tag":77,"props":177,"children":179},{"class":79,"line":178},7,[180,185,189],{"type":30,"tag":77,"props":181,"children":182},{"style":94},[183],{"type":35,"value":184},"    schema",{"type":30,"tag":77,"props":186,"children":187},{"style":100},[188],{"type":35,"value":103},{"type":30,"tag":77,"props":190,"children":191},{"style":154},[192],{"type":35,"value":193},"raw_ga4\n",{"type":30,"tag":77,"props":195,"children":196},{"class":79,"line":24},[197,202],{"type":30,"tag":77,"props":198,"children":199},{"style":94},[200],{"type":35,"value":201},"    tables",{"type":30,"tag":77,"props":203,"children":204},{"style":100},[205],{"type":35,"value":133},{"type":30,"tag":77,"props":207,"children":209},{"class":79,"line":208},9,[210,215,219,223],{"type":30,"tag":77,"props":211,"children":212},{"style":100},[213],{"type":35,"value":214},"      - ",{"type":30,"tag":77,"props":216,"children":217},{"style":94},[218],{"type":35,"value":147},{"type":30,"tag":77,"props":220,"children":221},{"style":100},[222],{"type":35,"value":103},{"type":30,"tag":77,"props":224,"children":225},{"style":154},[226],{"type":35,"value":227},"events_*\n",{"type":30,"tag":77,"props":229,"children":231},{"class":79,"line":230},10,[232,237],{"type":30,"tag":77,"props":233,"children":234},{"style":94},[235],{"type":35,"value":236},"        freshness",{"type":30,"tag":77,"props":238,"children":239},{"style":100},[240],{"type":35,"value":133},{"type":30,"tag":77,"props":242,"children":244},{"class":79,"line":243},11,[245,250,255,260,264,269,274,279,283,288],{"type":30,"tag":77,"props":246,"children":247},{"style":94},[248],{"type":35,"value":249},"          warn_after",{"type":30,"tag":77,"props":251,"children":252},{"style":100},[253],{"type":35,"value":254},": {",{"type":30,"tag":77,"props":256,"children":257},{"style":94},[258],{"type":35,"value":259},"count",{"type":30,"tag":77,"props":261,"children":262},{"style":100},[263],{"type":35,"value":103},{"type":30,"tag":77,"props":265,"children":266},{"style":106},[267],{"type":35,"value":268},"6",{"type":30,"tag":77,"props":270,"children":271},{"style":100},[272],{"type":35,"value":273},", ",{"type":30,"tag":77,"props":275,"children":276},{"style":94},[277],{"type":35,"value":278},"period",{"type":30,"tag":77,"props":280,"children":281},{"style":100},[282],{"type":35,"value":103},{"type":30,"tag":77,"props":284,"children":285},{"style":154},[286],{"type":35,"value":287},"hour",{"type":30,"tag":77,"props":289,"children":290},{"style":100},[291],{"type":35,"value":292},"}\n",{"type":30,"tag":77,"props":294,"children":296},{"class":79,"line":295},12,[297,302,306,310,314,319,323,327,331,335],{"type":30,"tag":77,"props":298,"children":299},{"style":94},[300],{"type":35,"value":301},"          error_after",{"type":30,"tag":77,"props":303,"children":304},{"style":100},[305],{"type":35,"value":254},{"type":30,"tag":77,"props":307,"children":308},{"style":94},[309],{"type":35,"value":259},{"type":30,"tag":77,"props":311,"children":312},{"style":100},[313],{"type":35,"value":103},{"type":30,"tag":77,"props":315,"children":316},{"style":106},[317],{"type":35,"value":318},"12",{"type":30,"tag":77,"props":320,"children":321},{"style":100},[322],{"type":35,"value":273},{"type":30,"tag":77,"props":324,"children":325},{"style":94},[326],{"type":35,"value":278},{"type":30,"tag":77,"props":328,"children":329},{"style":100},[330],{"type":35,"value":103},{"type":30,"tag":77,"props":332,"children":333},{"style":154},[334],{"type":35,"value":287},{"type":30,"tag":77,"props":336,"children":337},{"style":100},[338],{"type":35,"value":292},{"type":30,"tag":77,"props":340,"children":342},{"class":79,"line":341},13,[343,348,352],{"type":30,"tag":77,"props":344,"children":345},{"style":94},[346],{"type":35,"value":347},"        loaded_at_field",{"type":30,"tag":77,"props":349,"children":350},{"style":100},[351],{"type":35,"value":103},{"type":30,"tag":77,"props":353,"children":354},{"style":154},[355],{"type":35,"value":356},"event_timestamp\n",{"type":30,"tag":77,"props":358,"children":360},{"class":79,"line":359},14,[361,366],{"type":30,"tag":77,"props":362,"children":363},{"style":94},[364],{"type":35,"value":365},"        columns",{"type":30,"tag":77,"props":367,"children":368},{"style":100},[369],{"type":35,"value":133},{"type":30,"tag":77,"props":371,"children":373},{"class":79,"line":372},15,[374,379,383,387],{"type":30,"tag":77,"props":375,"children":376},{"style":100},[377],{"type":35,"value":378},"          - ",{"type":30,"tag":77,"props":380,"children":381},{"style":94},[382],{"type":35,"value":147},{"type":30,"tag":77,"props":384,"children":385},{"style":100},[386],{"type":35,"value":103},{"type":30,"tag":77,"props":388,"children":389},{"style":154},[390],{"type":35,"value":391},"event_name\n",{"type":30,"tag":77,"props":393,"children":395},{"class":79,"line":394},16,[396,401],{"type":30,"tag":77,"props":397,"children":398},{"style":94},[399],{"type":35,"value":400},"            tests",{"type":30,"tag":77,"props":402,"children":403},{"style":100},[404],{"type":35,"value":133},{"type":30,"tag":77,"props":406,"children":408},{"class":79,"line":407},17,[409,414],{"type":30,"tag":77,"props":410,"children":411},{"style":100},[412],{"type":35,"value":413},"              - ",{"type":30,"tag":77,"props":415,"children":416},{"style":154},[417],{"type":35,"value":418},"not_null\n",{"type":30,"tag":77,"props":420,"children":422},{"class":79,"line":421},18,[423,427,431,435],{"type":30,"tag":77,"props":424,"children":425},{"style":100},[426],{"type":35,"value":378},{"type":30,"tag":77,"props":428,"children":429},{"style":94},[430],{"type":35,"value":147},{"type":30,"tag":77,"props":432,"children":433},{"style":100},[434],{"type":35,"value":103},{"type":30,"tag":77,"props":436,"children":437},{"style":154},[438],{"type":35,"value":439},"user_pseudo_id\n",{"type":30,"tag":77,"props":441,"children":443},{"class":79,"line":442},19,[444,448],{"type":30,"tag":77,"props":445,"children":446},{"style":94},[447],{"type":35,"value":400},{"type":30,"tag":77,"props":449,"children":450},{"style":100},[451],{"type":35,"value":133},{"type":30,"tag":77,"props":453,"children":455},{"class":79,"line":454},20,[456,460],{"type":30,"tag":77,"props":457,"children":458},{"style":100},[459],{"type":35,"value":413},{"type":30,"tag":77,"props":461,"children":462},{"style":154},[463],{"type":35,"value":418},{"type":30,"tag":31,"props":465,"children":466},{},[467,469,474,476,482,484,489,491,496],{"type":35,"value":468},"Una definición de source cumple tres funciones: ",{"type":30,"tag":59,"props":470,"children":471},{},[472],{"type":35,"value":473},"(1)",{"type":35,"value":475}," alarma en cambios upstream (la métrica ",{"type":30,"tag":50,"props":477,"children":479},{"className":478},[],[480],{"type":35,"value":481},"freshness",{"type":35,"value":483}," envía a Slack), ",{"type":30,"tag":59,"props":485,"children":486},{},[487],{"type":35,"value":488},"(2)",{"type":35,"value":490}," contrato de esquema (la lista de columns aparece como documentación), ",{"type":30,"tag":59,"props":492,"children":493},{},[494],{"type":35,"value":495},"(3)",{"type":35,"value":497}," tracking de linaje (dbt docs muestra cuáles modelos dependen de GA4). Si Fivetran cambia el esquema, recibirás un error al compilar dbt — sin explosiones en producción.",{"type":30,"tag":31,"props":499,"children":500},{},[501,503,509,510,516,517,523,524,530,531,537,539,545],{"type":35,"value":502},"En la fase de source mapping, etiqueta también las señales de identidad: ",{"type":30,"tag":50,"props":504,"children":506},{"className":505},[],[507],{"type":35,"value":508},"user_id",{"type":35,"value":273},{"type":30,"tag":50,"props":511,"children":513},{"className":512},[],[514],{"type":35,"value":515},"client_id",{"type":35,"value":273},{"type":30,"tag":50,"props":518,"children":520},{"className":519},[],[521],{"type":35,"value":522},"fbclid",{"type":35,"value":273},{"type":30,"tag":50,"props":525,"children":527},{"className":526},[],[528],{"type":35,"value":529},"gclid",{"type":35,"value":273},{"type":30,"tag":50,"props":532,"children":534},{"className":533},[],[535],{"type":35,"value":536},"email_sha256",{"type":35,"value":538},". Más adelante en la modeling layer, mapearás estas señales a un único ",{"type":30,"tag":50,"props":540,"children":542},{"className":541},[],[543],{"type":35,"value":544},"customer_id",{"type":35,"value":546},". Perder señales en la tabla raw hace imposible el trabajo downstream.",{"type":30,"tag":548,"props":549,"children":551},"h3",{"id":550},"estrategia-de-tabla-particionada",[552],{"type":35,"value":553},"Estrategia de Tabla Particionada",{"type":30,"tag":31,"props":555,"children":556},{},[557,559,565,567,573,575,581],{"type":35,"value":558},"La tabla wildcard ",{"type":30,"tag":50,"props":560,"children":562},{"className":561},[],[563],{"type":35,"value":564},"events_*",{"type":35,"value":566}," de GA4 es diaria (",{"type":30,"tag":50,"props":568,"children":570},{"className":569},[],[571],{"type":35,"value":572},"events_20260630",{"type":35,"value":574},"). En dbt, define el source con wildcard y agrega filtro con ",{"type":30,"tag":50,"props":576,"children":578},{"className":577},[],[579],{"type":35,"value":580},"_TABLE_SUFFIX",{"type":35,"value":582},":",{"type":30,"tag":67,"props":584,"children":588},{"className":585,"code":586,"language":587,"meta":13,"style":13},"language-sql shiki shiki-themes github-dark","-- models\u002Fstaging\u002Fstg_ga4_events.sql\n{{\n  config(\n    materialized='incremental',\n    partition_by={'field': 'event_date', 'data_type': 'date'},\n    cluster_by=['event_name', 'user_pseudo_id']\n  )\n}}\n\nselect\n  parse_date('%Y%m%d', _table_suffix) as event_date,\n  event_timestamp,\n  event_name,\n  user_pseudo_id,\n  ...\nfrom {{ source('ga4', 'events_*') }}\nwhere _table_suffix >= format_date('%Y%m%d', date_sub(current_date(), interval 3 day))\n{% if is_incremental() %}\n  and parse_date('%Y%m%d', _table_suffix) > (select max(event_date) from {{ this }})\n{% endif %}\n","sql",[589],{"type":30,"tag":50,"props":590,"children":591},{"__ignoreMap":13},[592,600,608,616,640,694,711,719,727,734,742,770,778,786,794,802,834,881,899,954],{"type":30,"tag":77,"props":593,"children":594},{"class":79,"line":80},[595],{"type":30,"tag":77,"props":596,"children":597},{"style":84},[598],{"type":35,"value":599},"-- models\u002Fstaging\u002Fstg_ga4_events.sql\n",{"type":30,"tag":77,"props":601,"children":602},{"class":79,"line":90},[603],{"type":30,"tag":77,"props":604,"children":605},{"style":100},[606],{"type":35,"value":607},"{{\n",{"type":30,"tag":77,"props":609,"children":610},{"class":79,"line":112},[611],{"type":30,"tag":77,"props":612,"children":613},{"style":100},[614],{"type":35,"value":615},"  config(\n",{"type":30,"tag":77,"props":617,"children":618},{"class":79,"line":122},[619,624,630,635],{"type":30,"tag":77,"props":620,"children":621},{"style":100},[622],{"type":35,"value":623},"    materialized",{"type":30,"tag":77,"props":625,"children":627},{"style":626},"--shiki-default:#F97583",[628],{"type":35,"value":629},"=",{"type":30,"tag":77,"props":631,"children":632},{"style":154},[633],{"type":35,"value":634},"'incremental'",{"type":30,"tag":77,"props":636,"children":637},{"style":100},[638],{"type":35,"value":639},",\n",{"type":30,"tag":77,"props":641,"children":642},{"class":79,"line":136},[643,648,652,657,662,666,671,675,680,684,689],{"type":30,"tag":77,"props":644,"children":645},{"style":100},[646],{"type":35,"value":647},"    partition_by",{"type":30,"tag":77,"props":649,"children":650},{"style":626},[651],{"type":35,"value":629},{"type":30,"tag":77,"props":653,"children":654},{"style":100},[655],{"type":35,"value":656},"{",{"type":30,"tag":77,"props":658,"children":659},{"style":154},[660],{"type":35,"value":661},"'field'",{"type":30,"tag":77,"props":663,"children":664},{"style":100},[665],{"type":35,"value":103},{"type":30,"tag":77,"props":667,"children":668},{"style":154},[669],{"type":35,"value":670},"'event_date'",{"type":30,"tag":77,"props":672,"children":673},{"style":100},[674],{"type":35,"value":273},{"type":30,"tag":77,"props":676,"children":677},{"style":154},[678],{"type":35,"value":679},"'data_type'",{"type":30,"tag":77,"props":681,"children":682},{"style":100},[683],{"type":35,"value":103},{"type":30,"tag":77,"props":685,"children":686},{"style":154},[687],{"type":35,"value":688},"'date'",{"type":30,"tag":77,"props":690,"children":691},{"style":100},[692],{"type":35,"value":693},"},\n",{"type":30,"tag":77,"props":695,"children":696},{"class":79,"line":160},[697,702,706],{"type":30,"tag":77,"props":698,"children":699},{"style":100},[700],{"type":35,"value":701},"    cluster_by",{"type":30,"tag":77,"props":703,"children":704},{"style":626},[705],{"type":35,"value":629},{"type":30,"tag":77,"props":707,"children":708},{"style":100},[709],{"type":35,"value":710},"['event_name', 'user_pseudo_id']\n",{"type":30,"tag":77,"props":712,"children":713},{"class":79,"line":178},[714],{"type":30,"tag":77,"props":715,"children":716},{"style":100},[717],{"type":35,"value":718},"  )\n",{"type":30,"tag":77,"props":720,"children":721},{"class":79,"line":24},[722],{"type":30,"tag":77,"props":723,"children":724},{"style":100},[725],{"type":35,"value":726},"}}\n",{"type":30,"tag":77,"props":728,"children":729},{"class":79,"line":208},[730],{"type":30,"tag":77,"props":731,"children":732},{"emptyLinePlaceholder":116},[733],{"type":35,"value":119},{"type":30,"tag":77,"props":735,"children":736},{"class":79,"line":230},[737],{"type":30,"tag":77,"props":738,"children":739},{"style":626},[740],{"type":35,"value":741},"select\n",{"type":30,"tag":77,"props":743,"children":744},{"class":79,"line":243},[745,750,755,760,765],{"type":30,"tag":77,"props":746,"children":747},{"style":100},[748],{"type":35,"value":749},"  parse_date(",{"type":30,"tag":77,"props":751,"children":752},{"style":154},[753],{"type":35,"value":754},"'%Y%m%d'",{"type":30,"tag":77,"props":756,"children":757},{"style":100},[758],{"type":35,"value":759},", _table_suffix) ",{"type":30,"tag":77,"props":761,"children":762},{"style":626},[763],{"type":35,"value":764},"as",{"type":30,"tag":77,"props":766,"children":767},{"style":100},[768],{"type":35,"value":769}," event_date,\n",{"type":30,"tag":77,"props":771,"children":772},{"class":79,"line":295},[773],{"type":30,"tag":77,"props":774,"children":775},{"style":100},[776],{"type":35,"value":777},"  event_timestamp,\n",{"type":30,"tag":77,"props":779,"children":780},{"class":79,"line":341},[781],{"type":30,"tag":77,"props":782,"children":783},{"style":100},[784],{"type":35,"value":785},"  event_name,\n",{"type":30,"tag":77,"props":787,"children":788},{"class":79,"line":359},[789],{"type":30,"tag":77,"props":790,"children":791},{"style":100},[792],{"type":35,"value":793},"  user_pseudo_id,\n",{"type":30,"tag":77,"props":795,"children":796},{"class":79,"line":372},[797],{"type":30,"tag":77,"props":798,"children":799},{"style":100},[800],{"type":35,"value":801},"  ...\n",{"type":30,"tag":77,"props":803,"children":804},{"class":79,"line":394},[805,810,815,820,824,829],{"type":30,"tag":77,"props":806,"children":807},{"style":626},[808],{"type":35,"value":809},"from",{"type":30,"tag":77,"props":811,"children":812},{"style":100},[813],{"type":35,"value":814}," {{ source(",{"type":30,"tag":77,"props":816,"children":817},{"style":154},[818],{"type":35,"value":819},"'ga4'",{"type":30,"tag":77,"props":821,"children":822},{"style":100},[823],{"type":35,"value":273},{"type":30,"tag":77,"props":825,"children":826},{"style":154},[827],{"type":35,"value":828},"'events_*'",{"type":30,"tag":77,"props":830,"children":831},{"style":100},[832],{"type":35,"value":833},") }}\n",{"type":30,"tag":77,"props":835,"children":836},{"class":79,"line":407},[837,842,847,852,857,861,866,871,876],{"type":30,"tag":77,"props":838,"children":839},{"style":626},[840],{"type":35,"value":841},"where",{"type":30,"tag":77,"props":843,"children":844},{"style":100},[845],{"type":35,"value":846}," _table_suffix ",{"type":30,"tag":77,"props":848,"children":849},{"style":626},[850],{"type":35,"value":851},">=",{"type":30,"tag":77,"props":853,"children":854},{"style":100},[855],{"type":35,"value":856}," format_date(",{"type":30,"tag":77,"props":858,"children":859},{"style":154},[860],{"type":35,"value":754},{"type":30,"tag":77,"props":862,"children":863},{"style":100},[864],{"type":35,"value":865},", date_sub(current_date(), interval ",{"type":30,"tag":77,"props":867,"children":868},{"style":106},[869],{"type":35,"value":870},"3",{"type":30,"tag":77,"props":872,"children":873},{"style":626},[874],{"type":35,"value":875}," day",{"type":30,"tag":77,"props":877,"children":878},{"style":100},[879],{"type":35,"value":880},"))\n",{"type":30,"tag":77,"props":882,"children":883},{"class":79,"line":421},[884,889,894],{"type":30,"tag":77,"props":885,"children":886},{"style":100},[887],{"type":35,"value":888},"{% ",{"type":30,"tag":77,"props":890,"children":891},{"style":626},[892],{"type":35,"value":893},"if",{"type":30,"tag":77,"props":895,"children":896},{"style":100},[897],{"type":35,"value":898}," is_incremental() %}\n",{"type":30,"tag":77,"props":900,"children":901},{"class":79,"line":442},[902,907,912,916,920,925,930,935,940,945,949],{"type":30,"tag":77,"props":903,"children":904},{"style":626},[905],{"type":35,"value":906},"  and",{"type":30,"tag":77,"props":908,"children":909},{"style":100},[910],{"type":35,"value":911}," parse_date(",{"type":30,"tag":77,"props":913,"children":914},{"style":154},[915],{"type":35,"value":754},{"type":30,"tag":77,"props":917,"children":918},{"style":100},[919],{"type":35,"value":759},{"type":30,"tag":77,"props":921,"children":922},{"style":626},[923],{"type":35,"value":924},">",{"type":30,"tag":77,"props":926,"children":927},{"style":100},[928],{"type":35,"value":929}," (",{"type":30,"tag":77,"props":931,"children":932},{"style":626},[933],{"type":35,"value":934},"select",{"type":30,"tag":77,"props":936,"children":937},{"style":106},[938],{"type":35,"value":939}," max",{"type":30,"tag":77,"props":941,"children":942},{"style":100},[943],{"type":35,"value":944},"(event_date) ",{"type":30,"tag":77,"props":946,"children":947},{"style":626},[948],{"type":35,"value":809},{"type":30,"tag":77,"props":950,"children":951},{"style":100},[952],{"type":35,"value":953}," {{ this }})\n",{"type":30,"tag":77,"props":955,"children":956},{"class":79,"line":454},[957],{"type":30,"tag":77,"props":958,"children":959},{"style":100},[960],{"type":35,"value":961},"{% endif %}\n",{"type":30,"tag":31,"props":963,"children":964},{},[965,967,973,975,981,983,989],{"type":35,"value":966},"Esta configuración escribe la tabla ",{"type":30,"tag":50,"props":968,"children":970},{"className":969},[],[971],{"type":35,"value":972},"stg_ga4_events",{"type":35,"value":974}," en BigQuery con particiones diarias, y el clustering en ",{"type":30,"tag":50,"props":976,"children":978},{"className":977},[],[979],{"type":35,"value":980},"event_name",{"type":35,"value":982}," + ",{"type":30,"tag":50,"props":984,"children":986},{"className":985},[],[987],{"type":35,"value":988},"user_pseudo_id",{"type":35,"value":990}," reduce el costo de query. La materialización incremental reduce el escaneo de 90 días de history a 3 días — reducción de costo de 30×.",{"type":30,"tag":38,"props":992,"children":994},{"id":993},"modeling-layer-codifica-la-lógica-de-negocio",[995],{"type":35,"value":996},"Modeling Layer: Codifica la Lógica de Negocio",{"type":30,"tag":31,"props":998,"children":999},{},[1000,1002,1008,1009,1015,1016,1022],{"type":35,"value":1001},"La capa staging limpia el raw, la capa intermediate construye la lógica de join, la capa marts responde preguntas de negocio. dbt separa estas tres capas por estructura de carpetas: ",{"type":30,"tag":50,"props":1003,"children":1005},{"className":1004},[],[1006],{"type":35,"value":1007},"staging\u002F",{"type":35,"value":273},{"type":30,"tag":50,"props":1010,"children":1012},{"className":1011},[],[1013],{"type":35,"value":1014},"intermediate\u002F",{"type":35,"value":273},{"type":30,"tag":50,"props":1017,"children":1019},{"className":1018},[],[1020],{"type":35,"value":1021},"marts\u002F",{"type":35,"value":1023},".",{"type":30,"tag":31,"props":1025,"children":1026},{},[1027,1032],{"type":30,"tag":59,"props":1028,"children":1029},{},[1030],{"type":35,"value":1031},"Ejemplo de staging",{"type":35,"value":1033}," — estandariza columnas de Meta Ads:",{"type":30,"tag":67,"props":1035,"children":1037},{"className":585,"code":1036,"language":587,"meta":13,"style":13},"-- models\u002Fstaging\u002Fstg_meta_ads.sql\nselect\n  date_start as report_date,\n  campaign_id,\n  campaign_name,\n  spend as cost_usd,\n  impressions,\n  clicks,\n  actions.value as conversions -- extrae del JSON anidado\nfrom {{ source('meta_ads', 'ads_insights') }}\nwhere date_start >= date_sub(current_date(), interval 90 day)\n",[1038],{"type":30,"tag":50,"props":1039,"children":1040},{"__ignoreMap":13},[1041,1049,1056,1073,1081,1089,1106,1114,1122,1154,1183],{"type":30,"tag":77,"props":1042,"children":1043},{"class":79,"line":80},[1044],{"type":30,"tag":77,"props":1045,"children":1046},{"style":84},[1047],{"type":35,"value":1048},"-- models\u002Fstaging\u002Fstg_meta_ads.sql\n",{"type":30,"tag":77,"props":1050,"children":1051},{"class":79,"line":90},[1052],{"type":30,"tag":77,"props":1053,"children":1054},{"style":626},[1055],{"type":35,"value":741},{"type":30,"tag":77,"props":1057,"children":1058},{"class":79,"line":112},[1059,1064,1068],{"type":30,"tag":77,"props":1060,"children":1061},{"style":100},[1062],{"type":35,"value":1063},"  date_start ",{"type":30,"tag":77,"props":1065,"children":1066},{"style":626},[1067],{"type":35,"value":764},{"type":30,"tag":77,"props":1069,"children":1070},{"style":100},[1071],{"type":35,"value":1072}," report_date,\n",{"type":30,"tag":77,"props":1074,"children":1075},{"class":79,"line":122},[1076],{"type":30,"tag":77,"props":1077,"children":1078},{"style":100},[1079],{"type":35,"value":1080},"  campaign_id,\n",{"type":30,"tag":77,"props":1082,"children":1083},{"class":79,"line":136},[1084],{"type":30,"tag":77,"props":1085,"children":1086},{"style":100},[1087],{"type":35,"value":1088},"  campaign_name,\n",{"type":30,"tag":77,"props":1090,"children":1091},{"class":79,"line":160},[1092,1097,1101],{"type":30,"tag":77,"props":1093,"children":1094},{"style":100},[1095],{"type":35,"value":1096},"  spend ",{"type":30,"tag":77,"props":1098,"children":1099},{"style":626},[1100],{"type":35,"value":764},{"type":30,"tag":77,"props":1102,"children":1103},{"style":100},[1104],{"type":35,"value":1105}," cost_usd,\n",{"type":30,"tag":77,"props":1107,"children":1108},{"class":79,"line":178},[1109],{"type":30,"tag":77,"props":1110,"children":1111},{"style":100},[1112],{"type":35,"value":1113},"  impressions,\n",{"type":30,"tag":77,"props":1115,"children":1116},{"class":79,"line":24},[1117],{"type":30,"tag":77,"props":1118,"children":1119},{"style":100},[1120],{"type":35,"value":1121},"  clicks,\n",{"type":30,"tag":77,"props":1123,"children":1124},{"class":79,"line":208},[1125,1130,1134,1139,1144,1149],{"type":30,"tag":77,"props":1126,"children":1127},{"style":106},[1128],{"type":35,"value":1129},"  actions",{"type":30,"tag":77,"props":1131,"children":1132},{"style":100},[1133],{"type":35,"value":1023},{"type":30,"tag":77,"props":1135,"children":1136},{"style":106},[1137],{"type":35,"value":1138},"value",{"type":30,"tag":77,"props":1140,"children":1141},{"style":626},[1142],{"type":35,"value":1143}," as",{"type":30,"tag":77,"props":1145,"children":1146},{"style":100},[1147],{"type":35,"value":1148}," conversions ",{"type":30,"tag":77,"props":1150,"children":1151},{"style":84},[1152],{"type":35,"value":1153},"-- extrae del JSON anidado\n",{"type":30,"tag":77,"props":1155,"children":1156},{"class":79,"line":230},[1157,1161,1165,1170,1174,1179],{"type":30,"tag":77,"props":1158,"children":1159},{"style":626},[1160],{"type":35,"value":809},{"type":30,"tag":77,"props":1162,"children":1163},{"style":100},[1164],{"type":35,"value":814},{"type":30,"tag":77,"props":1166,"children":1167},{"style":154},[1168],{"type":35,"value":1169},"'meta_ads'",{"type":30,"tag":77,"props":1171,"children":1172},{"style":100},[1173],{"type":35,"value":273},{"type":30,"tag":77,"props":1175,"children":1176},{"style":154},[1177],{"type":35,"value":1178},"'ads_insights'",{"type":30,"tag":77,"props":1180,"children":1181},{"style":100},[1182],{"type":35,"value":833},{"type":30,"tag":77,"props":1184,"children":1185},{"class":79,"line":243},[1186,1190,1195,1199,1204,1209,1213],{"type":30,"tag":77,"props":1187,"children":1188},{"style":626},[1189],{"type":35,"value":841},{"type":30,"tag":77,"props":1191,"children":1192},{"style":100},[1193],{"type":35,"value":1194}," date_start ",{"type":30,"tag":77,"props":1196,"children":1197},{"style":626},[1198],{"type":35,"value":851},{"type":30,"tag":77,"props":1200,"children":1201},{"style":100},[1202],{"type":35,"value":1203}," date_sub(current_date(), interval ",{"type":30,"tag":77,"props":1205,"children":1206},{"style":106},[1207],{"type":35,"value":1208},"90",{"type":30,"tag":77,"props":1210,"children":1211},{"style":626},[1212],{"type":35,"value":875},{"type":30,"tag":77,"props":1214,"children":1215},{"style":100},[1216],{"type":35,"value":1217},")\n",{"type":30,"tag":31,"props":1219,"children":1220},{},[1221,1226],{"type":30,"tag":59,"props":1222,"children":1223},{},[1224],{"type":35,"value":1225},"Ejemplo de intermediate",{"type":35,"value":1227}," — unifica todas las fuentes de paid media:",{"type":30,"tag":67,"props":1229,"children":1231},{"className":585,"code":1230,"language":587,"meta":13,"style":13},"-- models\u002Fintermediate\u002Fint_paid_media_unified.sql\nwith meta as (\n  select report_date, campaign_id, 'meta' as source, cost_usd, impressions, clicks, conversions\n  from {{ ref('stg_meta_ads') }}\n),\ngoogle as (\n  select report_date, campaign_id, 'google' as source, cost_usd, impressions, clicks, conversions\n  from {{ ref('stg_google_ads') }}\n)\n\nselect * from meta\nunion all\nselect * from google\n",[1232],{"type":30,"tag":50,"props":1233,"children":1234},{"__ignoreMap":13},[1235,1243,1265,1292,1314,1322,1338,1362,1382,1389,1396,1418,1426],{"type":30,"tag":77,"props":1236,"children":1237},{"class":79,"line":80},[1238],{"type":30,"tag":77,"props":1239,"children":1240},{"style":84},[1241],{"type":35,"value":1242},"-- models\u002Fintermediate\u002Fint_paid_media_unified.sql\n",{"type":30,"tag":77,"props":1244,"children":1245},{"class":79,"line":90},[1246,1251,1256,1260],{"type":30,"tag":77,"props":1247,"children":1248},{"style":626},[1249],{"type":35,"value":1250},"with",{"type":30,"tag":77,"props":1252,"children":1253},{"style":100},[1254],{"type":35,"value":1255}," meta ",{"type":30,"tag":77,"props":1257,"children":1258},{"style":626},[1259],{"type":35,"value":764},{"type":30,"tag":77,"props":1261,"children":1262},{"style":100},[1263],{"type":35,"value":1264}," (\n",{"type":30,"tag":77,"props":1266,"children":1267},{"class":79,"line":112},[1268,1273,1278,1283,1287],{"type":30,"tag":77,"props":1269,"children":1270},{"style":626},[1271],{"type":35,"value":1272},"  select",{"type":30,"tag":77,"props":1274,"children":1275},{"style":100},[1276],{"type":35,"value":1277}," report_date, campaign_id, ",{"type":30,"tag":77,"props":1279,"children":1280},{"style":154},[1281],{"type":35,"value":1282},"'meta'",{"type":30,"tag":77,"props":1284,"children":1285},{"style":626},[1286],{"type":35,"value":1143},{"type":30,"tag":77,"props":1288,"children":1289},{"style":100},[1290],{"type":35,"value":1291}," source, cost_usd, impressions, clicks, conversions\n",{"type":30,"tag":77,"props":1293,"children":1294},{"class":79,"line":122},[1295,1300,1305,1310],{"type":30,"tag":77,"props":1296,"children":1297},{"style":626},[1298],{"type":35,"value":1299},"  from",{"type":30,"tag":77,"props":1301,"children":1302},{"style":100},[1303],{"type":35,"value":1304}," {{ ref(",{"type":30,"tag":77,"props":1306,"children":1307},{"style":154},[1308],{"type":35,"value":1309},"'stg_meta_ads'",{"type":30,"tag":77,"props":1311,"children":1312},{"style":100},[1313],{"type":35,"value":833},{"type":30,"tag":77,"props":1315,"children":1316},{"class":79,"line":136},[1317],{"type":30,"tag":77,"props":1318,"children":1319},{"style":100},[1320],{"type":35,"value":1321},"),\n",{"type":30,"tag":77,"props":1323,"children":1324},{"class":79,"line":160},[1325,1330,1334],{"type":30,"tag":77,"props":1326,"children":1327},{"style":100},[1328],{"type":35,"value":1329},"google ",{"type":30,"tag":77,"props":1331,"children":1332},{"style":626},[1333],{"type":35,"value":764},{"type":30,"tag":77,"props":1335,"children":1336},{"style":100},[1337],{"type":35,"value":1264},{"type":30,"tag":77,"props":1339,"children":1340},{"class":79,"line":178},[1341,1345,1349,1354,1358],{"type":30,"tag":77,"props":1342,"children":1343},{"style":626},[1344],{"type":35,"value":1272},{"type":30,"tag":77,"props":1346,"children":1347},{"style":100},[1348],{"type":35,"value":1277},{"type":30,"tag":77,"props":1350,"children":1351},{"style":154},[1352],{"type":35,"value":1353},"'google'",{"type":30,"tag":77,"props":1355,"children":1356},{"style":626},[1357],{"type":35,"value":1143},{"type":30,"tag":77,"props":1359,"children":1360},{"style":100},[1361],{"type":35,"value":1291},{"type":30,"tag":77,"props":1363,"children":1364},{"class":79,"line":24},[1365,1369,1373,1378],{"type":30,"tag":77,"props":1366,"children":1367},{"style":626},[1368],{"type":35,"value":1299},{"type":30,"tag":77,"props":1370,"children":1371},{"style":100},[1372],{"type":35,"value":1304},{"type":30,"tag":77,"props":1374,"children":1375},{"style":154},[1376],{"type":35,"value":1377},"'stg_google_ads'",{"type":30,"tag":77,"props":1379,"children":1380},{"style":100},[1381],{"type":35,"value":833},{"type":30,"tag":77,"props":1383,"children":1384},{"class":79,"line":208},[1385],{"type":30,"tag":77,"props":1386,"children":1387},{"style":100},[1388],{"type":35,"value":1217},{"type":30,"tag":77,"props":1390,"children":1391},{"class":79,"line":230},[1392],{"type":30,"tag":77,"props":1393,"children":1394},{"emptyLinePlaceholder":116},[1395],{"type":35,"value":119},{"type":30,"tag":77,"props":1397,"children":1398},{"class":79,"line":243},[1399,1403,1408,1413],{"type":30,"tag":77,"props":1400,"children":1401},{"style":626},[1402],{"type":35,"value":934},{"type":30,"tag":77,"props":1404,"children":1405},{"style":626},[1406],{"type":35,"value":1407}," *",{"type":30,"tag":77,"props":1409,"children":1410},{"style":626},[1411],{"type":35,"value":1412}," from",{"type":30,"tag":77,"props":1414,"children":1415},{"style":100},[1416],{"type":35,"value":1417}," meta\n",{"type":30,"tag":77,"props":1419,"children":1420},{"class":79,"line":295},[1421],{"type":30,"tag":77,"props":1422,"children":1423},{"style":626},[1424],{"type":35,"value":1425},"union all\n",{"type":30,"tag":77,"props":1427,"children":1428},{"class":79,"line":341},[1429,1433,1437,1441],{"type":30,"tag":77,"props":1430,"children":1431},{"style":626},[1432],{"type":35,"value":934},{"type":30,"tag":77,"props":1434,"children":1435},{"style":626},[1436],{"type":35,"value":1407},{"type":30,"tag":77,"props":1438,"children":1439},{"style":626},[1440],{"type":35,"value":1412},{"type":30,"tag":77,"props":1442,"children":1443},{"style":100},[1444],{"type":35,"value":1445}," google\n",{"type":30,"tag":31,"props":1447,"children":1448},{},[1449,1454],{"type":30,"tag":59,"props":1450,"children":1451},{},[1452],{"type":35,"value":1453},"Ejemplo de marts",{"type":35,"value":1455}," — dashboard de performance diario:",{"type":30,"tag":67,"props":1457,"children":1459},{"className":585,"code":1458,"language":587,"meta":13,"style":13},"-- models\u002Fmarts\u002Ffct_daily_performance.sql\nselect\n  report_date,\n  source,\n  sum(cost_usd) as total_cost,\n  sum(impressions) as total_impressions,\n  sum(clicks) as total_clicks,\n  sum(conversions) as total_conversions,\n  safe_divide(sum(clicks), sum(impressions)) as ctr,\n  safe_divide(sum(cost_usd), sum(conversions)) as cpa\nfrom {{ ref('int_paid_media_unified') }}\ngroup by 1, 2\n",[1460],{"type":30,"tag":50,"props":1461,"children":1462},{"__ignoreMap":13},[1463,1471,1478,1486,1494,1516,1537,1558,1579,1615,1649,1669],{"type":30,"tag":77,"props":1464,"children":1465},{"class":79,"line":80},[1466],{"type":30,"tag":77,"props":1467,"children":1468},{"style":84},[1469],{"type":35,"value":1470},"-- models\u002Fmarts\u002Ffct_daily_performance.sql\n",{"type":30,"tag":77,"props":1472,"children":1473},{"class":79,"line":90},[1474],{"type":30,"tag":77,"props":1475,"children":1476},{"style":626},[1477],{"type":35,"value":741},{"type":30,"tag":77,"props":1479,"children":1480},{"class":79,"line":112},[1481],{"type":30,"tag":77,"props":1482,"children":1483},{"style":100},[1484],{"type":35,"value":1485},"  report_date,\n",{"type":30,"tag":77,"props":1487,"children":1488},{"class":79,"line":122},[1489],{"type":30,"tag":77,"props":1490,"children":1491},{"style":100},[1492],{"type":35,"value":1493},"  source,\n",{"type":30,"tag":77,"props":1495,"children":1496},{"class":79,"line":136},[1497,1502,1507,1511],{"type":30,"tag":77,"props":1498,"children":1499},{"style":106},[1500],{"type":35,"value":1501},"  sum",{"type":30,"tag":77,"props":1503,"children":1504},{"style":100},[1505],{"type":35,"value":1506},"(cost_usd) ",{"type":30,"tag":77,"props":1508,"children":1509},{"style":626},[1510],{"type":35,"value":764},{"type":30,"tag":77,"props":1512,"children":1513},{"style":100},[1514],{"type":35,"value":1515}," total_cost,\n",{"type":30,"tag":77,"props":1517,"children":1518},{"class":79,"line":160},[1519,1523,1528,1532],{"type":30,"tag":77,"props":1520,"children":1521},{"style":106},[1522],{"type":35,"value":1501},{"type":30,"tag":77,"props":1524,"children":1525},{"style":100},[1526],{"type":35,"value":1527},"(impressions) ",{"type":30,"tag":77,"props":1529,"children":1530},{"style":626},[1531],{"type":35,"value":764},{"type":30,"tag":77,"props":1533,"children":1534},{"style":100},[1535],{"type":35,"value":1536}," total_impressions,\n",{"type":30,"tag":77,"props":1538,"children":1539},{"class":79,"line":178},[1540,1544,1549,1553],{"type":30,"tag":77,"props":1541,"children":1542},{"style":106},[1543],{"type":35,"value":1501},{"type":30,"tag":77,"props":1545,"children":1546},{"style":100},[1547],{"type":35,"value":1548},"(clicks) ",{"type":30,"tag":77,"props":1550,"children":1551},{"style":626},[1552],{"type":35,"value":764},{"type":30,"tag":77,"props":1554,"children":1555},{"style":100},[1556],{"type":35,"value":1557}," total_clicks,\n",{"type":30,"tag":77,"props":1559,"children":1560},{"class":79,"line":24},[1561,1565,1570,1574],{"type":30,"tag":77,"props":1562,"children":1563},{"style":106},[1564],{"type":35,"value":1501},{"type":30,"tag":77,"props":1566,"children":1567},{"style":100},[1568],{"type":35,"value":1569},"(conversions) ",{"type":30,"tag":77,"props":1571,"children":1572},{"style":626},[1573],{"type":35,"value":764},{"type":30,"tag":77,"props":1575,"children":1576},{"style":100},[1577],{"type":35,"value":1578}," total_conversions,\n",{"type":30,"tag":77,"props":1580,"children":1581},{"class":79,"line":208},[1582,1587,1592,1597,1601,1606,1610],{"type":30,"tag":77,"props":1583,"children":1584},{"style":100},[1585],{"type":35,"value":1586},"  safe_divide(",{"type":30,"tag":77,"props":1588,"children":1589},{"style":106},[1590],{"type":35,"value":1591},"sum",{"type":30,"tag":77,"props":1593,"children":1594},{"style":100},[1595],{"type":35,"value":1596},"(clicks), ",{"type":30,"tag":77,"props":1598,"children":1599},{"style":106},[1600],{"type":35,"value":1591},{"type":30,"tag":77,"props":1602,"children":1603},{"style":100},[1604],{"type":35,"value":1605},"(impressions)) ",{"type":30,"tag":77,"props":1607,"children":1608},{"style":626},[1609],{"type":35,"value":764},{"type":30,"tag":77,"props":1611,"children":1612},{"style":100},[1613],{"type":35,"value":1614}," ctr,\n",{"type":30,"tag":77,"props":1616,"children":1617},{"class":79,"line":230},[1618,1622,1626,1631,1635,1640,1644],{"type":30,"tag":77,"props":1619,"children":1620},{"style":100},[1621],{"type":35,"value":1586},{"type":30,"tag":77,"props":1623,"children":1624},{"style":106},[1625],{"type":35,"value":1591},{"type":30,"tag":77,"props":1627,"children":1628},{"style":100},[1629],{"type":35,"value":1630},"(cost_usd), ",{"type":30,"tag":77,"props":1632,"children":1633},{"style":106},[1634],{"type":35,"value":1591},{"type":30,"tag":77,"props":1636,"children":1637},{"style":100},[1638],{"type":35,"value":1639},"(conversions)) ",{"type":30,"tag":77,"props":1641,"children":1642},{"style":626},[1643],{"type":35,"value":764},{"type":30,"tag":77,"props":1645,"children":1646},{"style":100},[1647],{"type":35,"value":1648}," cpa\n",{"type":30,"tag":77,"props":1650,"children":1651},{"class":79,"line":243},[1652,1656,1660,1665],{"type":30,"tag":77,"props":1653,"children":1654},{"style":626},[1655],{"type":35,"value":809},{"type":30,"tag":77,"props":1657,"children":1658},{"style":100},[1659],{"type":35,"value":1304},{"type":30,"tag":77,"props":1661,"children":1662},{"style":154},[1663],{"type":35,"value":1664},"'int_paid_media_unified'",{"type":30,"tag":77,"props":1666,"children":1667},{"style":100},[1668],{"type":35,"value":833},{"type":30,"tag":77,"props":1670,"children":1671},{"class":79,"line":295},[1672,1677,1682,1686],{"type":30,"tag":77,"props":1673,"children":1674},{"style":626},[1675],{"type":35,"value":1676},"group by",{"type":30,"tag":77,"props":1678,"children":1679},{"style":106},[1680],{"type":35,"value":1681}," 1",{"type":30,"tag":77,"props":1683,"children":1684},{"style":100},[1685],{"type":35,"value":273},{"type":30,"tag":77,"props":1687,"children":1688},{"style":106},[1689],{"type":35,"value":109},{"type":30,"tag":31,"props":1691,"children":1692},{},[1693,1695,1701,1703,1709,1711,1717],{"type":35,"value":1694},"La función ",{"type":30,"tag":50,"props":1696,"children":1698},{"className":1697},[],[1699],{"type":35,"value":1700},"ref()",{"type":35,"value":1702}," construye el dependency graph de dbt. El comando ",{"type":30,"tag":50,"props":1704,"children":1706},{"className":1705},[],[1707],{"type":35,"value":1708},"dbt run",{"type":35,"value":1710}," ejecuta los modelos en orden de dependencia. Si ",{"type":30,"tag":50,"props":1712,"children":1714},{"className":1713},[],[1715],{"type":35,"value":1716},"int_paid_media_unified",{"type":35,"value":1718}," cambia, todos los mart tables downstream se reconstruyen automáticamente.",{"type":30,"tag":548,"props":1720,"children":1722},{"id":1721},"test-coverage",[1723],{"type":35,"value":1724},"Test Coverage",{"type":30,"tag":31,"props":1726,"children":1727},{},[1728],{"type":35,"value":1729},"En producción, un reporte KPI incorrecto es un error de 6 cifras en e-commerce. Los tests genéricos de dbt agregan contrato a cada modelo:",{"type":30,"tag":67,"props":1731,"children":1733},{"className":69,"code":1732,"language":71,"meta":13,"style":13},"# models\u002Fmarts\u002Fschema.yml\nversion: 2\n\nmodels:\n  - name: fct_daily_performance\n    columns:\n      - name: report_date\n        tests:\n          - not_null\n          - unique\n      - name: total_cost\n        tests:\n          - not_null\n          - dbt_utils.expression_is_true:\n              expression: \">= 0\"\n      - name: cpa\n        tests:\n          - dbt_utils.expression_is_true:\n              expression: \"is null or cpa >= 0\"\n",[1734],{"type":30,"tag":50,"props":1735,"children":1736},{"__ignoreMap":13},[1737,1745,1760,1767,1779,1799,1811,1831,1843,1854,1866,1886,1897,1908,1924,1941,1961,1972,1987],{"type":30,"tag":77,"props":1738,"children":1739},{"class":79,"line":80},[1740],{"type":30,"tag":77,"props":1741,"children":1742},{"style":84},[1743],{"type":35,"value":1744},"# models\u002Fmarts\u002Fschema.yml\n",{"type":30,"tag":77,"props":1746,"children":1747},{"class":79,"line":90},[1748,1752,1756],{"type":30,"tag":77,"props":1749,"children":1750},{"style":94},[1751],{"type":35,"value":97},{"type":30,"tag":77,"props":1753,"children":1754},{"style":100},[1755],{"type":35,"value":103},{"type":30,"tag":77,"props":1757,"children":1758},{"style":106},[1759],{"type":35,"value":109},{"type":30,"tag":77,"props":1761,"children":1762},{"class":79,"line":112},[1763],{"type":30,"tag":77,"props":1764,"children":1765},{"emptyLinePlaceholder":116},[1766],{"type":35,"value":119},{"type":30,"tag":77,"props":1768,"children":1769},{"class":79,"line":122},[1770,1775],{"type":30,"tag":77,"props":1771,"children":1772},{"style":94},[1773],{"type":35,"value":1774},"models",{"type":30,"tag":77,"props":1776,"children":1777},{"style":100},[1778],{"type":35,"value":133},{"type":30,"tag":77,"props":1780,"children":1781},{"class":79,"line":136},[1782,1786,1790,1794],{"type":30,"tag":77,"props":1783,"children":1784},{"style":100},[1785],{"type":35,"value":142},{"type":30,"tag":77,"props":1787,"children":1788},{"style":94},[1789],{"type":35,"value":147},{"type":30,"tag":77,"props":1791,"children":1792},{"style":100},[1793],{"type":35,"value":103},{"type":30,"tag":77,"props":1795,"children":1796},{"style":154},[1797],{"type":35,"value":1798},"fct_daily_performance\n",{"type":30,"tag":77,"props":1800,"children":1801},{"class":79,"line":160},[1802,1807],{"type":30,"tag":77,"props":1803,"children":1804},{"style":94},[1805],{"type":35,"value":1806},"    columns",{"type":30,"tag":77,"props":1808,"children":1809},{"style":100},[1810],{"type":35,"value":133},{"type":30,"tag":77,"props":1812,"children":1813},{"class":79,"line":178},[1814,1818,1822,1826],{"type":30,"tag":77,"props":1815,"children":1816},{"style":100},[1817],{"type":35,"value":214},{"type":30,"tag":77,"props":1819,"children":1820},{"style":94},[1821],{"type":35,"value":147},{"type":30,"tag":77,"props":1823,"children":1824},{"style":100},[1825],{"type":35,"value":103},{"type":30,"tag":77,"props":1827,"children":1828},{"style":154},[1829],{"type":35,"value":1830},"report_date\n",{"type":30,"tag":77,"props":1832,"children":1833},{"class":79,"line":24},[1834,1839],{"type":30,"tag":77,"props":1835,"children":1836},{"style":94},[1837],{"type":35,"value":1838},"        tests",{"type":30,"tag":77,"props":1840,"children":1841},{"style":100},[1842],{"type":35,"value":133},{"type":30,"tag":77,"props":1844,"children":1845},{"class":79,"line":208},[1846,1850],{"type":30,"tag":77,"props":1847,"children":1848},{"style":100},[1849],{"type":35,"value":378},{"type":30,"tag":77,"props":1851,"children":1852},{"style":154},[1853],{"type":35,"value":418},{"type":30,"tag":77,"props":1855,"children":1856},{"class":79,"line":230},[1857,1861],{"type":30,"tag":77,"props":1858,"children":1859},{"style":100},[1860],{"type":35,"value":378},{"type":30,"tag":77,"props":1862,"children":1863},{"style":154},[1864],{"type":35,"value":1865},"unique\n",{"type":30,"tag":77,"props":1867,"children":1868},{"class":79,"line":243},[1869,1873,1877,1881],{"type":30,"tag":77,"props":1870,"children":1871},{"style":100},[1872],{"type":35,"value":214},{"type":30,"tag":77,"props":1874,"children":1875},{"style":94},[1876],{"type":35,"value":147},{"type":30,"tag":77,"props":1878,"children":1879},{"style":100},[1880],{"type":35,"value":103},{"type":30,"tag":77,"props":1882,"children":1883},{"style":154},[1884],{"type":35,"value":1885},"total_cost\n",{"type":30,"tag":77,"props":1887,"children":1888},{"class":79,"line":295},[1889,1893],{"type":30,"tag":77,"props":1890,"children":1891},{"style":94},[1892],{"type":35,"value":1838},{"type":30,"tag":77,"props":1894,"children":1895},{"style":100},[1896],{"type":35,"value":133},{"type":30,"tag":77,"props":1898,"children":1899},{"class":79,"line":341},[1900,1904],{"type":30,"tag":77,"props":1901,"children":1902},{"style":100},[1903],{"type":35,"value":378},{"type":30,"tag":77,"props":1905,"children":1906},{"style":154},[1907],{"type":35,"value":418},{"type":30,"tag":77,"props":1909,"children":1910},{"class":79,"line":359},[1911,1915,1920],{"type":30,"tag":77,"props":1912,"children":1913},{"style":100},[1914],{"type":35,"value":378},{"type":30,"tag":77,"props":1916,"children":1917},{"style":94},[1918],{"type":35,"value":1919},"dbt_utils.expression_is_true",{"type":30,"tag":77,"props":1921,"children":1922},{"style":100},[1923],{"type":35,"value":133},{"type":30,"tag":77,"props":1925,"children":1926},{"class":79,"line":372},[1927,1932,1936],{"type":30,"tag":77,"props":1928,"children":1929},{"style":94},[1930],{"type":35,"value":1931},"              expression",{"type":30,"tag":77,"props":1933,"children":1934},{"style":100},[1935],{"type":35,"value":103},{"type":30,"tag":77,"props":1937,"children":1938},{"style":154},[1939],{"type":35,"value":1940},"\">= 0\"\n",{"type":30,"tag":77,"props":1942,"children":1943},{"class":79,"line":394},[1944,1948,1952,1956],{"type":30,"tag":77,"props":1945,"children":1946},{"style":100},[1947],{"type":35,"value":214},{"type":30,"tag":77,"props":1949,"children":1950},{"style":94},[1951],{"type":35,"value":147},{"type":30,"tag":77,"props":1953,"children":1954},{"style":100},[1955],{"type":35,"value":103},{"type":30,"tag":77,"props":1957,"children":1958},{"style":154},[1959],{"type":35,"value":1960},"cpa\n",{"type":30,"tag":77,"props":1962,"children":1963},{"class":79,"line":407},[1964,1968],{"type":30,"tag":77,"props":1965,"children":1966},{"style":94},[1967],{"type":35,"value":1838},{"type":30,"tag":77,"props":1969,"children":1970},{"style":100},[1971],{"type":35,"value":133},{"type":30,"tag":77,"props":1973,"children":1974},{"class":79,"line":421},[1975,1979,1983],{"type":30,"tag":77,"props":1976,"children":1977},{"style":100},[1978],{"type":35,"value":378},{"type":30,"tag":77,"props":1980,"children":1981},{"style":94},[1982],{"type":35,"value":1919},{"type":30,"tag":77,"props":1984,"children":1985},{"style":100},[1986],{"type":35,"value":133},{"type":30,"tag":77,"props":1988,"children":1989},{"class":79,"line":442},[1990,1994,1998],{"type":30,"tag":77,"props":1991,"children":1992},{"style":94},[1993],{"type":35,"value":1931},{"type":30,"tag":77,"props":1995,"children":1996},{"style":100},[1997],{"type":35,"value":103},{"type":30,"tag":77,"props":1999,"children":2000},{"style":154},[2001],{"type":35,"value":2002},"\"is null or cpa >= 0\"\n",{"type":30,"tag":31,"props":2004,"children":2005},{},[2006,2008,2014,2016,2025],{"type":35,"value":2007},"El comando ",{"type":30,"tag":50,"props":2009,"children":2011},{"className":2010},[],[2012],{"type":35,"value":2013},"dbt test",{"type":35,"value":2015}," valida estos contratos. En el pipeline de CI\u002FCD, si un test falla, el merge se bloquea — datos incorrectos nunca llegan a producción. En la investigación de ",{"type":30,"tag":2017,"props":2018,"children":2022},"a",{"href":2019,"rel":2020},"https:\u002F\u002Fwww.roibase.com.tr\u002Fes\u002Ffirstparty",[2021],"nofollow",[2023],{"type":35,"value":2024},"First-Party Data & Measurement Architecture",{"type":35,"value":2026}," de Roibase, apuntamos a 85% test coverage (métrica: líneas de código × campos críticos).",{"type":30,"tag":38,"props":2028,"children":2030},{"id":2029},"semantic-layer-define-la-métrica-en-un-lugar",[2031],{"type":35,"value":2032},"Semantic Layer: Define la Métrica en Un Lugar",{"type":30,"tag":31,"props":2034,"children":2035},{},[2036,2038,2044],{"type":35,"value":2037},"A finales de 2025, dbt Labs integró \"MetricFlow\" semantic layer en dbt Cloud. Cuando el equipo de marketing pide \"conversion rate\", el equipo de data no debe reescribir SQL — la definición de métrica debe existir en un único lugar. El archivo ",{"type":30,"tag":50,"props":2039,"children":2041},{"className":2040},[],[2042],{"type":35,"value":2043},"metrics.yml",{"type":35,"value":2045}," de dbt proporciona esta abstracción:",{"type":30,"tag":67,"props":2047,"children":2049},{"className":69,"code":2048,"language":71,"meta":13,"style":13},"# models\u002Fmetrics.yml\nversion: 2\n\nmetrics:\n  - name: conversion_rate\n    label: Conversion Rate\n    model: ref('fct_daily_performance')\n    calculation_method: derived\n    expression: \"safe_divide(total_conversions, total_clicks)\"\n    timestamp: report_date\n    time_grains: [day, week, month]\n    dimensions:\n      - source\n\n  - name: cpa\n    label: Cost Per Acquisition\n    model: ref('fct_daily_performance')\n    calculation_method: derived\n    expression: \"safe_divide(total_cost, total_conversions)\"\n    timestamp: report_date\n    time_grains: [day, week, month]\n    dimensions:\n      - source\n",[2050],{"type":30,"tag":50,"props":2051,"children":2052},{"__ignoreMap":13},[2053,2061,2076,2083,2095,2115,2132,2149,2166,2183,2199,2240,2252,2264,2271,2290,2306,2321,2336,2352,2367,2403,2415],{"type":30,"tag":77,"props":2054,"children":2055},{"class":79,"line":80},[2056],{"type":30,"tag":77,"props":2057,"children":2058},{"style":84},[2059],{"type":35,"value":2060},"# models\u002Fmetrics.yml\n",{"type":30,"tag":77,"props":2062,"children":2063},{"class":79,"line":90},[2064,2068,2072],{"type":30,"tag":77,"props":2065,"children":2066},{"style":94},[2067],{"type":35,"value":97},{"type":30,"tag":77,"props":2069,"children":2070},{"style":100},[2071],{"type":35,"value":103},{"type":30,"tag":77,"props":2073,"children":2074},{"style":106},[2075],{"type":35,"value":109},{"type":30,"tag":77,"props":2077,"children":2078},{"class":79,"line":112},[2079],{"type":30,"tag":77,"props":2080,"children":2081},{"emptyLinePlaceholder":116},[2082],{"type":35,"value":119},{"type":30,"tag":77,"props":2084,"children":2085},{"class":79,"line":122},[2086,2091],{"type":30,"tag":77,"props":2087,"children":2088},{"style":94},[2089],{"type":35,"value":2090},"metrics",{"type":30,"tag":77,"props":2092,"children":2093},{"style":100},[2094],{"type":35,"value":133},{"type":30,"tag":77,"props":2096,"children":2097},{"class":79,"line":136},[2098,2102,2106,2110],{"type":30,"tag":77,"props":2099,"children":2100},{"style":100},[2101],{"type":35,"value":142},{"type":30,"tag":77,"props":2103,"children":2104},{"style":94},[2105],{"type":35,"value":147},{"type":30,"tag":77,"props":2107,"children":2108},{"style":100},[2109],{"type":35,"value":103},{"type":30,"tag":77,"props":2111,"children":2112},{"style":154},[2113],{"type":35,"value":2114},"conversion_rate\n",{"type":30,"tag":77,"props":2116,"children":2117},{"class":79,"line":160},[2118,2123,2127],{"type":30,"tag":77,"props":2119,"children":2120},{"style":94},[2121],{"type":35,"value":2122},"    label",{"type":30,"tag":77,"props":2124,"children":2125},{"style":100},[2126],{"type":35,"value":103},{"type":30,"tag":77,"props":2128,"children":2129},{"style":154},[2130],{"type":35,"value":2131},"Conversion Rate\n",{"type":30,"tag":77,"props":2133,"children":2134},{"class":79,"line":178},[2135,2140,2144],{"type":30,"tag":77,"props":2136,"children":2137},{"style":94},[2138],{"type":35,"value":2139},"    model",{"type":30,"tag":77,"props":2141,"children":2142},{"style":100},[2143],{"type":35,"value":103},{"type":30,"tag":77,"props":2145,"children":2146},{"style":154},[2147],{"type":35,"value":2148},"ref('fct_daily_performance')\n",{"type":30,"tag":77,"props":2150,"children":2151},{"class":79,"line":24},[2152,2157,2161],{"type":30,"tag":77,"props":2153,"children":2154},{"style":94},[2155],{"type":35,"value":2156},"    calculation_method",{"type":30,"tag":77,"props":2158,"children":2159},{"style":100},[2160],{"type":35,"value":103},{"type":30,"tag":77,"props":2162,"children":2163},{"style":154},[2164],{"type":35,"value":2165},"derived\n",{"type":30,"tag":77,"props":2167,"children":2168},{"class":79,"line":208},[2169,2174,2178],{"type":30,"tag":77,"props":2170,"children":2171},{"style":94},[2172],{"type":35,"value":2173},"    expression",{"type":30,"tag":77,"props":2175,"children":2176},{"style":100},[2177],{"type":35,"value":103},{"type":30,"tag":77,"props":2179,"children":2180},{"style":154},[2181],{"type":35,"value":2182},"\"safe_divide(total_conversions, total_clicks)\"\n",{"type":30,"tag":77,"props":2184,"children":2185},{"class":79,"line":230},[2186,2191,2195],{"type":30,"tag":77,"props":2187,"children":2188},{"style":94},[2189],{"type":35,"value":2190},"    timestamp",{"type":30,"tag":77,"props":2192,"children":2193},{"style":100},[2194],{"type":35,"value":103},{"type":30,"tag":77,"props":2196,"children":2197},{"style":154},[2198],{"type":35,"value":1830},{"type":30,"tag":77,"props":2200,"children":2201},{"class":79,"line":243},[2202,2207,2212,2217,2221,2226,2230,2235],{"type":30,"tag":77,"props":2203,"children":2204},{"style":94},[2205],{"type":35,"value":2206},"    time_grains",{"type":30,"tag":77,"props":2208,"children":2209},{"style":100},[2210],{"type":35,"value":2211},": [",{"type":30,"tag":77,"props":2213,"children":2214},{"style":154},[2215],{"type":35,"value":2216},"day",{"type":30,"tag":77,"props":2218,"children":2219},{"style":100},[2220],{"type":35,"value":273},{"type":30,"tag":77,"props":2222,"children":2223},{"style":154},[2224],{"type":35,"value":2225},"week",{"type":30,"tag":77,"props":2227,"children":2228},{"style":100},[2229],{"type":35,"value":273},{"type":30,"tag":77,"props":2231,"children":2232},{"style":154},[2233],{"type":35,"value":2234},"month",{"type":30,"tag":77,"props":2236,"children":2237},{"style":100},[2238],{"type":35,"value":2239},"]\n",{"type":30,"tag":77,"props":2241,"children":2242},{"class":79,"line":295},[2243,2248],{"type":30,"tag":77,"props":2244,"children":2245},{"style":94},[2246],{"type":35,"value":2247},"    dimensions",{"type":30,"tag":77,"props":2249,"children":2250},{"style":100},[2251],{"type":35,"value":133},{"type":30,"tag":77,"props":2253,"children":2254},{"class":79,"line":341},[2255,2259],{"type":30,"tag":77,"props":2256,"children":2257},{"style":100},[2258],{"type":35,"value":214},{"type":30,"tag":77,"props":2260,"children":2261},{"style":154},[2262],{"type":35,"value":2263},"source\n",{"type":30,"tag":77,"props":2265,"children":2266},{"class":79,"line":359},[2267],{"type":30,"tag":77,"props":2268,"children":2269},{"emptyLinePlaceholder":116},[2270],{"type":35,"value":119},{"type":30,"tag":77,"props":2272,"children":2273},{"class":79,"line":372},[2274,2278,2282,2286],{"type":30,"tag":77,"props":2275,"children":2276},{"style":100},[2277],{"type":35,"value":142},{"type":30,"tag":77,"props":2279,"children":2280},{"style":94},[2281],{"type":35,"value":147},{"type":30,"tag":77,"props":2283,"children":2284},{"style":100},[2285],{"type":35,"value":103},{"type":30,"tag":77,"props":2287,"children":2288},{"style":154},[2289],{"type":35,"value":1960},{"type":30,"tag":77,"props":2291,"children":2292},{"class":79,"line":394},[2293,2297,2301],{"type":30,"tag":77,"props":2294,"children":2295},{"style":94},[2296],{"type":35,"value":2122},{"type":30,"tag":77,"props":2298,"children":2299},{"style":100},[2300],{"type":35,"value":103},{"type":30,"tag":77,"props":2302,"children":2303},{"style":154},[2304],{"type":35,"value":2305},"Cost Per Acquisition\n",{"type":30,"tag":77,"props":2307,"children":2308},{"class":79,"line":407},[2309,2313,2317],{"type":30,"tag":77,"props":2310,"children":2311},{"style":94},[2312],{"type":35,"value":2139},{"type":30,"tag":77,"props":2314,"children":2315},{"style":100},[2316],{"type":35,"value":103},{"type":30,"tag":77,"props":2318,"children":2319},{"style":154},[2320],{"type":35,"value":2148},{"type":30,"tag":77,"props":2322,"children":2323},{"class":79,"line":421},[2324,2328,2332],{"type":30,"tag":77,"props":2325,"children":2326},{"style":94},[2327],{"type":35,"value":2156},{"type":30,"tag":77,"props":2329,"children":2330},{"style":100},[2331],{"type":35,"value":103},{"type":30,"tag":77,"props":2333,"children":2334},{"style":154},[2335],{"type":35,"value":2165},{"type":30,"tag":77,"props":2337,"children":2338},{"class":79,"line":442},[2339,2343,2347],{"type":30,"tag":77,"props":2340,"children":2341},{"style":94},[2342],{"type":35,"value":2173},{"type":30,"tag":77,"props":2344,"children":2345},{"style":100},[2346],{"type":35,"value":103},{"type":30,"tag":77,"props":2348,"children":2349},{"style":154},[2350],{"type":35,"value":2351},"\"safe_divide(total_cost, total_conversions)\"\n",{"type":30,"tag":77,"props":2353,"children":2354},{"class":79,"line":454},[2355,2359,2363],{"type":30,"tag":77,"props":2356,"children":2357},{"style":94},[2358],{"type":35,"value":2190},{"type":30,"tag":77,"props":2360,"children":2361},{"style":100},[2362],{"type":35,"value":103},{"type":30,"tag":77,"props":2364,"children":2365},{"style":154},[2366],{"type":35,"value":1830},{"type":30,"tag":77,"props":2368,"children":2370},{"class":79,"line":2369},21,[2371,2375,2379,2383,2387,2391,2395,2399],{"type":30,"tag":77,"props":2372,"children":2373},{"style":94},[2374],{"type":35,"value":2206},{"type":30,"tag":77,"props":2376,"children":2377},{"style":100},[2378],{"type":35,"value":2211},{"type":30,"tag":77,"props":2380,"children":2381},{"style":154},[2382],{"type":35,"value":2216},{"type":30,"tag":77,"props":2384,"children":2385},{"style":100},[2386],{"type":35,"value":273},{"type":30,"tag":77,"props":2388,"children":2389},{"style":154},[2390],{"type":35,"value":2225},{"type":30,"tag":77,"props":2392,"children":2393},{"style":100},[2394],{"type":35,"value":273},{"type":30,"tag":77,"props":2396,"children":2397},{"style":154},[2398],{"type":35,"value":2234},{"type":30,"tag":77,"props":2400,"children":2401},{"style":100},[2402],{"type":35,"value":2239},{"type":30,"tag":77,"props":2404,"children":2406},{"class":79,"line":2405},22,[2407,2411],{"type":30,"tag":77,"props":2408,"children":2409},{"style":94},[2410],{"type":35,"value":2247},{"type":30,"tag":77,"props":2412,"children":2413},{"style":100},[2414],{"type":35,"value":133},{"type":30,"tag":77,"props":2416,"children":2418},{"class":79,"line":2417},23,[2419,2423],{"type":30,"tag":77,"props":2420,"children":2421},{"style":100},[2422],{"type":35,"value":214},{"type":30,"tag":77,"props":2424,"children":2425},{"style":154},[2426],{"type":35,"value":2263},{"type":30,"tag":31,"props":2428,"children":2429},{},[2430,2432,2436,2438,2442],{"type":35,"value":2431},"La semantic layer cumple dos funciones: ",{"type":30,"tag":59,"props":2433,"children":2434},{},[2435],{"type":35,"value":473},{"type":35,"value":2437}," cuando se selecciona una métrica en la herramienta BI, SQL se genera automáticamente (integración con Looker, Tableau, Power BI), ",{"type":30,"tag":59,"props":2439,"children":2440},{},[2441],{"type":35,"value":488},{"type":35,"value":2443}," cuando la métrica cambia, todos los dashboards permanecen consistentes. Si decides que \"el CPA debe incluir costos de shipping\", cambias una línea — 40 dashboards se actualizan simultáneamente.",{"type":30,"tag":31,"props":2445,"children":2446},{},[2447],{"type":35,"value":2448},"MetricFlow aún está en beta (junio de 2026), pero es utilizable en producción. Alternativa: escribe macros en dbt para funciones de métrica custom:",{"type":30,"tag":67,"props":2450,"children":2452},{"className":585,"code":2451,"language":587,"meta":13,"style":13},"-- macros\u002Fcalculate_cpa.sql\n{% macro calculate_cpa(cost_column, conversion_column) %}\n  safe_divide({{ cost_column }}, nullif({{ conversion_column }}, 0))\n{% endmacro %}\n",[2453],{"type":30,"tag":50,"props":2454,"children":2455},{"__ignoreMap":13},[2456,2464,2472,2499],{"type":30,"tag":77,"props":2457,"children":2458},{"class":79,"line":80},[2459],{"type":30,"tag":77,"props":2460,"children":2461},{"style":84},[2462],{"type":35,"value":2463},"-- macros\u002Fcalculate_cpa.sql\n",{"type":30,"tag":77,"props":2465,"children":2466},{"class":79,"line":90},[2467],{"type":30,"tag":77,"props":2468,"children":2469},{"style":100},[2470],{"type":35,"value":2471},"{% macro calculate_cpa(cost_column, conversion_column) %}\n",{"type":30,"tag":77,"props":2473,"children":2474},{"class":79,"line":112},[2475,2480,2485,2490,2495],{"type":30,"tag":77,"props":2476,"children":2477},{"style":100},[2478],{"type":35,"value":2479},"  safe_divide({{ cost_column }}, ",{"type":30,"tag":77,"props":2481,"children":2482},{"style":106},[2483],{"type":35,"value":2484},"nullif",{"type":30,"tag":77,"props":2486,"children":2487},{"style":100},[2488],{"type":35,"value":2489},"({{ conversion_column }}, ",{"type":30,"tag":77,"props":2491,"children":2492},{"style":106},[2493],{"type":35,"value":2494},"0",{"type":30,"tag":77,"props":2496,"children":2497},{"style":100},[2498],{"type":35,"value":880},{"type":30,"tag":77,"props":2500,"children":2501},{"class":79,"line":122},[2502],{"type":30,"tag":77,"props":2503,"children":2504},{"style":100},[2505],{"type":35,"value":2506},"{% endmacro %}\n",{"type":30,"tag":31,"props":2508,"children":2509},{},[2510,2512,2518],{"type":35,"value":2511},"Invocas ",{"type":30,"tag":50,"props":2513,"children":2515},{"className":2514},[],[2516],{"type":35,"value":2517},"{{ calculate_cpa('total_cost', 'total_conversions') }}",{"type":35,"value":2519}," en todos los mart models — el cambio de métrica se propaga desde un lugar.",{"type":30,"tag":38,"props":2521,"children":2523},{"id":2522},"exposures-conecta-el-modelo-al-dashboard-bi",[2524],{"type":35,"value":2525},"Exposures: Conecta el Modelo al Dashboard BI",{"type":30,"tag":31,"props":2527,"children":2528},{},[2529,2531,2537],{"type":35,"value":2530},"El archivo ",{"type":30,"tag":50,"props":2532,"children":2534},{"className":2533},[],[2535],{"type":35,"value":2536},"exposures.yml",{"type":35,"value":2538}," de dbt rastrea qué modelo se usa en qué dashboard. Este tracking es operacional — cuando un modelo cambia, sabes cuáles dashboards necesitan prueba:",{"type":30,"tag":67,"props":2540,"children":2542},{"className":69,"code":2541,"language":71,"meta":13,"style":13},"# models\u002Fexposures.yml\nversion: 2\n\nexposures:\n  - name: executive_performance_dashboard\n    type: dashboard\n    maturity: high\n    url: https:\u002F\u002Flookerstudio.google.com\u002Freporting\u002Fabc123\n    description: \"Daily paid media performance for C-level\"\n    depends_on:\n      - ref('fct_daily_performance')\n      - ref('fct_campaign_performance')\n    owner:\n      name: Growth Team\n      email: growth@company.com\n\n  - name: weekly_marketing_review\n    type: analysis\n    maturity: medium\n    url: https:\u002F\u002Fdocs.google.com\u002Fspreadsheets\u002Fd\u002Fxyz789\n    description: \"Weekly deep-dive into channel mix\"\n    depends_on:\n      - ref('fct_daily_performance')\n    owner:\n      name: Marketing Ops\n      email: mops@company.com\n",[2543],{"type":30,"tag":50,"props":2544,"children":2545},{"__ignoreMap":13},[2546,2554,2569,2576,2588,2608,2625,2642,2659,2676,2688,2699,2711,2723,2740,2757,2764,2784,2800,2816,2832,2848,2859,2870,2882,2899],{"type":30,"tag":77,"props":2547,"children":2548},{"class":79,"line":80},[2549],{"type":30,"tag":77,"props":2550,"children":2551},{"style":84},[2552],{"type":35,"value":2553},"# models\u002Fexposures.yml\n",{"type":30,"tag":77,"props":2555,"children":2556},{"class":79,"line":90},[2557,2561,2565],{"type":30,"tag":77,"props":2558,"children":2559},{"style":94},[2560],{"type":35,"value":97},{"type":30,"tag":77,"props":2562,"children":2563},{"style":100},[2564],{"type":35,"value":103},{"type":30,"tag":77,"props":2566,"children":2567},{"style":106},[2568],{"type":35,"value":109},{"type":30,"tag":77,"props":2570,"children":2571},{"class":79,"line":112},[2572],{"type":30,"tag":77,"props":2573,"children":2574},{"emptyLinePlaceholder":116},[2575],{"type":35,"value":119},{"type":30,"tag":77,"props":2577,"children":2578},{"class":79,"line":122},[2579,2584],{"type":30,"tag":77,"props":2580,"children":2581},{"style":94},[2582],{"type":35,"value":2583},"exposures",{"type":30,"tag":77,"props":2585,"children":2586},{"style":100},[2587],{"type":35,"value":133},{"type":30,"tag":77,"props":2589,"children":2590},{"class":79,"line":136},[2591,2595,2599,2603],{"type":30,"tag":77,"props":2592,"children":2593},{"style":100},[2594],{"type":35,"value":142},{"type":30,"tag":77,"props":2596,"children":2597},{"style":94},[2598],{"type":35,"value":147},{"type":30,"tag":77,"props":2600,"children":2601},{"style":100},[2602],{"type":35,"value":103},{"type":30,"tag":77,"props":2604,"children":2605},{"style":154},[2606],{"type":35,"value":2607},"executive_performance_dashboard\n",{"type":30,"tag":77,"props":2609,"children":2610},{"class":79,"line":160},[2611,2616,2620],{"type":30,"tag":77,"props":2612,"children":2613},{"style":94},[2614],{"type":35,"value":2615},"    type",{"type":30,"tag":77,"props":2617,"children":2618},{"style":100},[2619],{"type":35,"value":103},{"type":30,"tag":77,"props":2621,"children":2622},{"style":154},[2623],{"type":35,"value":2624},"dashboard\n",{"type":30,"tag":77,"props":2626,"children":2627},{"class":79,"line":178},[2628,2633,2637],{"type":30,"tag":77,"props":2629,"children":2630},{"style":94},[2631],{"type":35,"value":2632},"    maturity",{"type":30,"tag":77,"props":2634,"children":2635},{"style":100},[2636],{"type":35,"value":103},{"type":30,"tag":77,"props":2638,"children":2639},{"style":154},[2640],{"type":35,"value":2641},"high\n",{"type":30,"tag":77,"props":2643,"children":2644},{"class":79,"line":24},[2645,2650,2654],{"type":30,"tag":77,"props":2646,"children":2647},{"style":94},[2648],{"type":35,"value":2649},"    url",{"type":30,"tag":77,"props":2651,"children":2652},{"style":100},[2653],{"type":35,"value":103},{"type":30,"tag":77,"props":2655,"children":2656},{"style":154},[2657],{"type":35,"value":2658},"https:\u002F\u002Flookerstudio.google.com\u002Freporting\u002Fabc123\n",{"type":30,"tag":77,"props":2660,"children":2661},{"class":79,"line":208},[2662,2667,2671],{"type":30,"tag":77,"props":2663,"children":2664},{"style":94},[2665],{"type":35,"value":2666},"    description",{"type":30,"tag":77,"props":2668,"children":2669},{"style":100},[2670],{"type":35,"value":103},{"type":30,"tag":77,"props":2672,"children":2673},{"style":154},[2674],{"type":35,"value":2675},"\"Daily paid media performance for C-level\"\n",{"type":30,"tag":77,"props":2677,"children":2678},{"class":79,"line":230},[2679,2684],{"type":30,"tag":77,"props":2680,"children":2681},{"style":94},[2682],{"type":35,"value":2683},"    depends_on",{"type":30,"tag":77,"props":2685,"children":2686},{"style":100},[2687],{"type":35,"value":133},{"type":30,"tag":77,"props":2689,"children":2690},{"class":79,"line":243},[2691,2695],{"type":30,"tag":77,"props":2692,"children":2693},{"style":100},[2694],{"type":35,"value":214},{"type":30,"tag":77,"props":2696,"children":2697},{"style":154},[2698],{"type":35,"value":2148},{"type":30,"tag":77,"props":2700,"children":2701},{"class":79,"line":295},[2702,2706],{"type":30,"tag":77,"props":2703,"children":2704},{"style":100},[2705],{"type":35,"value":214},{"type":30,"tag":77,"props":2707,"children":2708},{"style":154},[2709],{"type":35,"value":2710},"ref('fct_campaign_performance')\n",{"type":30,"tag":77,"props":2712,"children":2713},{"class":79,"line":341},[2714,2719],{"type":30,"tag":77,"props":2715,"children":2716},{"style":94},[2717],{"type":35,"value":2718},"    owner",{"type":30,"tag":77,"props":2720,"children":2721},{"style":100},[2722],{"type":35,"value":133},{"type":30,"tag":77,"props":2724,"children":2725},{"class":79,"line":359},[2726,2731,2735],{"type":30,"tag":77,"props":2727,"children":2728},{"style":94},[2729],{"type":35,"value":2730},"      name",{"type":30,"tag":77,"props":2732,"children":2733},{"style":100},[2734],{"type":35,"value":103},{"type":30,"tag":77,"props":2736,"children":2737},{"style":154},[2738],{"type":35,"value":2739},"Growth Team\n",{"type":30,"tag":77,"props":2741,"children":2742},{"class":79,"line":372},[2743,2748,2752],{"type":30,"tag":77,"props":2744,"children":2745},{"style":94},[2746],{"type":35,"value":2747},"      email",{"type":30,"tag":77,"props":2749,"children":2750},{"style":100},[2751],{"type":35,"value":103},{"type":30,"tag":77,"props":2753,"children":2754},{"style":154},[2755],{"type":35,"value":2756},"growth@company.com\n",{"type":30,"tag":77,"props":2758,"children":2759},{"class":79,"line":394},[2760],{"type":30,"tag":77,"props":2761,"children":2762},{"emptyLinePlaceholder":116},[2763],{"type":35,"value":119},{"type":30,"tag":77,"props":2765,"children":2766},{"class":79,"line":407},[2767,2771,2775,2779],{"type":30,"tag":77,"props":2768,"children":2769},{"style":100},[2770],{"type":35,"value":142},{"type":30,"tag":77,"props":2772,"children":2773},{"style":94},[2774],{"type":35,"value":147},{"type":30,"tag":77,"props":2776,"children":2777},{"style":100},[2778],{"type":35,"value":103},{"type":30,"tag":77,"props":2780,"children":2781},{"style":154},[2782],{"type":35,"value":2783},"weekly_marketing_review\n",{"type":30,"tag":77,"props":2785,"children":2786},{"class":79,"line":421},[2787,2791,2795],{"type":30,"tag":77,"props":2788,"children":2789},{"style":94},[2790],{"type":35,"value":2615},{"type":30,"tag":77,"props":2792,"children":2793},{"style":100},[2794],{"type":35,"value":103},{"type":30,"tag":77,"props":2796,"children":2797},{"style":154},[2798],{"type":35,"value":2799},"analysis\n",{"type":30,"tag":77,"props":2801,"children":2802},{"class":79,"line":442},[2803,2807,2811],{"type":30,"tag":77,"props":2804,"children":2805},{"style":94},[2806],{"type":35,"value":2632},{"type":30,"tag":77,"props":2808,"children":2809},{"style":100},[2810],{"type":35,"value":103},{"type":30,"tag":77,"props":2812,"children":2813},{"style":154},[2814],{"type":35,"value":2815},"medium\n",{"type":30,"tag":77,"props":2817,"children":2818},{"class":79,"line":454},[2819,2823,2827],{"type":30,"tag":77,"props":2820,"children":2821},{"style":94},[2822],{"type":35,"value":2649},{"type":30,"tag":77,"props":2824,"children":2825},{"style":100},[2826],{"type":35,"value":103},{"type":30,"tag":77,"props":2828,"children":2829},{"style":154},[2830],{"type":35,"value":2831},"https:\u002F\u002Fdocs.google.com\u002Fspreadsheets\u002Fd\u002Fxyz789\n",{"type":30,"tag":77,"props":2833,"children":2834},{"class":79,"line":2369},[2835,2839,2843],{"type":30,"tag":77,"props":2836,"children":2837},{"style":94},[2838],{"type":35,"value":2666},{"type":30,"tag":77,"props":2840,"children":2841},{"style":100},[2842],{"type":35,"value":103},{"type":30,"tag":77,"props":2844,"children":2845},{"style":154},[2846],{"type":35,"value":2847},"\"Weekly deep-dive into channel mix\"\n",{"type":30,"tag":77,"props":2849,"children":2850},{"class":79,"line":2405},[2851,2855],{"type":30,"tag":77,"props":2852,"children":2853},{"style":94},[2854],{"type":35,"value":2683},{"type":30,"tag":77,"props":2856,"children":2857},{"style":100},[2858],{"type":35,"value":133},{"type":30,"tag":77,"props":2860,"children":2861},{"class":79,"line":2417},[2862,2866],{"type":30,"tag":77,"props":2863,"children":2864},{"style":100},[2865],{"type":35,"value":214},{"type":30,"tag":77,"props":2867,"children":2868},{"style":154},[2869],{"type":35,"value":2148},{"type":30,"tag":77,"props":2871,"children":2873},{"class":79,"line":2872},24,[2874,2878],{"type":30,"tag":77,"props":2875,"children":2876},{"style":94},[2877],{"type":35,"value":2718},{"type":30,"tag":77,"props":2879,"children":2880},{"style":100},[2881],{"type":35,"value":133},{"type":30,"tag":77,"props":2883,"children":2885},{"class":79,"line":2884},25,[2886,2890,2894],{"type":30,"tag":77,"props":2887,"children":2888},{"style":94},[2889],{"type":35,"value":2730},{"type":30,"tag":77,"props":2891,"children":2892},{"style":100},[2893],{"type":35,"value":103},{"type":30,"tag":77,"props":2895,"children":2896},{"style":154},[2897],{"type":35,"value":2898},"Marketing Ops\n",{"type":30,"tag":77,"props":2900,"children":2902},{"class":79,"line":2901},26,[2903,2907,2911],{"type":30,"tag":77,"props":2904,"children":2905},{"style":94},[2906],{"type":35,"value":2747},{"type":30,"tag":77,"props":2908,"children":2909},{"style":100},[2910],{"type":35,"value":103},{"type":30,"tag":77,"props":2912,"children":2913},{"style":154},[2914],{"type":35,"value":2915},"mops@company.com\n",{"type":30,"tag":31,"props":2917,"children":2918},{},[2919,2921,2927,2929,2935],{"type":35,"value":2920},"El lineage exposure aparece en el graph: después de ",{"type":30,"tag":50,"props":2922,"children":2924},{"className":2923},[],[2925],{"type":35,"value":2926},"dbt docs generate",{"type":35,"value":2928},", la UI web muestra que al hacer clic en el nodo ",{"type":30,"tag":50,"props":2930,"children":2932},{"className":2931},[],[2933],{"type":35,"value":2934},"fct_daily_performance",{"type":35,"value":2936},", ves cuáles dashboards dependen de él. Antes de hacer un breaking change en el modelo, puedes notificar automáticamente a los propietarios de exposure vía webhook de Slack.",{"type":30,"tag":548,"props":2938,"children":2940},{"id":2939},"production-deployment-pattern",[2941],{"type":35,"value":2942},"Production Deployment Pattern",{"type":30,"tag":31,"props":2944,"children":2945},{},[2946],{"type":35,"value":2947},"Los jobs de producción en dbt Cloud se ejecutan en este orden:",{"type":30,"tag":2949,"props":2950,"children":2951},"ol",{},[2952,2971,2988,3004],{"type":30,"tag":2953,"props":2954,"children":2955},"li",{},[2956,2961,2963,2969],{"type":30,"tag":59,"props":2957,"children":2958},{},[2959],{"type":35,"value":2960},"Source freshness check",{"type":35,"value":2962}," — ",{"type":30,"tag":50,"props":2964,"children":2966},{"className":2965},[],[2967],{"type":35,"value":2968},"dbt source freshness",{"type":35,"value":2970}," (falla si los datos upstream están retrasados)",{"type":30,"tag":2953,"props":2972,"children":2973},{},[2974,2979,2980,2986],{"type":30,"tag":59,"props":2975,"children":2976},{},[2977],{"type":35,"value":2978},"Model run",{"type":35,"value":2962},{"type":30,"tag":50,"props":2981,"children":2983},{"className":2982},[],[2984],{"type":35,"value":2985},"dbt run --select tag:daily",{"type":35,"value":2987}," (modelos diarios se construyen a las 07:00)",{"type":30,"tag":2953,"props":2989,"children":2990},{},[2991,2996,2997,3002],{"type":30,"tag":59,"props":2992,"children":2993},{},[2994],{"type":35,"value":2995},"Test execution",{"type":35,"value":2962},{"type":30,"tag":50,"props":2998,"children":3000},{"className":2999},[],[3001],{"type":35,"value":2013},{"type":35,"value":3003}," (si hay violación de contrato, rollback)",{"type":30,"tag":2953,"props":3005,"children":3006},{},[3007,3012,3013,3018],{"type":30,"tag":59,"props":3008,"children":3009},{},[3010],{"type":35,"value":3011},"Documentation update",{"type":35,"value":2962},{"type":30,"tag":50,"props":3014,"children":3016},{"className":3015},[],[3017],{"type":35,"value":2926},{"type":35,"value":3019}," (el graph de linaje se actualiza)",{"type":30,"tag":31,"props":3021,"children":3022},{},[3023],{"type":35,"value":3024},"Usar un job de dbt en lugar de scheduled query de BigQuery tiene ventajas: control de versiones (cada deployment está ligado a un commit de git), capacidad de rollback (un modelo errado vuelve a su versión anterior en 5 minutos), alertas de Slack (falla de test + advertencia de freshness).",{"type":30,"tag":38,"props":3026,"children":3028},{"id":3027},"tradeoff-elt-o-reverse-etl",[3029],{"type":35,"value":3030},"Tradeoff: ¿ELT o Reverse ETL?",{"type":30,"tag":31,"props":3032,"children":3033},{},[3034],{"type":35,"value":3035},"El stack dbt + BigQuery sigue el patrón ELT (extract-load-transform) — los datos raw se traen primero al warehouse, la transformación ocurre en BigQuery. Alternativa: reverse ETL (Hightouch, Census) — datos del warehouse se envían a herramientas SaaS. Se complementan: dbt limpia el warehouse, reverse ETL envía segmentos a Braze\u002FIterable.",{"type":30,"tag":31,"props":3037,"children":3038},{},[3039],{"type":35,"value":3040},"Tradeoff: costo de compute en BigQuery. Un TB de escaneo cuesta $5 — un modelo mart complejo que corre 10 veces al día cuesta $50\u002Fdía = $1500\u002Fmes. Optimización: materialización incremental + partition pruning + clustering. En proyectos de Roibase, el objetivo de costo BigQuery es: $0.02 por monthly active user — 1M MAU = $20K\u002Faño (aceptable).",{"type":30,"tag":31,"props":3042,"children":3043},{},[3044],{"type":35,"value":3045},"El marketing data stack no es un proyecto de una sola vez — es una arquitectura evolutiva. Una vez que cimentas la base de dbt + BigQuery, puedes agregar capas de MMM (marketing mix modeling), tests de incrementality, y capa de identity resolution. Construir este fundamento a nivel production toma 6-8 semanas, pero ahorra 18 meses downstream — cada pregunta KPI nueva se responde en 2 horas, se elimina la limpieza manual de datos, cambios en modelos de attribution toman 1 hora en lugar de 1 día. Una arquitectura correcta transforma datos de marketing en mecanismo de decisión.",{"type":30,"tag":3047,"props":3048,"children":3049},"style",{},[3050],{"type":35,"value":3051},"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":13,"searchDepth":112,"depth":112,"links":3053},[3054,3057,3060,3061,3064],{"id":40,"depth":90,"text":43,"children":3055},[3056],{"id":550,"depth":112,"text":553},{"id":993,"depth":90,"text":996,"children":3058},[3059],{"id":1721,"depth":112,"text":1724},{"id":2029,"depth":90,"text":2032},{"id":2522,"depth":90,"text":2525,"children":3062},[3063],{"id":2939,"depth":112,"text":2942},{"id":3027,"depth":90,"text":3030},"markdown","content:es:data:dbt-bigquery-modern-stack-marketing-data.md","content","es\u002Fdata\u002Fdbt-bigquery-modern-stack-marketing-data.md","es\u002Fdata\u002Fdbt-bigquery-modern-stack-marketing-data","md",1785103534283]