[{"data":1,"prerenderedAt":1867},["ShallowReactive",2],{"article-alternates":3,"article-\u002Fen\u002Fdata\u002Fmodern-marketing-data-stack-with-dbt-bigquery":13},{"i18nKey":4,"paths":5},"data-002-2026-05",{"de":6,"en":7,"es":8,"fr":9,"it":10,"ru":11,"tr":12},"\u002Fde\u002Fdata\u002Fdbt-bigquery-moderne-marketing-data-stack","\u002Fen\u002Fdata\u002Fmodern-marketing-data-stack-with-dbt-bigquery","\u002Fes\u002Fdata\u002Fdbt-bigquery-modern-data-stack-marketing","\u002Ffr\u002Fdata\u002Fdbt-bigquery-modern-marketing-data-stack","\u002Fit\u002Fdata\u002Fdbt-bigquery-modern-marketing-data-stack","\u002Fru\u002Fdata\u002Fdbt-bigquery-sovremennyi-stack-marketingovyh-dannyh","\u002Ftr\u002Fdata\u002Fdbt-bigquery-ile-modern-pazarlama-data-stack",{"_path":7,"_dir":14,"_draft":15,"_partial":15,"_locale":16,"title":17,"description":18,"publishedAt":19,"modifiedAt":19,"category":14,"i18nKey":4,"tags":20,"readingTime":26,"author":27,"body":28,"_type":1861,"_id":1862,"_source":1863,"_file":1864,"_stem":1865,"_extension":1866},"data",false,"","Modern Marketing Data Stack with dbt + BigQuery","Four-layer architecture connecting marketing data to decision-making: source mapping, modeling layer, semantic layer, and exposures that transform raw events into trusted metrics.","2026-05-10",[21,22,23,24,25],"dbt","bigquery","data-modeling","semantic-layer","marketing-analytics",7,"Roibase",{"type":29,"children":30,"toc":1853},"root",[31,39,46,60,81,391,397,418,453,1191,1197,1233,1257,1545,1551,1578,1583,1688,1694,1699,1747,1810,1816,1821,1842,1847],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36],{"type":37,"value":38},"text","Marketing teams have access to more data than ever, yet decisions remain forecast-driven. Reports scattered across spreadsheets, metrics that differ between dashboards, three different answers to \"what's our real CAC?\" The problem isn't data scarcity—it's loss of signal between source and insight. The dbt + BigQuery combination builds the architecture that eliminates this loss: source mapping collects raw data, modeling layer transforms it into business logic, semantic layer establishes a single shared language, and exposures put it into production use.",{"type":32,"tag":40,"props":41,"children":43},"h2",{"id":42},"source-mapping-from-raw-data-to-trusted-source",[44],{"type":37,"value":45},"Source Mapping: From Raw Data to Trusted Source",{"type":32,"tag":33,"props":47,"children":48},{},[49,51,58],{"type":37,"value":50},"Source mapping is dbt's first layer—the initial transformation after you've ingested marketing data into BigQuery. Raw events from Google Ads API, Meta Ads, Shopify get standardized in the staging layer. Your ",{"type":32,"tag":52,"props":53,"children":55},"code",{"className":54},[],[56],{"type":37,"value":57},"stg_google_ads__campaign_performance",{"type":37,"value":59}," model has 127 columns but you use 12. Source mapping selects those 12, converts timestamps to UTC, casts campaign_id to string, handles nulls, and produces a clean table.",{"type":32,"tag":33,"props":61,"children":62},{},[63,65,71,73,79],{"type":37,"value":64},"In BigQuery, source definition lives in ",{"type":32,"tag":52,"props":66,"children":68},{"className":67},[],[69],{"type":37,"value":70},"sources.yml",{"type":37,"value":72},". You define freshness checks here—if Google Ads data hasn't arrived in the last 2 hours, dbt run fails. This enforced contract makes your data pipeline reliable. Instead of selecting directly from source, you use the ",{"type":32,"tag":52,"props":74,"children":76},{"className":75},[],[77],{"type":37,"value":78},"{{ source('google_ads', 'campaign_stats') }}",{"type":37,"value":80}," macro—dbt's lineage graph shows which raw table feeds which model.",{"type":32,"tag":82,"props":83,"children":87},"pre",{"className":84,"code":85,"language":86,"meta":16,"style":16},"language-yaml shiki shiki-themes github-dark","sources:\n  - name: google_ads\n    database: production\n    schema: raw_google_ads\n    tables:\n      - name: campaign_stats\n        freshness:\n          warn_after: {count: 2, period: hour}\n          error_after: {count: 6, period: hour}\n        columns:\n          - name: campaign_id\n            tests:\n              - not_null\n              - unique\n","yaml",[88],{"type":32,"tag":52,"props":89,"children":90},{"__ignoreMap":16},[91,109,134,152,170,183,205,217,270,316,329,351,364,378],{"type":32,"tag":92,"props":93,"children":96},"span",{"class":94,"line":95},"line",1,[97,103],{"type":32,"tag":92,"props":98,"children":100},{"style":99},"--shiki-default:#85E89D",[101],{"type":37,"value":102},"sources",{"type":32,"tag":92,"props":104,"children":106},{"style":105},"--shiki-default:#E1E4E8",[107],{"type":37,"value":108},":\n",{"type":32,"tag":92,"props":110,"children":112},{"class":94,"line":111},2,[113,118,123,128],{"type":32,"tag":92,"props":114,"children":115},{"style":105},[116],{"type":37,"value":117},"  - ",{"type":32,"tag":92,"props":119,"children":120},{"style":99},[121],{"type":37,"value":122},"name",{"type":32,"tag":92,"props":124,"children":125},{"style":105},[126],{"type":37,"value":127},": ",{"type":32,"tag":92,"props":129,"children":131},{"style":130},"--shiki-default:#9ECBFF",[132],{"type":37,"value":133},"google_ads\n",{"type":32,"tag":92,"props":135,"children":137},{"class":94,"line":136},3,[138,143,147],{"type":32,"tag":92,"props":139,"children":140},{"style":99},[141],{"type":37,"value":142},"    database",{"type":32,"tag":92,"props":144,"children":145},{"style":105},[146],{"type":37,"value":127},{"type":32,"tag":92,"props":148,"children":149},{"style":130},[150],{"type":37,"value":151},"production\n",{"type":32,"tag":92,"props":153,"children":155},{"class":94,"line":154},4,[156,161,165],{"type":32,"tag":92,"props":157,"children":158},{"style":99},[159],{"type":37,"value":160},"    schema",{"type":32,"tag":92,"props":162,"children":163},{"style":105},[164],{"type":37,"value":127},{"type":32,"tag":92,"props":166,"children":167},{"style":130},[168],{"type":37,"value":169},"raw_google_ads\n",{"type":32,"tag":92,"props":171,"children":173},{"class":94,"line":172},5,[174,179],{"type":32,"tag":92,"props":175,"children":176},{"style":99},[177],{"type":37,"value":178},"    tables",{"type":32,"tag":92,"props":180,"children":181},{"style":105},[182],{"type":37,"value":108},{"type":32,"tag":92,"props":184,"children":186},{"class":94,"line":185},6,[187,192,196,200],{"type":32,"tag":92,"props":188,"children":189},{"style":105},[190],{"type":37,"value":191},"      - ",{"type":32,"tag":92,"props":193,"children":194},{"style":99},[195],{"type":37,"value":122},{"type":32,"tag":92,"props":197,"children":198},{"style":105},[199],{"type":37,"value":127},{"type":32,"tag":92,"props":201,"children":202},{"style":130},[203],{"type":37,"value":204},"campaign_stats\n",{"type":32,"tag":92,"props":206,"children":207},{"class":94,"line":26},[208,213],{"type":32,"tag":92,"props":209,"children":210},{"style":99},[211],{"type":37,"value":212},"        freshness",{"type":32,"tag":92,"props":214,"children":215},{"style":105},[216],{"type":37,"value":108},{"type":32,"tag":92,"props":218,"children":220},{"class":94,"line":219},8,[221,226,231,236,240,246,251,256,260,265],{"type":32,"tag":92,"props":222,"children":223},{"style":99},[224],{"type":37,"value":225},"          warn_after",{"type":32,"tag":92,"props":227,"children":228},{"style":105},[229],{"type":37,"value":230},": {",{"type":32,"tag":92,"props":232,"children":233},{"style":99},[234],{"type":37,"value":235},"count",{"type":32,"tag":92,"props":237,"children":238},{"style":105},[239],{"type":37,"value":127},{"type":32,"tag":92,"props":241,"children":243},{"style":242},"--shiki-default:#79B8FF",[244],{"type":37,"value":245},"2",{"type":32,"tag":92,"props":247,"children":248},{"style":105},[249],{"type":37,"value":250},", ",{"type":32,"tag":92,"props":252,"children":253},{"style":99},[254],{"type":37,"value":255},"period",{"type":32,"tag":92,"props":257,"children":258},{"style":105},[259],{"type":37,"value":127},{"type":32,"tag":92,"props":261,"children":262},{"style":130},[263],{"type":37,"value":264},"hour",{"type":32,"tag":92,"props":266,"children":267},{"style":105},[268],{"type":37,"value":269},"}\n",{"type":32,"tag":92,"props":271,"children":273},{"class":94,"line":272},9,[274,279,283,287,291,296,300,304,308,312],{"type":32,"tag":92,"props":275,"children":276},{"style":99},[277],{"type":37,"value":278},"          error_after",{"type":32,"tag":92,"props":280,"children":281},{"style":105},[282],{"type":37,"value":230},{"type":32,"tag":92,"props":284,"children":285},{"style":99},[286],{"type":37,"value":235},{"type":32,"tag":92,"props":288,"children":289},{"style":105},[290],{"type":37,"value":127},{"type":32,"tag":92,"props":292,"children":293},{"style":242},[294],{"type":37,"value":295},"6",{"type":32,"tag":92,"props":297,"children":298},{"style":105},[299],{"type":37,"value":250},{"type":32,"tag":92,"props":301,"children":302},{"style":99},[303],{"type":37,"value":255},{"type":32,"tag":92,"props":305,"children":306},{"style":105},[307],{"type":37,"value":127},{"type":32,"tag":92,"props":309,"children":310},{"style":130},[311],{"type":37,"value":264},{"type":32,"tag":92,"props":313,"children":314},{"style":105},[315],{"type":37,"value":269},{"type":32,"tag":92,"props":317,"children":319},{"class":94,"line":318},10,[320,325],{"type":32,"tag":92,"props":321,"children":322},{"style":99},[323],{"type":37,"value":324},"        columns",{"type":32,"tag":92,"props":326,"children":327},{"style":105},[328],{"type":37,"value":108},{"type":32,"tag":92,"props":330,"children":332},{"class":94,"line":331},11,[333,338,342,346],{"type":32,"tag":92,"props":334,"children":335},{"style":105},[336],{"type":37,"value":337},"          - ",{"type":32,"tag":92,"props":339,"children":340},{"style":99},[341],{"type":37,"value":122},{"type":32,"tag":92,"props":343,"children":344},{"style":105},[345],{"type":37,"value":127},{"type":32,"tag":92,"props":347,"children":348},{"style":130},[349],{"type":37,"value":350},"campaign_id\n",{"type":32,"tag":92,"props":352,"children":354},{"class":94,"line":353},12,[355,360],{"type":32,"tag":92,"props":356,"children":357},{"style":99},[358],{"type":37,"value":359},"            tests",{"type":32,"tag":92,"props":361,"children":362},{"style":105},[363],{"type":37,"value":108},{"type":32,"tag":92,"props":365,"children":367},{"class":94,"line":366},13,[368,373],{"type":32,"tag":92,"props":369,"children":370},{"style":105},[371],{"type":37,"value":372},"              - ",{"type":32,"tag":92,"props":374,"children":375},{"style":130},[376],{"type":37,"value":377},"not_null\n",{"type":32,"tag":92,"props":379,"children":381},{"class":94,"line":380},14,[382,386],{"type":32,"tag":92,"props":383,"children":384},{"style":105},[385],{"type":37,"value":372},{"type":32,"tag":92,"props":387,"children":388},{"style":130},[389],{"type":37,"value":390},"unique\n",{"type":32,"tag":40,"props":392,"children":394},{"id":393},"modeling-layer-turning-business-logic-into-code",[395],{"type":37,"value":396},"Modeling Layer: Turning Business Logic into Code",{"type":32,"tag":33,"props":398,"children":399},{},[400,402,408,410,416],{"type":37,"value":401},"After staging come intermediate and mart layers—where business logic applies to marketing data. In your ",{"type":32,"tag":52,"props":403,"children":405},{"className":404},[],[406],{"type":37,"value":407},"int_campaign_attribution",{"type":37,"value":409}," model, you calculate first-touch and last-touch attribution. The ",{"type":32,"tag":52,"props":411,"children":413},{"className":412},[],[414],{"type":37,"value":415},"fct_customer_lifetime_value",{"type":37,"value":417}," table handles cohort-based LTV analysis. These models use dbt's incremental materialization—each run processes only the last 3 days, older records untouched. Your 40-million-row customer_event table in BigQuery runs in 2 minutes per dbt run with incremental strategy instead of full-table refreshes.",{"type":32,"tag":33,"props":419,"children":420},{},[421,423,429,430,436,437,443,445,451],{"type":37,"value":422},"Mart layer creates business-unit-specific tables: ",{"type":32,"tag":52,"props":424,"children":426},{"className":425},[],[427],{"type":37,"value":428},"mart_paid_media__daily_performance",{"type":37,"value":250},{"type":32,"tag":52,"props":431,"children":433},{"className":432},[],[434],{"type":37,"value":435},"mart_crm__email_engagement",{"type":37,"value":250},{"type":32,"tag":52,"props":438,"children":440},{"className":439},[],[441],{"type":37,"value":442},"mart_finance__revenue_attribution",{"type":37,"value":444},". These feed directly into Looker Studio, Tableau, Amplitude—everyone pulls their metric from the same source. CAC calculation stops being a debate because the ",{"type":32,"tag":52,"props":446,"children":448},{"className":447},[],[449],{"type":37,"value":450},"paid_media_spend \u002F new_customers",{"type":37,"value":452}," formula lives in dbt code. It passes code review, gets tested, stays under version control.",{"type":32,"tag":82,"props":454,"children":458},{"className":455,"code":456,"language":457,"meta":16,"style":16},"language-sql shiki shiki-themes github-dark","-- models\u002Fmarts\u002Fpaid_media\u002Fmart_paid_media__daily_performance.sql\n{{ config(materialized='incremental', unique_key='date_campaign_id') }}\n\nwith campaign_spend as (\n  select\n    date,\n    campaign_id,\n    sum(cost_micros) \u002F 1e6 as spend\n  from {{ ref('stg_google_ads__campaign_performance') }}\n  {% if is_incremental() %}\n    where date >= date_sub(current_date(), interval 3 day)\n  {% endif %}\n  group by 1, 2\n),\n\nconversions as (\n  select\n    date(timestamp) as date,\n    campaign_id,\n    count(distinct user_id) as conversions\n  from {{ ref('stg_ga4__conversions') }}\n  {% if is_incremental() %}\n    where date(timestamp) >= date_sub(current_date(), interval 3 day)\n  {% endif %}\n  group by 1, 2\n)\n\nselect\n  c.date,\n  c.campaign_id,\n  c.spend,\n  coalesce(cv.conversions, 0) as conversions,\n  safe_divide(c.spend, nullif(cv.conversions, 0)) as cpa\nfrom campaign_spend c\nleft join conversions cv using (date, campaign_id)\n","sql",[459],{"type":32,"tag":52,"props":460,"children":461},{"__ignoreMap":16},[462,471,509,518,541,549,562,570,602,624,642,680,688,710,718,726,743,751,786,794,826,847,863,908,916,936,944,952,961,984,1005,1026,1075,1144,1158],{"type":32,"tag":92,"props":463,"children":464},{"class":94,"line":95},[465],{"type":32,"tag":92,"props":466,"children":468},{"style":467},"--shiki-default:#6A737D",[469],{"type":37,"value":470},"-- models\u002Fmarts\u002Fpaid_media\u002Fmart_paid_media__daily_performance.sql\n",{"type":32,"tag":92,"props":472,"children":473},{"class":94,"line":111},[474,479,485,490,495,499,504],{"type":32,"tag":92,"props":475,"children":476},{"style":105},[477],{"type":37,"value":478},"{{ config(materialized",{"type":32,"tag":92,"props":480,"children":482},{"style":481},"--shiki-default:#F97583",[483],{"type":37,"value":484},"=",{"type":32,"tag":92,"props":486,"children":487},{"style":130},[488],{"type":37,"value":489},"'incremental'",{"type":32,"tag":92,"props":491,"children":492},{"style":105},[493],{"type":37,"value":494},", unique_key",{"type":32,"tag":92,"props":496,"children":497},{"style":481},[498],{"type":37,"value":484},{"type":32,"tag":92,"props":500,"children":501},{"style":130},[502],{"type":37,"value":503},"'date_campaign_id'",{"type":32,"tag":92,"props":505,"children":506},{"style":105},[507],{"type":37,"value":508},") }}\n",{"type":32,"tag":92,"props":510,"children":511},{"class":94,"line":136},[512],{"type":32,"tag":92,"props":513,"children":515},{"emptyLinePlaceholder":514},true,[516],{"type":37,"value":517},"\n",{"type":32,"tag":92,"props":519,"children":520},{"class":94,"line":154},[521,526,531,536],{"type":32,"tag":92,"props":522,"children":523},{"style":481},[524],{"type":37,"value":525},"with",{"type":32,"tag":92,"props":527,"children":528},{"style":105},[529],{"type":37,"value":530}," campaign_spend ",{"type":32,"tag":92,"props":532,"children":533},{"style":481},[534],{"type":37,"value":535},"as",{"type":32,"tag":92,"props":537,"children":538},{"style":105},[539],{"type":37,"value":540}," (\n",{"type":32,"tag":92,"props":542,"children":543},{"class":94,"line":172},[544],{"type":32,"tag":92,"props":545,"children":546},{"style":481},[547],{"type":37,"value":548},"  select\n",{"type":32,"tag":92,"props":550,"children":551},{"class":94,"line":185},[552,557],{"type":32,"tag":92,"props":553,"children":554},{"style":481},[555],{"type":37,"value":556},"    date",{"type":32,"tag":92,"props":558,"children":559},{"style":105},[560],{"type":37,"value":561},",\n",{"type":32,"tag":92,"props":563,"children":564},{"class":94,"line":26},[565],{"type":32,"tag":92,"props":566,"children":567},{"style":105},[568],{"type":37,"value":569},"    campaign_id,\n",{"type":32,"tag":92,"props":571,"children":572},{"class":94,"line":219},[573,578,583,588,593,597],{"type":32,"tag":92,"props":574,"children":575},{"style":242},[576],{"type":37,"value":577},"    sum",{"type":32,"tag":92,"props":579,"children":580},{"style":105},[581],{"type":37,"value":582},"(cost_micros) ",{"type":32,"tag":92,"props":584,"children":585},{"style":481},[586],{"type":37,"value":587},"\u002F",{"type":32,"tag":92,"props":589,"children":590},{"style":105},[591],{"type":37,"value":592}," 1e6 ",{"type":32,"tag":92,"props":594,"children":595},{"style":481},[596],{"type":37,"value":535},{"type":32,"tag":92,"props":598,"children":599},{"style":105},[600],{"type":37,"value":601}," spend\n",{"type":32,"tag":92,"props":603,"children":604},{"class":94,"line":272},[605,610,615,620],{"type":32,"tag":92,"props":606,"children":607},{"style":481},[608],{"type":37,"value":609},"  from",{"type":32,"tag":92,"props":611,"children":612},{"style":105},[613],{"type":37,"value":614}," {{ ref(",{"type":32,"tag":92,"props":616,"children":617},{"style":130},[618],{"type":37,"value":619},"'stg_google_ads__campaign_performance'",{"type":32,"tag":92,"props":621,"children":622},{"style":105},[623],{"type":37,"value":508},{"type":32,"tag":92,"props":625,"children":626},{"class":94,"line":318},[627,632,637],{"type":32,"tag":92,"props":628,"children":629},{"style":105},[630],{"type":37,"value":631},"  {% ",{"type":32,"tag":92,"props":633,"children":634},{"style":481},[635],{"type":37,"value":636},"if",{"type":32,"tag":92,"props":638,"children":639},{"style":105},[640],{"type":37,"value":641}," is_incremental() %}\n",{"type":32,"tag":92,"props":643,"children":644},{"class":94,"line":331},[645,650,655,660,665,670,675],{"type":32,"tag":92,"props":646,"children":647},{"style":481},[648],{"type":37,"value":649},"    where",{"type":32,"tag":92,"props":651,"children":652},{"style":481},[653],{"type":37,"value":654}," date",{"type":32,"tag":92,"props":656,"children":657},{"style":481},[658],{"type":37,"value":659}," >=",{"type":32,"tag":92,"props":661,"children":662},{"style":105},[663],{"type":37,"value":664}," date_sub(current_date(), interval ",{"type":32,"tag":92,"props":666,"children":667},{"style":242},[668],{"type":37,"value":669},"3",{"type":32,"tag":92,"props":671,"children":672},{"style":481},[673],{"type":37,"value":674}," day",{"type":32,"tag":92,"props":676,"children":677},{"style":105},[678],{"type":37,"value":679},")\n",{"type":32,"tag":92,"props":681,"children":682},{"class":94,"line":353},[683],{"type":32,"tag":92,"props":684,"children":685},{"style":105},[686],{"type":37,"value":687},"  {% endif %}\n",{"type":32,"tag":92,"props":689,"children":690},{"class":94,"line":366},[691,696,701,705],{"type":32,"tag":92,"props":692,"children":693},{"style":481},[694],{"type":37,"value":695},"  group by",{"type":32,"tag":92,"props":697,"children":698},{"style":242},[699],{"type":37,"value":700}," 1",{"type":32,"tag":92,"props":702,"children":703},{"style":105},[704],{"type":37,"value":250},{"type":32,"tag":92,"props":706,"children":707},{"style":242},[708],{"type":37,"value":709},"2\n",{"type":32,"tag":92,"props":711,"children":712},{"class":94,"line":380},[713],{"type":32,"tag":92,"props":714,"children":715},{"style":105},[716],{"type":37,"value":717},"),\n",{"type":32,"tag":92,"props":719,"children":721},{"class":94,"line":720},15,[722],{"type":32,"tag":92,"props":723,"children":724},{"emptyLinePlaceholder":514},[725],{"type":37,"value":517},{"type":32,"tag":92,"props":727,"children":729},{"class":94,"line":728},16,[730,735,739],{"type":32,"tag":92,"props":731,"children":732},{"style":105},[733],{"type":37,"value":734},"conversions ",{"type":32,"tag":92,"props":736,"children":737},{"style":481},[738],{"type":37,"value":535},{"type":32,"tag":92,"props":740,"children":741},{"style":105},[742],{"type":37,"value":540},{"type":32,"tag":92,"props":744,"children":746},{"class":94,"line":745},17,[747],{"type":32,"tag":92,"props":748,"children":749},{"style":481},[750],{"type":37,"value":548},{"type":32,"tag":92,"props":752,"children":754},{"class":94,"line":753},18,[755,759,764,769,774,778,782],{"type":32,"tag":92,"props":756,"children":757},{"style":481},[758],{"type":37,"value":556},{"type":32,"tag":92,"props":760,"children":761},{"style":105},[762],{"type":37,"value":763},"(",{"type":32,"tag":92,"props":765,"children":766},{"style":481},[767],{"type":37,"value":768},"timestamp",{"type":32,"tag":92,"props":770,"children":771},{"style":105},[772],{"type":37,"value":773},") ",{"type":32,"tag":92,"props":775,"children":776},{"style":481},[777],{"type":37,"value":535},{"type":32,"tag":92,"props":779,"children":780},{"style":481},[781],{"type":37,"value":654},{"type":32,"tag":92,"props":783,"children":784},{"style":105},[785],{"type":37,"value":561},{"type":32,"tag":92,"props":787,"children":789},{"class":94,"line":788},19,[790],{"type":32,"tag":92,"props":791,"children":792},{"style":105},[793],{"type":37,"value":569},{"type":32,"tag":92,"props":795,"children":797},{"class":94,"line":796},20,[798,803,807,812,817,821],{"type":32,"tag":92,"props":799,"children":800},{"style":242},[801],{"type":37,"value":802},"    count",{"type":32,"tag":92,"props":804,"children":805},{"style":105},[806],{"type":37,"value":763},{"type":32,"tag":92,"props":808,"children":809},{"style":481},[810],{"type":37,"value":811},"distinct",{"type":32,"tag":92,"props":813,"children":814},{"style":105},[815],{"type":37,"value":816}," user_id) ",{"type":32,"tag":92,"props":818,"children":819},{"style":481},[820],{"type":37,"value":535},{"type":32,"tag":92,"props":822,"children":823},{"style":105},[824],{"type":37,"value":825}," conversions\n",{"type":32,"tag":92,"props":827,"children":829},{"class":94,"line":828},21,[830,834,838,843],{"type":32,"tag":92,"props":831,"children":832},{"style":481},[833],{"type":37,"value":609},{"type":32,"tag":92,"props":835,"children":836},{"style":105},[837],{"type":37,"value":614},{"type":32,"tag":92,"props":839,"children":840},{"style":130},[841],{"type":37,"value":842},"'stg_ga4__conversions'",{"type":32,"tag":92,"props":844,"children":845},{"style":105},[846],{"type":37,"value":508},{"type":32,"tag":92,"props":848,"children":850},{"class":94,"line":849},22,[851,855,859],{"type":32,"tag":92,"props":852,"children":853},{"style":105},[854],{"type":37,"value":631},{"type":32,"tag":92,"props":856,"children":857},{"style":481},[858],{"type":37,"value":636},{"type":32,"tag":92,"props":860,"children":861},{"style":105},[862],{"type":37,"value":641},{"type":32,"tag":92,"props":864,"children":866},{"class":94,"line":865},23,[867,871,875,879,883,887,892,896,900,904],{"type":32,"tag":92,"props":868,"children":869},{"style":481},[870],{"type":37,"value":649},{"type":32,"tag":92,"props":872,"children":873},{"style":481},[874],{"type":37,"value":654},{"type":32,"tag":92,"props":876,"children":877},{"style":105},[878],{"type":37,"value":763},{"type":32,"tag":92,"props":880,"children":881},{"style":481},[882],{"type":37,"value":768},{"type":32,"tag":92,"props":884,"children":885},{"style":105},[886],{"type":37,"value":773},{"type":32,"tag":92,"props":888,"children":889},{"style":481},[890],{"type":37,"value":891},">=",{"type":32,"tag":92,"props":893,"children":894},{"style":105},[895],{"type":37,"value":664},{"type":32,"tag":92,"props":897,"children":898},{"style":242},[899],{"type":37,"value":669},{"type":32,"tag":92,"props":901,"children":902},{"style":481},[903],{"type":37,"value":674},{"type":32,"tag":92,"props":905,"children":906},{"style":105},[907],{"type":37,"value":679},{"type":32,"tag":92,"props":909,"children":911},{"class":94,"line":910},24,[912],{"type":32,"tag":92,"props":913,"children":914},{"style":105},[915],{"type":37,"value":687},{"type":32,"tag":92,"props":917,"children":919},{"class":94,"line":918},25,[920,924,928,932],{"type":32,"tag":92,"props":921,"children":922},{"style":481},[923],{"type":37,"value":695},{"type":32,"tag":92,"props":925,"children":926},{"style":242},[927],{"type":37,"value":700},{"type":32,"tag":92,"props":929,"children":930},{"style":105},[931],{"type":37,"value":250},{"type":32,"tag":92,"props":933,"children":934},{"style":242},[935],{"type":37,"value":709},{"type":32,"tag":92,"props":937,"children":939},{"class":94,"line":938},26,[940],{"type":32,"tag":92,"props":941,"children":942},{"style":105},[943],{"type":37,"value":679},{"type":32,"tag":92,"props":945,"children":947},{"class":94,"line":946},27,[948],{"type":32,"tag":92,"props":949,"children":950},{"emptyLinePlaceholder":514},[951],{"type":37,"value":517},{"type":32,"tag":92,"props":953,"children":955},{"class":94,"line":954},28,[956],{"type":32,"tag":92,"props":957,"children":958},{"style":481},[959],{"type":37,"value":960},"select\n",{"type":32,"tag":92,"props":962,"children":964},{"class":94,"line":963},29,[965,970,975,980],{"type":32,"tag":92,"props":966,"children":967},{"style":242},[968],{"type":37,"value":969},"  c",{"type":32,"tag":92,"props":971,"children":972},{"style":105},[973],{"type":37,"value":974},".",{"type":32,"tag":92,"props":976,"children":977},{"style":242},[978],{"type":37,"value":979},"date",{"type":32,"tag":92,"props":981,"children":982},{"style":105},[983],{"type":37,"value":561},{"type":32,"tag":92,"props":985,"children":987},{"class":94,"line":986},30,[988,992,996,1001],{"type":32,"tag":92,"props":989,"children":990},{"style":242},[991],{"type":37,"value":969},{"type":32,"tag":92,"props":993,"children":994},{"style":105},[995],{"type":37,"value":974},{"type":32,"tag":92,"props":997,"children":998},{"style":242},[999],{"type":37,"value":1000},"campaign_id",{"type":32,"tag":92,"props":1002,"children":1003},{"style":105},[1004],{"type":37,"value":561},{"type":32,"tag":92,"props":1006,"children":1008},{"class":94,"line":1007},31,[1009,1013,1017,1022],{"type":32,"tag":92,"props":1010,"children":1011},{"style":242},[1012],{"type":37,"value":969},{"type":32,"tag":92,"props":1014,"children":1015},{"style":105},[1016],{"type":37,"value":974},{"type":32,"tag":92,"props":1018,"children":1019},{"style":242},[1020],{"type":37,"value":1021},"spend",{"type":32,"tag":92,"props":1023,"children":1024},{"style":105},[1025],{"type":37,"value":561},{"type":32,"tag":92,"props":1027,"children":1029},{"class":94,"line":1028},32,[1030,1035,1039,1044,1048,1053,1057,1062,1066,1070],{"type":32,"tag":92,"props":1031,"children":1032},{"style":242},[1033],{"type":37,"value":1034},"  coalesce",{"type":32,"tag":92,"props":1036,"children":1037},{"style":105},[1038],{"type":37,"value":763},{"type":32,"tag":92,"props":1040,"children":1041},{"style":242},[1042],{"type":37,"value":1043},"cv",{"type":32,"tag":92,"props":1045,"children":1046},{"style":105},[1047],{"type":37,"value":974},{"type":32,"tag":92,"props":1049,"children":1050},{"style":242},[1051],{"type":37,"value":1052},"conversions",{"type":32,"tag":92,"props":1054,"children":1055},{"style":105},[1056],{"type":37,"value":250},{"type":32,"tag":92,"props":1058,"children":1059},{"style":242},[1060],{"type":37,"value":1061},"0",{"type":32,"tag":92,"props":1063,"children":1064},{"style":105},[1065],{"type":37,"value":773},{"type":32,"tag":92,"props":1067,"children":1068},{"style":481},[1069],{"type":37,"value":535},{"type":32,"tag":92,"props":1071,"children":1072},{"style":105},[1073],{"type":37,"value":1074}," conversions,\n",{"type":32,"tag":92,"props":1076,"children":1078},{"class":94,"line":1077},33,[1079,1084,1089,1093,1097,1101,1106,1110,1114,1118,1122,1126,1130,1135,1139],{"type":32,"tag":92,"props":1080,"children":1081},{"style":105},[1082],{"type":37,"value":1083},"  safe_divide(",{"type":32,"tag":92,"props":1085,"children":1086},{"style":242},[1087],{"type":37,"value":1088},"c",{"type":32,"tag":92,"props":1090,"children":1091},{"style":105},[1092],{"type":37,"value":974},{"type":32,"tag":92,"props":1094,"children":1095},{"style":242},[1096],{"type":37,"value":1021},{"type":32,"tag":92,"props":1098,"children":1099},{"style":105},[1100],{"type":37,"value":250},{"type":32,"tag":92,"props":1102,"children":1103},{"style":242},[1104],{"type":37,"value":1105},"nullif",{"type":32,"tag":92,"props":1107,"children":1108},{"style":105},[1109],{"type":37,"value":763},{"type":32,"tag":92,"props":1111,"children":1112},{"style":242},[1113],{"type":37,"value":1043},{"type":32,"tag":92,"props":1115,"children":1116},{"style":105},[1117],{"type":37,"value":974},{"type":32,"tag":92,"props":1119,"children":1120},{"style":242},[1121],{"type":37,"value":1052},{"type":32,"tag":92,"props":1123,"children":1124},{"style":105},[1125],{"type":37,"value":250},{"type":32,"tag":92,"props":1127,"children":1128},{"style":242},[1129],{"type":37,"value":1061},{"type":32,"tag":92,"props":1131,"children":1132},{"style":105},[1133],{"type":37,"value":1134},")) ",{"type":32,"tag":92,"props":1136,"children":1137},{"style":481},[1138],{"type":37,"value":535},{"type":32,"tag":92,"props":1140,"children":1141},{"style":105},[1142],{"type":37,"value":1143}," cpa\n",{"type":32,"tag":92,"props":1145,"children":1147},{"class":94,"line":1146},34,[1148,1153],{"type":32,"tag":92,"props":1149,"children":1150},{"style":481},[1151],{"type":37,"value":1152},"from",{"type":32,"tag":92,"props":1154,"children":1155},{"style":105},[1156],{"type":37,"value":1157}," campaign_spend c\n",{"type":32,"tag":92,"props":1159,"children":1161},{"class":94,"line":1160},35,[1162,1167,1172,1177,1182,1186],{"type":32,"tag":92,"props":1163,"children":1164},{"style":481},[1165],{"type":37,"value":1166},"left join",{"type":32,"tag":92,"props":1168,"children":1169},{"style":105},[1170],{"type":37,"value":1171}," conversions cv ",{"type":32,"tag":92,"props":1173,"children":1174},{"style":481},[1175],{"type":37,"value":1176},"using",{"type":32,"tag":92,"props":1178,"children":1179},{"style":105},[1180],{"type":37,"value":1181}," (",{"type":32,"tag":92,"props":1183,"children":1184},{"style":481},[1185],{"type":37,"value":979},{"type":32,"tag":92,"props":1187,"children":1188},{"style":105},[1189],{"type":37,"value":1190},", campaign_id)\n",{"type":32,"tag":40,"props":1192,"children":1194},{"id":1193},"semantic-layer-creating-a-single-source-of-truth",[1195],{"type":37,"value":1196},"Semantic Layer: Creating a Single Source of Truth",{"type":32,"tag":33,"props":1198,"children":1199},{},[1200,1202,1208,1210,1216,1218,1224,1226,1231],{"type":37,"value":1201},"The semantic layer—introduced in dbt 1.6—lets you define metrics as code that every tool consumes. ",{"type":32,"tag":52,"props":1203,"children":1205},{"className":1204},[],[1206],{"type":37,"value":1207},"revenue",{"type":37,"value":1209}," isn't just ",{"type":32,"tag":52,"props":1211,"children":1213},{"className":1212},[],[1214],{"type":37,"value":1215},"sum(order_total)",{"type":37,"value":1217},", it's ",{"type":32,"tag":52,"props":1219,"children":1221},{"className":1220},[],[1222],{"type":37,"value":1223},"sum(case when payment_status = 'completed' then order_total end)",{"type":37,"value":1225},". The question \"are refunded orders included?\" disappears because the metric definition sits on GitHub. Marketing, finance, and product teams use the same ",{"type":32,"tag":52,"props":1227,"children":1229},{"className":1228},[],[1230],{"type":37,"value":1207},{"type":37,"value":1232}," metric—they just slice it by different dimensions.",{"type":32,"tag":33,"props":1234,"children":1235},{},[1236,1238,1247,1249,1255],{"type":37,"value":1237},"In Roibase's ",{"type":32,"tag":1239,"props":1240,"children":1244},"a",{"href":1241,"rel":1242},"https:\u002F\u002Fwww.roibase.com.tr\u002Fen\u002Ffirstparty",[1243],"nofollow",[1245],{"type":37,"value":1246},"first-party data and measurement architecture",{"type":37,"value":1248}," work, semantic layer is a mandatory step. When merging customer events from different touchpoints without pinned metric definitions, every analysis produces different results. In dbt, metrics defined in ",{"type":32,"tag":52,"props":1250,"children":1252},{"className":1251},[],[1253],{"type":37,"value":1254},"metrics.yml",{"type":37,"value":1256}," get exposed to BI tools via API—Looker, Hex, Mode fetch metrics from the semantic layer, the same number appears everywhere.",{"type":32,"tag":82,"props":1258,"children":1260},{"className":84,"code":1259,"language":86,"meta":16,"style":16},"# models\u002Fmetrics\u002Fmetrics.yml\nmetrics:\n  - name: marketing_qualified_leads\n    label: Marketing Qualified Leads\n    model: ref('fct_leads')\n    calculation_method: count_distinct\n    expression: lead_id\n    timestamp: created_at\n    time_grains: [day, week, month]\n    dimensions:\n      - utm_source\n      - utm_campaign\n      - landing_page\n    filters:\n      - field: lead_status\n        operator: '='\n        value: \"'MQL'\"\n",[1261],{"type":32,"tag":52,"props":1262,"children":1263},{"__ignoreMap":16},[1264,1272,1284,1304,1321,1338,1355,1372,1389,1430,1442,1454,1466,1478,1490,1511,1528],{"type":32,"tag":92,"props":1265,"children":1266},{"class":94,"line":95},[1267],{"type":32,"tag":92,"props":1268,"children":1269},{"style":467},[1270],{"type":37,"value":1271},"# models\u002Fmetrics\u002Fmetrics.yml\n",{"type":32,"tag":92,"props":1273,"children":1274},{"class":94,"line":111},[1275,1280],{"type":32,"tag":92,"props":1276,"children":1277},{"style":99},[1278],{"type":37,"value":1279},"metrics",{"type":32,"tag":92,"props":1281,"children":1282},{"style":105},[1283],{"type":37,"value":108},{"type":32,"tag":92,"props":1285,"children":1286},{"class":94,"line":136},[1287,1291,1295,1299],{"type":32,"tag":92,"props":1288,"children":1289},{"style":105},[1290],{"type":37,"value":117},{"type":32,"tag":92,"props":1292,"children":1293},{"style":99},[1294],{"type":37,"value":122},{"type":32,"tag":92,"props":1296,"children":1297},{"style":105},[1298],{"type":37,"value":127},{"type":32,"tag":92,"props":1300,"children":1301},{"style":130},[1302],{"type":37,"value":1303},"marketing_qualified_leads\n",{"type":32,"tag":92,"props":1305,"children":1306},{"class":94,"line":154},[1307,1312,1316],{"type":32,"tag":92,"props":1308,"children":1309},{"style":99},[1310],{"type":37,"value":1311},"    label",{"type":32,"tag":92,"props":1313,"children":1314},{"style":105},[1315],{"type":37,"value":127},{"type":32,"tag":92,"props":1317,"children":1318},{"style":130},[1319],{"type":37,"value":1320},"Marketing Qualified Leads\n",{"type":32,"tag":92,"props":1322,"children":1323},{"class":94,"line":172},[1324,1329,1333],{"type":32,"tag":92,"props":1325,"children":1326},{"style":99},[1327],{"type":37,"value":1328},"    model",{"type":32,"tag":92,"props":1330,"children":1331},{"style":105},[1332],{"type":37,"value":127},{"type":32,"tag":92,"props":1334,"children":1335},{"style":130},[1336],{"type":37,"value":1337},"ref('fct_leads')\n",{"type":32,"tag":92,"props":1339,"children":1340},{"class":94,"line":185},[1341,1346,1350],{"type":32,"tag":92,"props":1342,"children":1343},{"style":99},[1344],{"type":37,"value":1345},"    calculation_method",{"type":32,"tag":92,"props":1347,"children":1348},{"style":105},[1349],{"type":37,"value":127},{"type":32,"tag":92,"props":1351,"children":1352},{"style":130},[1353],{"type":37,"value":1354},"count_distinct\n",{"type":32,"tag":92,"props":1356,"children":1357},{"class":94,"line":26},[1358,1363,1367],{"type":32,"tag":92,"props":1359,"children":1360},{"style":99},[1361],{"type":37,"value":1362},"    expression",{"type":32,"tag":92,"props":1364,"children":1365},{"style":105},[1366],{"type":37,"value":127},{"type":32,"tag":92,"props":1368,"children":1369},{"style":130},[1370],{"type":37,"value":1371},"lead_id\n",{"type":32,"tag":92,"props":1373,"children":1374},{"class":94,"line":219},[1375,1380,1384],{"type":32,"tag":92,"props":1376,"children":1377},{"style":99},[1378],{"type":37,"value":1379},"    timestamp",{"type":32,"tag":92,"props":1381,"children":1382},{"style":105},[1383],{"type":37,"value":127},{"type":32,"tag":92,"props":1385,"children":1386},{"style":130},[1387],{"type":37,"value":1388},"created_at\n",{"type":32,"tag":92,"props":1390,"children":1391},{"class":94,"line":272},[1392,1397,1402,1407,1411,1416,1420,1425],{"type":32,"tag":92,"props":1393,"children":1394},{"style":99},[1395],{"type":37,"value":1396},"    time_grains",{"type":32,"tag":92,"props":1398,"children":1399},{"style":105},[1400],{"type":37,"value":1401},": [",{"type":32,"tag":92,"props":1403,"children":1404},{"style":130},[1405],{"type":37,"value":1406},"day",{"type":32,"tag":92,"props":1408,"children":1409},{"style":105},[1410],{"type":37,"value":250},{"type":32,"tag":92,"props":1412,"children":1413},{"style":130},[1414],{"type":37,"value":1415},"week",{"type":32,"tag":92,"props":1417,"children":1418},{"style":105},[1419],{"type":37,"value":250},{"type":32,"tag":92,"props":1421,"children":1422},{"style":130},[1423],{"type":37,"value":1424},"month",{"type":32,"tag":92,"props":1426,"children":1427},{"style":105},[1428],{"type":37,"value":1429},"]\n",{"type":32,"tag":92,"props":1431,"children":1432},{"class":94,"line":318},[1433,1438],{"type":32,"tag":92,"props":1434,"children":1435},{"style":99},[1436],{"type":37,"value":1437},"    dimensions",{"type":32,"tag":92,"props":1439,"children":1440},{"style":105},[1441],{"type":37,"value":108},{"type":32,"tag":92,"props":1443,"children":1444},{"class":94,"line":331},[1445,1449],{"type":32,"tag":92,"props":1446,"children":1447},{"style":105},[1448],{"type":37,"value":191},{"type":32,"tag":92,"props":1450,"children":1451},{"style":130},[1452],{"type":37,"value":1453},"utm_source\n",{"type":32,"tag":92,"props":1455,"children":1456},{"class":94,"line":353},[1457,1461],{"type":32,"tag":92,"props":1458,"children":1459},{"style":105},[1460],{"type":37,"value":191},{"type":32,"tag":92,"props":1462,"children":1463},{"style":130},[1464],{"type":37,"value":1465},"utm_campaign\n",{"type":32,"tag":92,"props":1467,"children":1468},{"class":94,"line":366},[1469,1473],{"type":32,"tag":92,"props":1470,"children":1471},{"style":105},[1472],{"type":37,"value":191},{"type":32,"tag":92,"props":1474,"children":1475},{"style":130},[1476],{"type":37,"value":1477},"landing_page\n",{"type":32,"tag":92,"props":1479,"children":1480},{"class":94,"line":380},[1481,1486],{"type":32,"tag":92,"props":1482,"children":1483},{"style":99},[1484],{"type":37,"value":1485},"    filters",{"type":32,"tag":92,"props":1487,"children":1488},{"style":105},[1489],{"type":37,"value":108},{"type":32,"tag":92,"props":1491,"children":1492},{"class":94,"line":720},[1493,1497,1502,1506],{"type":32,"tag":92,"props":1494,"children":1495},{"style":105},[1496],{"type":37,"value":191},{"type":32,"tag":92,"props":1498,"children":1499},{"style":99},[1500],{"type":37,"value":1501},"field",{"type":32,"tag":92,"props":1503,"children":1504},{"style":105},[1505],{"type":37,"value":127},{"type":32,"tag":92,"props":1507,"children":1508},{"style":130},[1509],{"type":37,"value":1510},"lead_status\n",{"type":32,"tag":92,"props":1512,"children":1513},{"class":94,"line":728},[1514,1519,1523],{"type":32,"tag":92,"props":1515,"children":1516},{"style":99},[1517],{"type":37,"value":1518},"        operator",{"type":32,"tag":92,"props":1520,"children":1521},{"style":105},[1522],{"type":37,"value":127},{"type":32,"tag":92,"props":1524,"children":1525},{"style":130},[1526],{"type":37,"value":1527},"'='\n",{"type":32,"tag":92,"props":1529,"children":1530},{"class":94,"line":745},[1531,1536,1540],{"type":32,"tag":92,"props":1532,"children":1533},{"style":99},[1534],{"type":37,"value":1535},"        value",{"type":32,"tag":92,"props":1537,"children":1538},{"style":105},[1539],{"type":37,"value":127},{"type":32,"tag":92,"props":1541,"children":1542},{"style":130},[1543],{"type":37,"value":1544},"\"'MQL'\"\n",{"type":32,"tag":40,"props":1546,"children":1548},{"id":1547},"exposures-moving-to-production",[1549],{"type":37,"value":1550},"Exposures: Moving to Production",{"type":32,"tag":33,"props":1552,"children":1553},{},[1554,1556,1561,1563,1569,1571,1576],{"type":37,"value":1555},"Exposures are dbt's downstream dependency tracking—you define which dashboard consumes which dbt model. Your \"Weekly Campaign Performance\" dashboard in Looker pulls from ",{"type":32,"tag":52,"props":1557,"children":1559},{"className":1558},[],[1560],{"type":37,"value":428},{"type":37,"value":1562},". Document this dependency in ",{"type":32,"tag":52,"props":1564,"children":1566},{"className":1565},[],[1567],{"type":37,"value":1568},"exposures.yml",{"type":37,"value":1570},". Now when you make a breaking change to ",{"type":32,"tag":52,"props":1572,"children":1574},{"className":1573},[],[1575],{"type":37,"value":428},{"type":37,"value":1577},", dbt warns you: \"This model powers 3 dashboards—run impact analysis first.\"",{"type":32,"tag":33,"props":1579,"children":1580},{},[1581],{"type":37,"value":1582},"Exposures also appear in documentation—click a model in dbt docs and see \"Used in 5 dashboards, 2 reverse ETL jobs, 1 ML pipeline.\" Data lineage extends to the BI layer. You know which SQL powers which dashboard in production. Debug time shrinks because you find the broken dashboard, trace it to the source model in seconds.",{"type":32,"tag":1584,"props":1585,"children":1586},"table",{},[1587,1611],{"type":32,"tag":1588,"props":1589,"children":1590},"thead",{},[1591],{"type":32,"tag":1592,"props":1593,"children":1594},"tr",{},[1595,1601,1606],{"type":32,"tag":1596,"props":1597,"children":1598},"th",{},[1599],{"type":37,"value":1600},"Exposure Type",{"type":32,"tag":1596,"props":1602,"children":1603},{},[1604],{"type":37,"value":1605},"Use Case",{"type":32,"tag":1596,"props":1607,"children":1608},{},[1609],{"type":37,"value":1610},"Tracking Method",{"type":32,"tag":1612,"props":1613,"children":1614},"tbody",{},[1615,1634,1652,1670],{"type":32,"tag":1592,"props":1616,"children":1617},{},[1618,1624,1629],{"type":32,"tag":1619,"props":1620,"children":1621},"td",{},[1622],{"type":37,"value":1623},"Dashboard",{"type":32,"tag":1619,"props":1625,"children":1626},{},[1627],{"type":37,"value":1628},"Looker, Tableau, Metabase",{"type":32,"tag":1619,"props":1630,"children":1631},{},[1632],{"type":37,"value":1633},"URL + model ref",{"type":32,"tag":1592,"props":1635,"children":1636},{},[1637,1642,1647],{"type":32,"tag":1619,"props":1638,"children":1639},{},[1640],{"type":37,"value":1641},"Reverse ETL",{"type":32,"tag":1619,"props":1643,"children":1644},{},[1645],{"type":37,"value":1646},"Census, Hightouch",{"type":32,"tag":1619,"props":1648,"children":1649},{},[1650],{"type":37,"value":1651},"Job ID + source table",{"type":32,"tag":1592,"props":1653,"children":1654},{},[1655,1660,1665],{"type":32,"tag":1619,"props":1656,"children":1657},{},[1658],{"type":37,"value":1659},"ML Pipeline",{"type":32,"tag":1619,"props":1661,"children":1662},{},[1663],{"type":37,"value":1664},"Vertex AI, SageMaker",{"type":32,"tag":1619,"props":1666,"children":1667},{},[1668],{"type":37,"value":1669},"Model name + feature table",{"type":32,"tag":1592,"props":1671,"children":1672},{},[1673,1678,1683],{"type":32,"tag":1619,"props":1674,"children":1675},{},[1676],{"type":37,"value":1677},"Operational Tool",{"type":32,"tag":1619,"props":1679,"children":1680},{},[1681],{"type":37,"value":1682},"Braze, Iterable campaign segment",{"type":32,"tag":1619,"props":1684,"children":1685},{},[1686],{"type":37,"value":1687},"Segment ID + dbt model",{"type":32,"tag":40,"props":1689,"children":1691},{"id":1690},"pipeline-orchestration-orchestrating-each-layer",[1692],{"type":37,"value":1693},"Pipeline Orchestration: Orchestrating Each Layer",{"type":32,"tag":33,"props":1695,"children":1696},{},[1697],{"type":37,"value":1698},"Use dbt Cloud Scheduler or Airflow to orchestrate your pipeline. Raw data loads to BigQuery at 6:00 AM (via Fivetran, Stitch, Airbyte). dbt run starts at 6:30. Staging models finish in 5 minutes, intermediate in 10, marts in 15. Semantic layer exposes at 7:00, Looker dashboards refresh by 7:15. Your team arrives at 9:00 AM to yesterday's data—no 3-hour pipeline lag.",{"type":32,"tag":33,"props":1700,"children":1701},{},[1702,1704,1710,1711,1717,1718,1724,1725,1731,1733,1738,1740,1745],{"type":37,"value":1703},"Test suite runs on every execution: ",{"type":32,"tag":52,"props":1705,"children":1707},{"className":1706},[],[1708],{"type":37,"value":1709},"not_null",{"type":37,"value":250},{"type":32,"tag":52,"props":1712,"children":1714},{"className":1713},[],[1715],{"type":37,"value":1716},"unique",{"type":37,"value":250},{"type":32,"tag":52,"props":1719,"children":1721},{"className":1720},[],[1722],{"type":37,"value":1723},"accepted_values",{"type":37,"value":250},{"type":32,"tag":52,"props":1726,"children":1728},{"className":1727},[],[1729],{"type":37,"value":1730},"relationships",{"type":37,"value":1732},". If ",{"type":32,"tag":52,"props":1734,"children":1736},{"className":1735},[],[1737],{"type":37,"value":1000},{"type":37,"value":1739}," isn't unique in ",{"type":32,"tag":52,"props":1741,"children":1743},{"className":1742},[],[1744],{"type":37,"value":57},{"type":37,"value":1746},", dbt run fails. Slack alerts fire. Data quality gate enforces at code level. Broken data never reaches production.",{"type":32,"tag":82,"props":1748,"children":1750},{"className":84,"code":1749,"language":86,"meta":16,"style":16},"# dbt_project.yml on-run-end hooks\non-run-end:\n  - \"{{ log_dbt_results() }}\"\n  - \"{{ send_slack_notification() }}\"\n  - \"{{ update_looker_cache() }}\"\n",[1751],{"type":32,"tag":52,"props":1752,"children":1753},{"__ignoreMap":16},[1754,1762,1774,1786,1798],{"type":32,"tag":92,"props":1755,"children":1756},{"class":94,"line":95},[1757],{"type":32,"tag":92,"props":1758,"children":1759},{"style":467},[1760],{"type":37,"value":1761},"# dbt_project.yml on-run-end hooks\n",{"type":32,"tag":92,"props":1763,"children":1764},{"class":94,"line":111},[1765,1770],{"type":32,"tag":92,"props":1766,"children":1767},{"style":99},[1768],{"type":37,"value":1769},"on-run-end",{"type":32,"tag":92,"props":1771,"children":1772},{"style":105},[1773],{"type":37,"value":108},{"type":32,"tag":92,"props":1775,"children":1776},{"class":94,"line":136},[1777,1781],{"type":32,"tag":92,"props":1778,"children":1779},{"style":105},[1780],{"type":37,"value":117},{"type":32,"tag":92,"props":1782,"children":1783},{"style":130},[1784],{"type":37,"value":1785},"\"{{ log_dbt_results() }}\"\n",{"type":32,"tag":92,"props":1787,"children":1788},{"class":94,"line":154},[1789,1793],{"type":32,"tag":92,"props":1790,"children":1791},{"style":105},[1792],{"type":37,"value":117},{"type":32,"tag":92,"props":1794,"children":1795},{"style":130},[1796],{"type":37,"value":1797},"\"{{ send_slack_notification() }}\"\n",{"type":32,"tag":92,"props":1799,"children":1800},{"class":94,"line":172},[1801,1805],{"type":32,"tag":92,"props":1802,"children":1803},{"style":105},[1804],{"type":37,"value":117},{"type":32,"tag":92,"props":1806,"children":1807},{"style":130},[1808],{"type":37,"value":1809},"\"{{ update_looker_cache() }}\"\n",{"type":32,"tag":40,"props":1811,"children":1813},{"id":1812},"tradeoff-complexity-vs-governance",[1814],{"type":37,"value":1815},"Tradeoff: Complexity vs Governance",{"type":32,"tag":33,"props":1817,"children":1818},{},[1819],{"type":37,"value":1820},"dbt + BigQuery stack introduces complexity. SQL fluency becomes non-negotiable in the analyst team—\"let me pivot this in Excel\" no longer cuts it. Git workflows, code review, CI\u002FCD pipelines are now required knowledge. Small teams may find this overhead costly. But the tradeoff is clear: you gain governance. Instead of formulas lost in spreadsheets, you have version-controlled code. \"Where does this number come from?\" gets answered in 10 seconds via Git blame.",{"type":32,"tag":33,"props":1822,"children":1823},{},[1824,1826,1832,1834,1840],{"type":37,"value":1825},"BigQuery costs are another tradeoff. Full table scans are expensive—partition and cluster strategy becomes mandatory. In dbt incremental models, ",{"type":32,"tag":52,"props":1827,"children":1829},{"className":1828},[],[1830],{"type":37,"value":1831},"partition_by",{"type":37,"value":1833}," and ",{"type":32,"tag":52,"props":1835,"children":1837},{"className":1836},[],[1838],{"type":37,"value":1839},"cluster_by",{"type":37,"value":1841}," configs are critical. A pipeline processing 100 GB monthly in BigQuery costs roughly $50 for reserved slots plus $5 for storage. As a managed service there's no infrastructure overhead, but unoptimized queries balloon the bill.",{"type":32,"tag":33,"props":1843,"children":1844},{},[1845],{"type":37,"value":1846},"Connecting marketing data to decision-making can't be solved with spreadsheets and BI tools anymore. The dbt + BigQuery stack codifies every layer from source to exposure. Source mapping makes raw data trustworthy, modeling layer applies business logic, semantic layer establishes shared language, exposures move it to production. Code review, testing, version control—data pipelines now follow software engineering discipline.",{"type":32,"tag":1848,"props":1849,"children":1850},"style",{},[1851],{"type":37,"value":1852},"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":136,"depth":136,"links":1854},[1855,1856,1857,1858,1859,1860],{"id":42,"depth":111,"text":45},{"id":393,"depth":111,"text":396},{"id":1193,"depth":111,"text":1196},{"id":1547,"depth":111,"text":1550},{"id":1690,"depth":111,"text":1693},{"id":1812,"depth":111,"text":1815},"markdown","content:en:data:modern-marketing-data-stack-with-dbt-bigquery.md","content","en\u002Fdata\u002Fmodern-marketing-data-stack-with-dbt-bigquery.md","en\u002Fdata\u002Fmodern-marketing-data-stack-with-dbt-bigquery","md",1778392982736]