[{"data":1,"prerenderedAt":2772},["ShallowReactive",2],{"article-alternates":3,"article-\u002Fru\u002Fdata\u002Fdbt-bigquery-pazarlama-data-stack":11},{"i18nKey":4,"paths":5},"data-002-2026-05",{"de":6,"en":7,"es":8,"it":9,"ru":10},"\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","\u002Fit\u002Fdata\u002Fdbt-bigquery-modern-marketing-data-stack","\u002Fru\u002Fdata\u002Fdbt-bigquery-sovremennyi-stack-marketingovyh-dannyh",{"_path":12,"_dir":13,"_draft":14,"_partial":14,"_locale":15,"title":16,"description":17,"publishedAt":18,"modifiedAt":18,"category":13,"i18nKey":4,"tags":19,"readingTime":25,"author":26,"body":27,"_type":2766,"_id":2767,"_source":2768,"_file":2769,"_stem":2770,"_extension":2771},"\u002Fru\u002Fdata\u002Fdbt-bigquery-pazarlama-data-stack","data",false,"","dbt + BigQuery с современным маркетинг-стеком данных","Source mapping, modeling layer, semantic layer, exposures: production-ready архитектура, связывающая маркетинг-данные с системой принятия решений через dbt и BigQuery.","2026-05-29",[20,21,22,23,24],"dbt","bigquery","data-modeling","semantic-layer","marketing-analytics",8,"Roibase",{"type":28,"children":29,"toc":2757},"root",[30,38,45,59,64,434,439,460,466,471,482,747,757,1198,1224,1468,1481,1487,1492,1497,1918,1923,1947,1953,1966,2141,2160,2165,2170,2176,2181,2489,2510,2515,2521,2526,2593,2598,2663,2668,2681,2711,2725,2731,2736,2741,2746,2751],{"type":31,"tag":32,"props":33,"children":34},"element","p",{},[35],{"type":36,"value":37},"text","Маркетинг-команды всё ещё говорят: \"Не смотрев на дашборд, я не знаю результаты кампании.\" Аналитик пишет новый SQL на каждый запрос. CFO не понимает, почему расчёт CAC отличается в каждом отчёте. Проблема не в технологии — pipeline есть, источники подключены, данные текут. Проблема в архитектуре: между исходными таблицами и дашбордом отсутствует слой определений. Комбинация dbt + BigQuery решает эту проблему: source mapping, modeling layer, semantic layer и exposures стандартизируют данные на уровне логики, а не визуализации.",{"type":31,"tag":39,"props":40,"children":42},"h2",{"id":41},"source-mapping-привязываем-сырые-данные-к-контракту",[43],{"type":36,"value":44},"Source Mapping: привязываем сырые данные к контракту",{"type":31,"tag":32,"props":46,"children":47},{},[48,50,57],{"type":36,"value":49},"В BigQuery стекают данные из CRM, GA4, Meta Ads, Klaviyo. Каждый источник использует разную схему, разные соглашения об именовании, разные форматы временных меток. dbt source mapping позволяет декларировать эти источники как код и тестировать их. В файле ",{"type":31,"tag":51,"props":52,"children":54},"code",{"className":53},[],[55],{"type":36,"value":56},"sources.yml",{"type":36,"value":58}," вы объявляете каждую таблицу, добавляете проверки свежести данных, тестируете уникальность.",{"type":31,"tag":32,"props":60,"children":61},{},[62],{"type":36,"value":63},"Пример определения source:",{"type":31,"tag":65,"props":66,"children":70},"pre",{"className":67,"code":68,"language":69,"meta":15,"style":15},"language-yaml shiki shiki-themes github-dark","version: 2\n\nsources:\n  - name: raw_ga4\n    database: analytics_lake\n    schema: raw_ga4_events\n    tables:\n      - name: events\n        freshness:\n          warn_after: {count: 6, period: hour}\n          error_after: {count: 12, period: hour}\n        columns:\n          - name: event_timestamp\n            tests:\n              - not_null\n          - name: user_pseudo_id\n            tests:\n              - not_null\n","yaml",[71],{"type":31,"tag":51,"props":72,"children":73},{"__ignoreMap":15},[74,98,108,122,146,164,182,195,216,229,281,327,340,362,375,389,410,422],{"type":31,"tag":75,"props":76,"children":79},"span",{"class":77,"line":78},"line",1,[80,86,92],{"type":31,"tag":75,"props":81,"children":83},{"style":82},"--shiki-default:#85E89D",[84],{"type":36,"value":85},"version",{"type":31,"tag":75,"props":87,"children":89},{"style":88},"--shiki-default:#E1E4E8",[90],{"type":36,"value":91},": ",{"type":31,"tag":75,"props":93,"children":95},{"style":94},"--shiki-default:#79B8FF",[96],{"type":36,"value":97},"2\n",{"type":31,"tag":75,"props":99,"children":101},{"class":77,"line":100},2,[102],{"type":31,"tag":75,"props":103,"children":105},{"emptyLinePlaceholder":104},true,[106],{"type":36,"value":107},"\n",{"type":31,"tag":75,"props":109,"children":111},{"class":77,"line":110},3,[112,117],{"type":31,"tag":75,"props":113,"children":114},{"style":82},[115],{"type":36,"value":116},"sources",{"type":31,"tag":75,"props":118,"children":119},{"style":88},[120],{"type":36,"value":121},":\n",{"type":31,"tag":75,"props":123,"children":125},{"class":77,"line":124},4,[126,131,136,140],{"type":31,"tag":75,"props":127,"children":128},{"style":88},[129],{"type":36,"value":130},"  - ",{"type":31,"tag":75,"props":132,"children":133},{"style":82},[134],{"type":36,"value":135},"name",{"type":31,"tag":75,"props":137,"children":138},{"style":88},[139],{"type":36,"value":91},{"type":31,"tag":75,"props":141,"children":143},{"style":142},"--shiki-default:#9ECBFF",[144],{"type":36,"value":145},"raw_ga4\n",{"type":31,"tag":75,"props":147,"children":149},{"class":77,"line":148},5,[150,155,159],{"type":31,"tag":75,"props":151,"children":152},{"style":82},[153],{"type":36,"value":154},"    database",{"type":31,"tag":75,"props":156,"children":157},{"style":88},[158],{"type":36,"value":91},{"type":31,"tag":75,"props":160,"children":161},{"style":142},[162],{"type":36,"value":163},"analytics_lake\n",{"type":31,"tag":75,"props":165,"children":167},{"class":77,"line":166},6,[168,173,177],{"type":31,"tag":75,"props":169,"children":170},{"style":82},[171],{"type":36,"value":172},"    schema",{"type":31,"tag":75,"props":174,"children":175},{"style":88},[176],{"type":36,"value":91},{"type":31,"tag":75,"props":178,"children":179},{"style":142},[180],{"type":36,"value":181},"raw_ga4_events\n",{"type":31,"tag":75,"props":183,"children":185},{"class":77,"line":184},7,[186,191],{"type":31,"tag":75,"props":187,"children":188},{"style":82},[189],{"type":36,"value":190},"    tables",{"type":31,"tag":75,"props":192,"children":193},{"style":88},[194],{"type":36,"value":121},{"type":31,"tag":75,"props":196,"children":197},{"class":77,"line":25},[198,203,207,211],{"type":31,"tag":75,"props":199,"children":200},{"style":88},[201],{"type":36,"value":202},"      - ",{"type":31,"tag":75,"props":204,"children":205},{"style":82},[206],{"type":36,"value":135},{"type":31,"tag":75,"props":208,"children":209},{"style":88},[210],{"type":36,"value":91},{"type":31,"tag":75,"props":212,"children":213},{"style":142},[214],{"type":36,"value":215},"events\n",{"type":31,"tag":75,"props":217,"children":219},{"class":77,"line":218},9,[220,225],{"type":31,"tag":75,"props":221,"children":222},{"style":82},[223],{"type":36,"value":224},"        freshness",{"type":31,"tag":75,"props":226,"children":227},{"style":88},[228],{"type":36,"value":121},{"type":31,"tag":75,"props":230,"children":232},{"class":77,"line":231},10,[233,238,243,248,252,257,262,267,271,276],{"type":31,"tag":75,"props":234,"children":235},{"style":82},[236],{"type":36,"value":237},"          warn_after",{"type":31,"tag":75,"props":239,"children":240},{"style":88},[241],{"type":36,"value":242},": {",{"type":31,"tag":75,"props":244,"children":245},{"style":82},[246],{"type":36,"value":247},"count",{"type":31,"tag":75,"props":249,"children":250},{"style":88},[251],{"type":36,"value":91},{"type":31,"tag":75,"props":253,"children":254},{"style":94},[255],{"type":36,"value":256},"6",{"type":31,"tag":75,"props":258,"children":259},{"style":88},[260],{"type":36,"value":261},", ",{"type":31,"tag":75,"props":263,"children":264},{"style":82},[265],{"type":36,"value":266},"period",{"type":31,"tag":75,"props":268,"children":269},{"style":88},[270],{"type":36,"value":91},{"type":31,"tag":75,"props":272,"children":273},{"style":142},[274],{"type":36,"value":275},"hour",{"type":31,"tag":75,"props":277,"children":278},{"style":88},[279],{"type":36,"value":280},"}\n",{"type":31,"tag":75,"props":282,"children":284},{"class":77,"line":283},11,[285,290,294,298,302,307,311,315,319,323],{"type":31,"tag":75,"props":286,"children":287},{"style":82},[288],{"type":36,"value":289},"          error_after",{"type":31,"tag":75,"props":291,"children":292},{"style":88},[293],{"type":36,"value":242},{"type":31,"tag":75,"props":295,"children":296},{"style":82},[297],{"type":36,"value":247},{"type":31,"tag":75,"props":299,"children":300},{"style":88},[301],{"type":36,"value":91},{"type":31,"tag":75,"props":303,"children":304},{"style":94},[305],{"type":36,"value":306},"12",{"type":31,"tag":75,"props":308,"children":309},{"style":88},[310],{"type":36,"value":261},{"type":31,"tag":75,"props":312,"children":313},{"style":82},[314],{"type":36,"value":266},{"type":31,"tag":75,"props":316,"children":317},{"style":88},[318],{"type":36,"value":91},{"type":31,"tag":75,"props":320,"children":321},{"style":142},[322],{"type":36,"value":275},{"type":31,"tag":75,"props":324,"children":325},{"style":88},[326],{"type":36,"value":280},{"type":31,"tag":75,"props":328,"children":330},{"class":77,"line":329},12,[331,336],{"type":31,"tag":75,"props":332,"children":333},{"style":82},[334],{"type":36,"value":335},"        columns",{"type":31,"tag":75,"props":337,"children":338},{"style":88},[339],{"type":36,"value":121},{"type":31,"tag":75,"props":341,"children":343},{"class":77,"line":342},13,[344,349,353,357],{"type":31,"tag":75,"props":345,"children":346},{"style":88},[347],{"type":36,"value":348},"          - ",{"type":31,"tag":75,"props":350,"children":351},{"style":82},[352],{"type":36,"value":135},{"type":31,"tag":75,"props":354,"children":355},{"style":88},[356],{"type":36,"value":91},{"type":31,"tag":75,"props":358,"children":359},{"style":142},[360],{"type":36,"value":361},"event_timestamp\n",{"type":31,"tag":75,"props":363,"children":365},{"class":77,"line":364},14,[366,371],{"type":31,"tag":75,"props":367,"children":368},{"style":82},[369],{"type":36,"value":370},"            tests",{"type":31,"tag":75,"props":372,"children":373},{"style":88},[374],{"type":36,"value":121},{"type":31,"tag":75,"props":376,"children":378},{"class":77,"line":377},15,[379,384],{"type":31,"tag":75,"props":380,"children":381},{"style":88},[382],{"type":36,"value":383},"              - ",{"type":31,"tag":75,"props":385,"children":386},{"style":142},[387],{"type":36,"value":388},"not_null\n",{"type":31,"tag":75,"props":390,"children":392},{"class":77,"line":391},16,[393,397,401,405],{"type":31,"tag":75,"props":394,"children":395},{"style":88},[396],{"type":36,"value":348},{"type":31,"tag":75,"props":398,"children":399},{"style":82},[400],{"type":36,"value":135},{"type":31,"tag":75,"props":402,"children":403},{"style":88},[404],{"type":36,"value":91},{"type":31,"tag":75,"props":406,"children":407},{"style":142},[408],{"type":36,"value":409},"user_pseudo_id\n",{"type":31,"tag":75,"props":411,"children":413},{"class":77,"line":412},17,[414,418],{"type":31,"tag":75,"props":415,"children":416},{"style":82},[417],{"type":36,"value":370},{"type":31,"tag":75,"props":419,"children":420},{"style":88},[421],{"type":36,"value":121},{"type":31,"tag":75,"props":423,"children":425},{"class":77,"line":424},18,[426,430],{"type":31,"tag":75,"props":427,"children":428},{"style":88},[429],{"type":36,"value":383},{"type":31,"tag":75,"props":431,"children":432},{"style":142},[433],{"type":36,"value":388},{"type":31,"tag":32,"props":435,"children":436},{},[437],{"type":36,"value":438},"Это определение устанавливает контракт: \"Если событие GA4 не поступило за 6 часов — выдать предупреждение, за 12 часов — остановить pipeline.\" В production этот тест привязывается к CI\u002FCD — проблемы с источником обнаруживаются мгновенно. dbt docs автоматически генерирует граф lineage — вы видите, какой дашборд зависит от какого источника.",{"type":31,"tag":32,"props":440,"children":441},{},[442,444,450,452,458],{"type":36,"value":443},"Без source mapping аналитик начинает с ",{"type":31,"tag":51,"props":445,"children":447},{"className":446},[],[448],{"type":36,"value":449},"SELECT * FROM analytics_lake.raw_ga4_events.events",{"type":36,"value":451}," — он не знает, что означает каждая колонка, нет тестов, нет документации. С dbt вы ссылаетесь на источник: ",{"type":31,"tag":51,"props":453,"children":455},{"className":454},[],[456],{"type":36,"value":457},"{{ source('raw_ga4', 'events') }}",{"type":36,"value":459},". Если название таблицы изменится, вы обновляете его в одном месте, все нижестоящие модели автоматически адаптируются.",{"type":31,"tag":39,"props":461,"children":463},{"id":462},"modeling-layer-staging-intermediate-mart",[464],{"type":36,"value":465},"Modeling Layer: Staging, Intermediate, Mart",{"type":31,"tag":32,"props":467,"children":468},{},[469],{"type":36,"value":470},"Мощь dbt проявляется в слоях моделирования. Вы разделяете процесс на три уровня: staging (нормализуете формат из источника), intermediate (применяете бизнес-логику), mart (создаёте финальные таблицы метрик).",{"type":31,"tag":32,"props":472,"children":473},{},[474,480],{"type":31,"tag":475,"props":476,"children":477},"strong",{},[478],{"type":36,"value":479},"Staging layer:",{"type":36,"value":481}," для каждого источника одна модель. Только преобразование типов данных, переименование колонок, приведение временных меток к UTC. Никакой бизнес-логики.",{"type":31,"tag":65,"props":483,"children":487},{"className":484,"code":485,"language":486,"meta":15,"style":15},"language-sql shiki shiki-themes github-dark","-- models\u002Fstaging\u002Fstg_ga4__events.sql\nWITH source AS (\n    SELECT * FROM {{ source('raw_ga4', 'events') }}\n)\n\nSELECT\n    TIMESTAMP_MICROS(event_timestamp) AS event_at,\n    user_pseudo_id AS user_id,\n    event_name,\n    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page_url\nFROM source\nWHERE event_date >= CURRENT_DATE() - 90\n","sql",[488],{"type":31,"tag":51,"props":489,"children":490},{"__ignoreMap":15},[491,500,524,566,574,581,589,606,623,631,702,715],{"type":31,"tag":75,"props":492,"children":493},{"class":77,"line":78},[494],{"type":31,"tag":75,"props":495,"children":497},{"style":496},"--shiki-default:#6A737D",[498],{"type":36,"value":499},"-- models\u002Fstaging\u002Fstg_ga4__events.sql\n",{"type":31,"tag":75,"props":501,"children":502},{"class":77,"line":100},[503,509,514,519],{"type":31,"tag":75,"props":504,"children":506},{"style":505},"--shiki-default:#F97583",[507],{"type":36,"value":508},"WITH",{"type":31,"tag":75,"props":510,"children":511},{"style":88},[512],{"type":36,"value":513}," source ",{"type":31,"tag":75,"props":515,"children":516},{"style":505},[517],{"type":36,"value":518},"AS",{"type":31,"tag":75,"props":520,"children":521},{"style":88},[522],{"type":36,"value":523}," (\n",{"type":31,"tag":75,"props":525,"children":526},{"class":77,"line":110},[527,532,537,542,547,552,556,561],{"type":31,"tag":75,"props":528,"children":529},{"style":505},[530],{"type":36,"value":531},"    SELECT",{"type":31,"tag":75,"props":533,"children":534},{"style":505},[535],{"type":36,"value":536}," *",{"type":31,"tag":75,"props":538,"children":539},{"style":505},[540],{"type":36,"value":541}," FROM",{"type":31,"tag":75,"props":543,"children":544},{"style":88},[545],{"type":36,"value":546}," {{ source(",{"type":31,"tag":75,"props":548,"children":549},{"style":142},[550],{"type":36,"value":551},"'raw_ga4'",{"type":31,"tag":75,"props":553,"children":554},{"style":88},[555],{"type":36,"value":261},{"type":31,"tag":75,"props":557,"children":558},{"style":142},[559],{"type":36,"value":560},"'events'",{"type":31,"tag":75,"props":562,"children":563},{"style":88},[564],{"type":36,"value":565},") }}\n",{"type":31,"tag":75,"props":567,"children":568},{"class":77,"line":124},[569],{"type":31,"tag":75,"props":570,"children":571},{"style":88},[572],{"type":36,"value":573},")\n",{"type":31,"tag":75,"props":575,"children":576},{"class":77,"line":148},[577],{"type":31,"tag":75,"props":578,"children":579},{"emptyLinePlaceholder":104},[580],{"type":36,"value":107},{"type":31,"tag":75,"props":582,"children":583},{"class":77,"line":166},[584],{"type":31,"tag":75,"props":585,"children":586},{"style":505},[587],{"type":36,"value":588},"SELECT\n",{"type":31,"tag":75,"props":590,"children":591},{"class":77,"line":184},[592,597,601],{"type":31,"tag":75,"props":593,"children":594},{"style":88},[595],{"type":36,"value":596},"    TIMESTAMP_MICROS(event_timestamp) ",{"type":31,"tag":75,"props":598,"children":599},{"style":505},[600],{"type":36,"value":518},{"type":31,"tag":75,"props":602,"children":603},{"style":88},[604],{"type":36,"value":605}," event_at,\n",{"type":31,"tag":75,"props":607,"children":608},{"class":77,"line":25},[609,614,618],{"type":31,"tag":75,"props":610,"children":611},{"style":88},[612],{"type":36,"value":613},"    user_pseudo_id ",{"type":31,"tag":75,"props":615,"children":616},{"style":505},[617],{"type":36,"value":518},{"type":31,"tag":75,"props":619,"children":620},{"style":88},[621],{"type":36,"value":622}," user_id,\n",{"type":31,"tag":75,"props":624,"children":625},{"class":77,"line":218},[626],{"type":31,"tag":75,"props":627,"children":628},{"style":88},[629],{"type":36,"value":630},"    event_name,\n",{"type":31,"tag":75,"props":632,"children":633},{"class":77,"line":231},[634,639,644,649,654,659,663,668,673,678,683,688,693,697],{"type":31,"tag":75,"props":635,"children":636},{"style":88},[637],{"type":36,"value":638},"    (",{"type":31,"tag":75,"props":640,"children":641},{"style":505},[642],{"type":36,"value":643},"SELECT",{"type":31,"tag":75,"props":645,"children":646},{"style":94},[647],{"type":36,"value":648}," value",{"type":31,"tag":75,"props":650,"children":651},{"style":88},[652],{"type":36,"value":653},".",{"type":31,"tag":75,"props":655,"children":656},{"style":94},[657],{"type":36,"value":658},"string_value",{"type":31,"tag":75,"props":660,"children":661},{"style":505},[662],{"type":36,"value":541},{"type":31,"tag":75,"props":664,"children":665},{"style":88},[666],{"type":36,"value":667}," UNNEST(event_params) ",{"type":31,"tag":75,"props":669,"children":670},{"style":505},[671],{"type":36,"value":672},"WHERE",{"type":31,"tag":75,"props":674,"children":675},{"style":505},[676],{"type":36,"value":677}," key",{"type":31,"tag":75,"props":679,"children":680},{"style":505},[681],{"type":36,"value":682}," =",{"type":31,"tag":75,"props":684,"children":685},{"style":142},[686],{"type":36,"value":687}," 'page_location'",{"type":31,"tag":75,"props":689,"children":690},{"style":88},[691],{"type":36,"value":692},") ",{"type":31,"tag":75,"props":694,"children":695},{"style":505},[696],{"type":36,"value":518},{"type":31,"tag":75,"props":698,"children":699},{"style":88},[700],{"type":36,"value":701}," page_url\n",{"type":31,"tag":75,"props":703,"children":704},{"class":77,"line":283},[705,710],{"type":31,"tag":75,"props":706,"children":707},{"style":505},[708],{"type":36,"value":709},"FROM",{"type":31,"tag":75,"props":711,"children":712},{"style":88},[713],{"type":36,"value":714}," source\n",{"type":31,"tag":75,"props":716,"children":717},{"class":77,"line":329},[718,722,727,732,737,742],{"type":31,"tag":75,"props":719,"children":720},{"style":505},[721],{"type":36,"value":672},{"type":31,"tag":75,"props":723,"children":724},{"style":88},[725],{"type":36,"value":726}," event_date ",{"type":31,"tag":75,"props":728,"children":729},{"style":505},[730],{"type":36,"value":731},">=",{"type":31,"tag":75,"props":733,"children":734},{"style":88},[735],{"type":36,"value":736}," CURRENT_DATE() ",{"type":31,"tag":75,"props":738,"children":739},{"style":505},[740],{"type":36,"value":741},"-",{"type":31,"tag":75,"props":743,"children":744},{"style":94},[745],{"type":36,"value":746}," 90\n",{"type":31,"tag":32,"props":748,"children":749},{},[750,755],{"type":31,"tag":475,"props":751,"children":752},{},[753],{"type":36,"value":754},"Intermediate layer:",{"type":36,"value":756}," здесь применяется бизнес-логика. Определяете сессии, маппируете категории продуктов, применяете окно атрибуции. Эти модели не идут конечному пользователю — они служат входом для нижестоящих моделей.",{"type":31,"tag":65,"props":758,"children":760},{"className":484,"code":759,"language":486,"meta":15,"style":15},"-- models\u002Fintermediate\u002Fint_sessions.sql\nWITH events AS (\n    SELECT * FROM {{ ref('stg_ga4__events') }}\n),\n\nsession_windows AS (\n    SELECT\n        user_id,\n        event_at,\n        SUM(CASE WHEN TIMESTAMP_DIFF(event_at, LAG(event_at) OVER (PARTITION BY user_id ORDER BY event_at), MINUTE) > 30 THEN 1 ELSE 0 END) \n            OVER (PARTITION BY user_id ORDER BY event_at) AS session_index\n    FROM events\n)\n\nSELECT\n    user_id,\n    session_index,\n    MIN(event_at) AS session_start_at,\n    MAX(event_at) AS session_end_at,\n    COUNT(*) AS event_count\nFROM session_windows\nGROUP BY 1, 2\n",[761],{"type":31,"tag":51,"props":762,"children":763},{"__ignoreMap":15},[764,772,792,821,829,836,852,860,868,876,998,1040,1053,1060,1067,1074,1082,1090,1111,1133,1164,1177],{"type":31,"tag":75,"props":765,"children":766},{"class":77,"line":78},[767],{"type":31,"tag":75,"props":768,"children":769},{"style":496},[770],{"type":36,"value":771},"-- models\u002Fintermediate\u002Fint_sessions.sql\n",{"type":31,"tag":75,"props":773,"children":774},{"class":77,"line":100},[775,779,784,788],{"type":31,"tag":75,"props":776,"children":777},{"style":505},[778],{"type":36,"value":508},{"type":31,"tag":75,"props":780,"children":781},{"style":88},[782],{"type":36,"value":783}," events ",{"type":31,"tag":75,"props":785,"children":786},{"style":505},[787],{"type":36,"value":518},{"type":31,"tag":75,"props":789,"children":790},{"style":88},[791],{"type":36,"value":523},{"type":31,"tag":75,"props":793,"children":794},{"class":77,"line":110},[795,799,803,807,812,817],{"type":31,"tag":75,"props":796,"children":797},{"style":505},[798],{"type":36,"value":531},{"type":31,"tag":75,"props":800,"children":801},{"style":505},[802],{"type":36,"value":536},{"type":31,"tag":75,"props":804,"children":805},{"style":505},[806],{"type":36,"value":541},{"type":31,"tag":75,"props":808,"children":809},{"style":88},[810],{"type":36,"value":811}," {{ ref(",{"type":31,"tag":75,"props":813,"children":814},{"style":142},[815],{"type":36,"value":816},"'stg_ga4__events'",{"type":31,"tag":75,"props":818,"children":819},{"style":88},[820],{"type":36,"value":565},{"type":31,"tag":75,"props":822,"children":823},{"class":77,"line":124},[824],{"type":31,"tag":75,"props":825,"children":826},{"style":88},[827],{"type":36,"value":828},"),\n",{"type":31,"tag":75,"props":830,"children":831},{"class":77,"line":148},[832],{"type":31,"tag":75,"props":833,"children":834},{"emptyLinePlaceholder":104},[835],{"type":36,"value":107},{"type":31,"tag":75,"props":837,"children":838},{"class":77,"line":166},[839,844,848],{"type":31,"tag":75,"props":840,"children":841},{"style":88},[842],{"type":36,"value":843},"session_windows ",{"type":31,"tag":75,"props":845,"children":846},{"style":505},[847],{"type":36,"value":518},{"type":31,"tag":75,"props":849,"children":850},{"style":88},[851],{"type":36,"value":523},{"type":31,"tag":75,"props":853,"children":854},{"class":77,"line":184},[855],{"type":31,"tag":75,"props":856,"children":857},{"style":505},[858],{"type":36,"value":859},"    SELECT\n",{"type":31,"tag":75,"props":861,"children":862},{"class":77,"line":25},[863],{"type":31,"tag":75,"props":864,"children":865},{"style":88},[866],{"type":36,"value":867},"        user_id,\n",{"type":31,"tag":75,"props":869,"children":870},{"class":77,"line":218},[871],{"type":31,"tag":75,"props":872,"children":873},{"style":88},[874],{"type":36,"value":875},"        event_at,\n",{"type":31,"tag":75,"props":877,"children":878},{"class":77,"line":231},[879,884,889,894,899,904,909,914,919,924,929,934,939,944,949,954,958,963,968,973,978,983,988,993],{"type":31,"tag":75,"props":880,"children":881},{"style":94},[882],{"type":36,"value":883},"        SUM",{"type":31,"tag":75,"props":885,"children":886},{"style":88},[887],{"type":36,"value":888},"(",{"type":31,"tag":75,"props":890,"children":891},{"style":505},[892],{"type":36,"value":893},"CASE",{"type":31,"tag":75,"props":895,"children":896},{"style":505},[897],{"type":36,"value":898}," WHEN",{"type":31,"tag":75,"props":900,"children":901},{"style":88},[902],{"type":36,"value":903}," TIMESTAMP_DIFF(event_at, ",{"type":31,"tag":75,"props":905,"children":906},{"style":94},[907],{"type":36,"value":908},"LAG",{"type":31,"tag":75,"props":910,"children":911},{"style":88},[912],{"type":36,"value":913},"(event_at) ",{"type":31,"tag":75,"props":915,"children":916},{"style":505},[917],{"type":36,"value":918},"OVER",{"type":31,"tag":75,"props":920,"children":921},{"style":88},[922],{"type":36,"value":923}," (",{"type":31,"tag":75,"props":925,"children":926},{"style":505},[927],{"type":36,"value":928},"PARTITION",{"type":31,"tag":75,"props":930,"children":931},{"style":505},[932],{"type":36,"value":933}," BY",{"type":31,"tag":75,"props":935,"children":936},{"style":88},[937],{"type":36,"value":938}," user_id ",{"type":31,"tag":75,"props":940,"children":941},{"style":505},[942],{"type":36,"value":943},"ORDER BY",{"type":31,"tag":75,"props":945,"children":946},{"style":88},[947],{"type":36,"value":948}," event_at), ",{"type":31,"tag":75,"props":950,"children":951},{"style":505},[952],{"type":36,"value":953},"MINUTE",{"type":31,"tag":75,"props":955,"children":956},{"style":88},[957],{"type":36,"value":692},{"type":31,"tag":75,"props":959,"children":960},{"style":505},[961],{"type":36,"value":962},">",{"type":31,"tag":75,"props":964,"children":965},{"style":94},[966],{"type":36,"value":967}," 30",{"type":31,"tag":75,"props":969,"children":970},{"style":505},[971],{"type":36,"value":972}," THEN",{"type":31,"tag":75,"props":974,"children":975},{"style":94},[976],{"type":36,"value":977}," 1",{"type":31,"tag":75,"props":979,"children":980},{"style":505},[981],{"type":36,"value":982}," ELSE",{"type":31,"tag":75,"props":984,"children":985},{"style":94},[986],{"type":36,"value":987}," 0",{"type":31,"tag":75,"props":989,"children":990},{"style":505},[991],{"type":36,"value":992}," END",{"type":31,"tag":75,"props":994,"children":995},{"style":88},[996],{"type":36,"value":997},") \n",{"type":31,"tag":75,"props":999,"children":1000},{"class":77,"line":283},[1001,1006,1010,1014,1018,1022,1026,1031,1035],{"type":31,"tag":75,"props":1002,"children":1003},{"style":505},[1004],{"type":36,"value":1005},"            OVER",{"type":31,"tag":75,"props":1007,"children":1008},{"style":88},[1009],{"type":36,"value":923},{"type":31,"tag":75,"props":1011,"children":1012},{"style":505},[1013],{"type":36,"value":928},{"type":31,"tag":75,"props":1015,"children":1016},{"style":505},[1017],{"type":36,"value":933},{"type":31,"tag":75,"props":1019,"children":1020},{"style":88},[1021],{"type":36,"value":938},{"type":31,"tag":75,"props":1023,"children":1024},{"style":505},[1025],{"type":36,"value":943},{"type":31,"tag":75,"props":1027,"children":1028},{"style":88},[1029],{"type":36,"value":1030}," event_at) ",{"type":31,"tag":75,"props":1032,"children":1033},{"style":505},[1034],{"type":36,"value":518},{"type":31,"tag":75,"props":1036,"children":1037},{"style":88},[1038],{"type":36,"value":1039}," session_index\n",{"type":31,"tag":75,"props":1041,"children":1042},{"class":77,"line":329},[1043,1048],{"type":31,"tag":75,"props":1044,"children":1045},{"style":505},[1046],{"type":36,"value":1047},"    FROM",{"type":31,"tag":75,"props":1049,"children":1050},{"style":88},[1051],{"type":36,"value":1052}," events\n",{"type":31,"tag":75,"props":1054,"children":1055},{"class":77,"line":342},[1056],{"type":31,"tag":75,"props":1057,"children":1058},{"style":88},[1059],{"type":36,"value":573},{"type":31,"tag":75,"props":1061,"children":1062},{"class":77,"line":364},[1063],{"type":31,"tag":75,"props":1064,"children":1065},{"emptyLinePlaceholder":104},[1066],{"type":36,"value":107},{"type":31,"tag":75,"props":1068,"children":1069},{"class":77,"line":377},[1070],{"type":31,"tag":75,"props":1071,"children":1072},{"style":505},[1073],{"type":36,"value":588},{"type":31,"tag":75,"props":1075,"children":1076},{"class":77,"line":391},[1077],{"type":31,"tag":75,"props":1078,"children":1079},{"style":88},[1080],{"type":36,"value":1081},"    user_id,\n",{"type":31,"tag":75,"props":1083,"children":1084},{"class":77,"line":412},[1085],{"type":31,"tag":75,"props":1086,"children":1087},{"style":88},[1088],{"type":36,"value":1089},"    session_index,\n",{"type":31,"tag":75,"props":1091,"children":1092},{"class":77,"line":424},[1093,1098,1102,1106],{"type":31,"tag":75,"props":1094,"children":1095},{"style":94},[1096],{"type":36,"value":1097},"    MIN",{"type":31,"tag":75,"props":1099,"children":1100},{"style":88},[1101],{"type":36,"value":913},{"type":31,"tag":75,"props":1103,"children":1104},{"style":505},[1105],{"type":36,"value":518},{"type":31,"tag":75,"props":1107,"children":1108},{"style":88},[1109],{"type":36,"value":1110}," session_start_at,\n",{"type":31,"tag":75,"props":1112,"children":1114},{"class":77,"line":1113},19,[1115,1120,1124,1128],{"type":31,"tag":75,"props":1116,"children":1117},{"style":94},[1118],{"type":36,"value":1119},"    MAX",{"type":31,"tag":75,"props":1121,"children":1122},{"style":88},[1123],{"type":36,"value":913},{"type":31,"tag":75,"props":1125,"children":1126},{"style":505},[1127],{"type":36,"value":518},{"type":31,"tag":75,"props":1129,"children":1130},{"style":88},[1131],{"type":36,"value":1132}," session_end_at,\n",{"type":31,"tag":75,"props":1134,"children":1136},{"class":77,"line":1135},20,[1137,1142,1146,1151,1155,1159],{"type":31,"tag":75,"props":1138,"children":1139},{"style":94},[1140],{"type":36,"value":1141},"    COUNT",{"type":31,"tag":75,"props":1143,"children":1144},{"style":88},[1145],{"type":36,"value":888},{"type":31,"tag":75,"props":1147,"children":1148},{"style":505},[1149],{"type":36,"value":1150},"*",{"type":31,"tag":75,"props":1152,"children":1153},{"style":88},[1154],{"type":36,"value":692},{"type":31,"tag":75,"props":1156,"children":1157},{"style":505},[1158],{"type":36,"value":518},{"type":31,"tag":75,"props":1160,"children":1161},{"style":88},[1162],{"type":36,"value":1163}," event_count\n",{"type":31,"tag":75,"props":1165,"children":1167},{"class":77,"line":1166},21,[1168,1172],{"type":31,"tag":75,"props":1169,"children":1170},{"style":505},[1171],{"type":36,"value":709},{"type":31,"tag":75,"props":1173,"children":1174},{"style":88},[1175],{"type":36,"value":1176}," session_windows\n",{"type":31,"tag":75,"props":1178,"children":1180},{"class":77,"line":1179},22,[1181,1186,1190,1194],{"type":31,"tag":75,"props":1182,"children":1183},{"style":505},[1184],{"type":36,"value":1185},"GROUP BY",{"type":31,"tag":75,"props":1187,"children":1188},{"style":94},[1189],{"type":36,"value":977},{"type":31,"tag":75,"props":1191,"children":1192},{"style":88},[1193],{"type":36,"value":261},{"type":31,"tag":75,"props":1195,"children":1196},{"style":94},[1197],{"type":36,"value":97},{"type":31,"tag":32,"props":1199,"children":1200},{},[1201,1206,1208,1214,1216,1222],{"type":31,"tag":475,"props":1202,"children":1203},{},[1204],{"type":36,"value":1205},"Mart layer:",{"type":36,"value":1207}," финальные таблицы метрик. Это то, что подключается к дашбордам, BI-инструментам, Looker. Используйте префиксы ",{"type":31,"tag":51,"props":1209,"children":1211},{"className":1210},[],[1212],{"type":36,"value":1213},"fct_",{"type":36,"value":1215}," (fact) или ",{"type":31,"tag":51,"props":1217,"children":1219},{"className":1218},[],[1220],{"type":36,"value":1221},"dim_",{"type":36,"value":1223}," (dimension).",{"type":31,"tag":65,"props":1225,"children":1227},{"className":484,"code":1226,"language":486,"meta":15,"style":15},"-- models\u002Fmarts\u002Ffct_daily_channel_performance.sql\nSELECT\n    DATE(session_start_at) AS date,\n    traffic_source.medium AS channel,\n    COUNT(DISTINCT user_id) AS users,\n    SUM(revenue) AS revenue,\n    SAFE_DIVIDE(SUM(revenue), COUNT(DISTINCT user_id)) AS revenue_per_user\nFROM {{ ref('int_sessions') }}\nLEFT JOIN {{ ref('int_transactions') }} USING (user_id, session_index)\nGROUP BY 1, 2\n",[1228],{"type":31,"tag":51,"props":1229,"children":1230},{"__ignoreMap":15},[1231,1239,1246,1273,1300,1330,1352,1397,1417,1449],{"type":31,"tag":75,"props":1232,"children":1233},{"class":77,"line":78},[1234],{"type":31,"tag":75,"props":1235,"children":1236},{"style":496},[1237],{"type":36,"value":1238},"-- models\u002Fmarts\u002Ffct_daily_channel_performance.sql\n",{"type":31,"tag":75,"props":1240,"children":1241},{"class":77,"line":100},[1242],{"type":31,"tag":75,"props":1243,"children":1244},{"style":505},[1245],{"type":36,"value":588},{"type":31,"tag":75,"props":1247,"children":1248},{"class":77,"line":110},[1249,1254,1259,1263,1268],{"type":31,"tag":75,"props":1250,"children":1251},{"style":505},[1252],{"type":36,"value":1253},"    DATE",{"type":31,"tag":75,"props":1255,"children":1256},{"style":88},[1257],{"type":36,"value":1258},"(session_start_at) ",{"type":31,"tag":75,"props":1260,"children":1261},{"style":505},[1262],{"type":36,"value":518},{"type":31,"tag":75,"props":1264,"children":1265},{"style":505},[1266],{"type":36,"value":1267}," date",{"type":31,"tag":75,"props":1269,"children":1270},{"style":88},[1271],{"type":36,"value":1272},",\n",{"type":31,"tag":75,"props":1274,"children":1275},{"class":77,"line":124},[1276,1281,1285,1290,1295],{"type":31,"tag":75,"props":1277,"children":1278},{"style":94},[1279],{"type":36,"value":1280},"    traffic_source",{"type":31,"tag":75,"props":1282,"children":1283},{"style":88},[1284],{"type":36,"value":653},{"type":31,"tag":75,"props":1286,"children":1287},{"style":94},[1288],{"type":36,"value":1289},"medium",{"type":31,"tag":75,"props":1291,"children":1292},{"style":505},[1293],{"type":36,"value":1294}," AS",{"type":31,"tag":75,"props":1296,"children":1297},{"style":88},[1298],{"type":36,"value":1299}," channel,\n",{"type":31,"tag":75,"props":1301,"children":1302},{"class":77,"line":148},[1303,1307,1311,1316,1321,1325],{"type":31,"tag":75,"props":1304,"children":1305},{"style":94},[1306],{"type":36,"value":1141},{"type":31,"tag":75,"props":1308,"children":1309},{"style":88},[1310],{"type":36,"value":888},{"type":31,"tag":75,"props":1312,"children":1313},{"style":505},[1314],{"type":36,"value":1315},"DISTINCT",{"type":31,"tag":75,"props":1317,"children":1318},{"style":88},[1319],{"type":36,"value":1320}," user_id) ",{"type":31,"tag":75,"props":1322,"children":1323},{"style":505},[1324],{"type":36,"value":518},{"type":31,"tag":75,"props":1326,"children":1327},{"style":88},[1328],{"type":36,"value":1329}," users,\n",{"type":31,"tag":75,"props":1331,"children":1332},{"class":77,"line":166},[1333,1338,1343,1347],{"type":31,"tag":75,"props":1334,"children":1335},{"style":94},[1336],{"type":36,"value":1337},"    SUM",{"type":31,"tag":75,"props":1339,"children":1340},{"style":88},[1341],{"type":36,"value":1342},"(revenue) ",{"type":31,"tag":75,"props":1344,"children":1345},{"style":505},[1346],{"type":36,"value":518},{"type":31,"tag":75,"props":1348,"children":1349},{"style":88},[1350],{"type":36,"value":1351}," revenue,\n",{"type":31,"tag":75,"props":1353,"children":1354},{"class":77,"line":184},[1355,1360,1365,1370,1375,1379,1383,1388,1392],{"type":31,"tag":75,"props":1356,"children":1357},{"style":88},[1358],{"type":36,"value":1359},"    SAFE_DIVIDE(",{"type":31,"tag":75,"props":1361,"children":1362},{"style":94},[1363],{"type":36,"value":1364},"SUM",{"type":31,"tag":75,"props":1366,"children":1367},{"style":88},[1368],{"type":36,"value":1369},"(revenue), ",{"type":31,"tag":75,"props":1371,"children":1372},{"style":94},[1373],{"type":36,"value":1374},"COUNT",{"type":31,"tag":75,"props":1376,"children":1377},{"style":88},[1378],{"type":36,"value":888},{"type":31,"tag":75,"props":1380,"children":1381},{"style":505},[1382],{"type":36,"value":1315},{"type":31,"tag":75,"props":1384,"children":1385},{"style":88},[1386],{"type":36,"value":1387}," user_id)) ",{"type":31,"tag":75,"props":1389,"children":1390},{"style":505},[1391],{"type":36,"value":518},{"type":31,"tag":75,"props":1393,"children":1394},{"style":88},[1395],{"type":36,"value":1396}," revenue_per_user\n",{"type":31,"tag":75,"props":1398,"children":1399},{"class":77,"line":25},[1400,1404,1408,1413],{"type":31,"tag":75,"props":1401,"children":1402},{"style":505},[1403],{"type":36,"value":709},{"type":31,"tag":75,"props":1405,"children":1406},{"style":88},[1407],{"type":36,"value":811},{"type":31,"tag":75,"props":1409,"children":1410},{"style":142},[1411],{"type":36,"value":1412},"'int_sessions'",{"type":31,"tag":75,"props":1414,"children":1415},{"style":88},[1416],{"type":36,"value":565},{"type":31,"tag":75,"props":1418,"children":1419},{"class":77,"line":218},[1420,1425,1429,1434,1439,1444],{"type":31,"tag":75,"props":1421,"children":1422},{"style":505},[1423],{"type":36,"value":1424},"LEFT JOIN",{"type":31,"tag":75,"props":1426,"children":1427},{"style":88},[1428],{"type":36,"value":811},{"type":31,"tag":75,"props":1430,"children":1431},{"style":142},[1432],{"type":36,"value":1433},"'int_transactions'",{"type":31,"tag":75,"props":1435,"children":1436},{"style":88},[1437],{"type":36,"value":1438},") }} ",{"type":31,"tag":75,"props":1440,"children":1441},{"style":505},[1442],{"type":36,"value":1443},"USING",{"type":31,"tag":75,"props":1445,"children":1446},{"style":88},[1447],{"type":36,"value":1448}," (user_id, session_index)\n",{"type":31,"tag":75,"props":1450,"children":1451},{"class":77,"line":231},[1452,1456,1460,1464],{"type":31,"tag":75,"props":1453,"children":1454},{"style":505},[1455],{"type":36,"value":1185},{"type":31,"tag":75,"props":1457,"children":1458},{"style":94},[1459],{"type":36,"value":977},{"type":31,"tag":75,"props":1461,"children":1462},{"style":88},[1463],{"type":36,"value":261},{"type":31,"tag":75,"props":1465,"children":1466},{"style":94},[1467],{"type":36,"value":97},{"type":31,"tag":32,"props":1469,"children":1470},{},[1471,1473,1479],{"type":36,"value":1472},"С этой структурой аналитик работает с таблицей ",{"type":31,"tag":51,"props":1474,"children":1476},{"className":1475},[],[1477],{"type":36,"value":1478},"fct_daily_channel_performance",{"type":36,"value":1480},", не трогая логику в staging\u002Fintermediate. Если определение метрики изменится, обновление произойдёт в одном месте, все дашборды останутся согласованными.",{"type":31,"tag":39,"props":1482,"children":1484},{"id":1483},"semantic-layer-кодируем-определения-метрик",[1485],{"type":36,"value":1486},"Semantic Layer: кодируем определения метрик",{"type":31,"tag":32,"props":1488,"children":1489},{},[1490],{"type":36,"value":1491},"В комбинации BigQuery + dbt концепция \"semantic layer\" реализуется двумя способами: dbt metrics (deprecated в 2023) или dbt semantic models (новый подход). Semantic model отделяет метрику от SQL и определяет её в YAML. Looker, Tableau, Mode читают это определение и вычисляют CAC, LTV, ROAS согласованно.",{"type":31,"tag":32,"props":1493,"children":1494},{},[1495],{"type":36,"value":1496},"Пример semantic model:",{"type":31,"tag":65,"props":1498,"children":1500},{"className":67,"code":1499,"language":69,"meta":15,"style":15},"# models\u002Fmarts\u002Fsemantic_models.yml\nsemantic_models:\n  - name: channel_performance\n    model: ref('fct_daily_channel_performance')\n    dimensions:\n      - name: date\n        type: time\n        type_params:\n          time_granularity: day\n      - name: channel\n        type: categorical\n    measures:\n      - name: total_revenue\n        agg: sum\n        expr: revenue\n      - name: total_users\n        agg: count_distinct\n        expr: user_id\n\nmetrics:\n  - name: revenue_per_user\n    type: derived\n    type_params:\n      expr: total_revenue \u002F total_users\n      metrics:\n        - total_revenue\n        - total_users\n",[1501],{"type":31,"tag":51,"props":1502,"children":1503},{"__ignoreMap":15},[1504,1512,1524,1544,1561,1573,1593,1610,1622,1639,1659,1675,1687,1707,1724,1741,1761,1777,1793,1800,1812,1832,1849,1862,1880,1893,1906],{"type":31,"tag":75,"props":1505,"children":1506},{"class":77,"line":78},[1507],{"type":31,"tag":75,"props":1508,"children":1509},{"style":496},[1510],{"type":36,"value":1511},"# models\u002Fmarts\u002Fsemantic_models.yml\n",{"type":31,"tag":75,"props":1513,"children":1514},{"class":77,"line":100},[1515,1520],{"type":31,"tag":75,"props":1516,"children":1517},{"style":82},[1518],{"type":36,"value":1519},"semantic_models",{"type":31,"tag":75,"props":1521,"children":1522},{"style":88},[1523],{"type":36,"value":121},{"type":31,"tag":75,"props":1525,"children":1526},{"class":77,"line":110},[1527,1531,1535,1539],{"type":31,"tag":75,"props":1528,"children":1529},{"style":88},[1530],{"type":36,"value":130},{"type":31,"tag":75,"props":1532,"children":1533},{"style":82},[1534],{"type":36,"value":135},{"type":31,"tag":75,"props":1536,"children":1537},{"style":88},[1538],{"type":36,"value":91},{"type":31,"tag":75,"props":1540,"children":1541},{"style":142},[1542],{"type":36,"value":1543},"channel_performance\n",{"type":31,"tag":75,"props":1545,"children":1546},{"class":77,"line":124},[1547,1552,1556],{"type":31,"tag":75,"props":1548,"children":1549},{"style":82},[1550],{"type":36,"value":1551},"    model",{"type":31,"tag":75,"props":1553,"children":1554},{"style":88},[1555],{"type":36,"value":91},{"type":31,"tag":75,"props":1557,"children":1558},{"style":142},[1559],{"type":36,"value":1560},"ref('fct_daily_channel_performance')\n",{"type":31,"tag":75,"props":1562,"children":1563},{"class":77,"line":148},[1564,1569],{"type":31,"tag":75,"props":1565,"children":1566},{"style":82},[1567],{"type":36,"value":1568},"    dimensions",{"type":31,"tag":75,"props":1570,"children":1571},{"style":88},[1572],{"type":36,"value":121},{"type":31,"tag":75,"props":1574,"children":1575},{"class":77,"line":166},[1576,1580,1584,1588],{"type":31,"tag":75,"props":1577,"children":1578},{"style":88},[1579],{"type":36,"value":202},{"type":31,"tag":75,"props":1581,"children":1582},{"style":82},[1583],{"type":36,"value":135},{"type":31,"tag":75,"props":1585,"children":1586},{"style":88},[1587],{"type":36,"value":91},{"type":31,"tag":75,"props":1589,"children":1590},{"style":142},[1591],{"type":36,"value":1592},"date\n",{"type":31,"tag":75,"props":1594,"children":1595},{"class":77,"line":184},[1596,1601,1605],{"type":31,"tag":75,"props":1597,"children":1598},{"style":82},[1599],{"type":36,"value":1600},"        type",{"type":31,"tag":75,"props":1602,"children":1603},{"style":88},[1604],{"type":36,"value":91},{"type":31,"tag":75,"props":1606,"children":1607},{"style":142},[1608],{"type":36,"value":1609},"time\n",{"type":31,"tag":75,"props":1611,"children":1612},{"class":77,"line":25},[1613,1618],{"type":31,"tag":75,"props":1614,"children":1615},{"style":82},[1616],{"type":36,"value":1617},"        type_params",{"type":31,"tag":75,"props":1619,"children":1620},{"style":88},[1621],{"type":36,"value":121},{"type":31,"tag":75,"props":1623,"children":1624},{"class":77,"line":218},[1625,1630,1634],{"type":31,"tag":75,"props":1626,"children":1627},{"style":82},[1628],{"type":36,"value":1629},"          time_granularity",{"type":31,"tag":75,"props":1631,"children":1632},{"style":88},[1633],{"type":36,"value":91},{"type":31,"tag":75,"props":1635,"children":1636},{"style":142},[1637],{"type":36,"value":1638},"day\n",{"type":31,"tag":75,"props":1640,"children":1641},{"class":77,"line":231},[1642,1646,1650,1654],{"type":31,"tag":75,"props":1643,"children":1644},{"style":88},[1645],{"type":36,"value":202},{"type":31,"tag":75,"props":1647,"children":1648},{"style":82},[1649],{"type":36,"value":135},{"type":31,"tag":75,"props":1651,"children":1652},{"style":88},[1653],{"type":36,"value":91},{"type":31,"tag":75,"props":1655,"children":1656},{"style":142},[1657],{"type":36,"value":1658},"channel\n",{"type":31,"tag":75,"props":1660,"children":1661},{"class":77,"line":283},[1662,1666,1670],{"type":31,"tag":75,"props":1663,"children":1664},{"style":82},[1665],{"type":36,"value":1600},{"type":31,"tag":75,"props":1667,"children":1668},{"style":88},[1669],{"type":36,"value":91},{"type":31,"tag":75,"props":1671,"children":1672},{"style":142},[1673],{"type":36,"value":1674},"categorical\n",{"type":31,"tag":75,"props":1676,"children":1677},{"class":77,"line":329},[1678,1683],{"type":31,"tag":75,"props":1679,"children":1680},{"style":82},[1681],{"type":36,"value":1682},"    measures",{"type":31,"tag":75,"props":1684,"children":1685},{"style":88},[1686],{"type":36,"value":121},{"type":31,"tag":75,"props":1688,"children":1689},{"class":77,"line":342},[1690,1694,1698,1702],{"type":31,"tag":75,"props":1691,"children":1692},{"style":88},[1693],{"type":36,"value":202},{"type":31,"tag":75,"props":1695,"children":1696},{"style":82},[1697],{"type":36,"value":135},{"type":31,"tag":75,"props":1699,"children":1700},{"style":88},[1701],{"type":36,"value":91},{"type":31,"tag":75,"props":1703,"children":1704},{"style":142},[1705],{"type":36,"value":1706},"total_revenue\n",{"type":31,"tag":75,"props":1708,"children":1709},{"class":77,"line":364},[1710,1715,1719],{"type":31,"tag":75,"props":1711,"children":1712},{"style":82},[1713],{"type":36,"value":1714},"        agg",{"type":31,"tag":75,"props":1716,"children":1717},{"style":88},[1718],{"type":36,"value":91},{"type":31,"tag":75,"props":1720,"children":1721},{"style":142},[1722],{"type":36,"value":1723},"sum\n",{"type":31,"tag":75,"props":1725,"children":1726},{"class":77,"line":377},[1727,1732,1736],{"type":31,"tag":75,"props":1728,"children":1729},{"style":82},[1730],{"type":36,"value":1731},"        expr",{"type":31,"tag":75,"props":1733,"children":1734},{"style":88},[1735],{"type":36,"value":91},{"type":31,"tag":75,"props":1737,"children":1738},{"style":142},[1739],{"type":36,"value":1740},"revenue\n",{"type":31,"tag":75,"props":1742,"children":1743},{"class":77,"line":391},[1744,1748,1752,1756],{"type":31,"tag":75,"props":1745,"children":1746},{"style":88},[1747],{"type":36,"value":202},{"type":31,"tag":75,"props":1749,"children":1750},{"style":82},[1751],{"type":36,"value":135},{"type":31,"tag":75,"props":1753,"children":1754},{"style":88},[1755],{"type":36,"value":91},{"type":31,"tag":75,"props":1757,"children":1758},{"style":142},[1759],{"type":36,"value":1760},"total_users\n",{"type":31,"tag":75,"props":1762,"children":1763},{"class":77,"line":412},[1764,1768,1772],{"type":31,"tag":75,"props":1765,"children":1766},{"style":82},[1767],{"type":36,"value":1714},{"type":31,"tag":75,"props":1769,"children":1770},{"style":88},[1771],{"type":36,"value":91},{"type":31,"tag":75,"props":1773,"children":1774},{"style":142},[1775],{"type":36,"value":1776},"count_distinct\n",{"type":31,"tag":75,"props":1778,"children":1779},{"class":77,"line":424},[1780,1784,1788],{"type":31,"tag":75,"props":1781,"children":1782},{"style":82},[1783],{"type":36,"value":1731},{"type":31,"tag":75,"props":1785,"children":1786},{"style":88},[1787],{"type":36,"value":91},{"type":31,"tag":75,"props":1789,"children":1790},{"style":142},[1791],{"type":36,"value":1792},"user_id\n",{"type":31,"tag":75,"props":1794,"children":1795},{"class":77,"line":1113},[1796],{"type":31,"tag":75,"props":1797,"children":1798},{"emptyLinePlaceholder":104},[1799],{"type":36,"value":107},{"type":31,"tag":75,"props":1801,"children":1802},{"class":77,"line":1135},[1803,1808],{"type":31,"tag":75,"props":1804,"children":1805},{"style":82},[1806],{"type":36,"value":1807},"metrics",{"type":31,"tag":75,"props":1809,"children":1810},{"style":88},[1811],{"type":36,"value":121},{"type":31,"tag":75,"props":1813,"children":1814},{"class":77,"line":1166},[1815,1819,1823,1827],{"type":31,"tag":75,"props":1816,"children":1817},{"style":88},[1818],{"type":36,"value":130},{"type":31,"tag":75,"props":1820,"children":1821},{"style":82},[1822],{"type":36,"value":135},{"type":31,"tag":75,"props":1824,"children":1825},{"style":88},[1826],{"type":36,"value":91},{"type":31,"tag":75,"props":1828,"children":1829},{"style":142},[1830],{"type":36,"value":1831},"revenue_per_user\n",{"type":31,"tag":75,"props":1833,"children":1834},{"class":77,"line":1179},[1835,1840,1844],{"type":31,"tag":75,"props":1836,"children":1837},{"style":82},[1838],{"type":36,"value":1839},"    type",{"type":31,"tag":75,"props":1841,"children":1842},{"style":88},[1843],{"type":36,"value":91},{"type":31,"tag":75,"props":1845,"children":1846},{"style":142},[1847],{"type":36,"value":1848},"derived\n",{"type":31,"tag":75,"props":1850,"children":1852},{"class":77,"line":1851},23,[1853,1858],{"type":31,"tag":75,"props":1854,"children":1855},{"style":82},[1856],{"type":36,"value":1857},"    type_params",{"type":31,"tag":75,"props":1859,"children":1860},{"style":88},[1861],{"type":36,"value":121},{"type":31,"tag":75,"props":1863,"children":1865},{"class":77,"line":1864},24,[1866,1871,1875],{"type":31,"tag":75,"props":1867,"children":1868},{"style":82},[1869],{"type":36,"value":1870},"      expr",{"type":31,"tag":75,"props":1872,"children":1873},{"style":88},[1874],{"type":36,"value":91},{"type":31,"tag":75,"props":1876,"children":1877},{"style":142},[1878],{"type":36,"value":1879},"total_revenue \u002F total_users\n",{"type":31,"tag":75,"props":1881,"children":1883},{"class":77,"line":1882},25,[1884,1889],{"type":31,"tag":75,"props":1885,"children":1886},{"style":82},[1887],{"type":36,"value":1888},"      metrics",{"type":31,"tag":75,"props":1890,"children":1891},{"style":88},[1892],{"type":36,"value":121},{"type":31,"tag":75,"props":1894,"children":1896},{"class":77,"line":1895},26,[1897,1902],{"type":31,"tag":75,"props":1898,"children":1899},{"style":88},[1900],{"type":36,"value":1901},"        - ",{"type":31,"tag":75,"props":1903,"children":1904},{"style":142},[1905],{"type":36,"value":1706},{"type":31,"tag":75,"props":1907,"children":1909},{"class":77,"line":1908},27,[1910,1914],{"type":31,"tag":75,"props":1911,"children":1912},{"style":88},[1913],{"type":36,"value":1901},{"type":31,"tag":75,"props":1915,"children":1916},{"style":142},[1917],{"type":36,"value":1760},{"type":31,"tag":32,"props":1919,"children":1920},{},[1921],{"type":36,"value":1922},"С этим определением метрика \"revenue per user\" вычисляется одинаково везде. Аналитик в Looker выбирает \"RPU\", backend берёт определение из semantic layer dbt, SQL не пишется вручную. Если логика изменится (например, исключить отменённые заказы), вы обновляете одно место.",{"type":31,"tag":32,"props":1924,"children":1925},{},[1926,1928,1934,1936,1945],{"type":36,"value":1927},"Без semantic layer каждый дашборд переписывает ",{"type":31,"tag":51,"props":1929,"children":1931},{"className":1930},[],[1932],{"type":36,"value":1933},"revenue \u002F users",{"type":36,"value":1935},". В одном отчёте возврат исключен, в другом включен. CMO видит два разных числа — доверие к данным падает. С применением ",{"type":31,"tag":1937,"props":1938,"children":1942},"a",{"href":1939,"rel":1940},"https:\u002F\u002Fwww.roibase.com.tr\u002Fru\u002Ffirstparty",[1941],"nofollow",[1943],{"type":36,"value":1944},"Архитектуры первосторонних данных и измерений",{"type":36,"value":1946}," этот слой становится critical: вы кодируете атрибуцию, согласие, сигналы TCF по одной логике.",{"type":31,"tag":39,"props":1948,"children":1950},{"id":1949},"exposures-отслеживаем-финальное-применение-данных",[1951],{"type":36,"value":1952},"Exposures: отслеживаем финальное применение данных",{"type":31,"tag":32,"props":1954,"children":1955},{},[1956,1958,1964],{"type":36,"value":1957},"dbt exposure отвечает на вопрос: \"эта модель питает какой дашборд, какой ML-pipeline, какую операционную систему?\" Вы определяете это в ",{"type":31,"tag":51,"props":1959,"children":1961},{"className":1960},[],[1962],{"type":36,"value":1963},"exposures.yml",{"type":36,"value":1965},":",{"type":31,"tag":65,"props":1967,"children":1969},{"className":67,"code":1968,"language":69,"meta":15,"style":15},"exposures:\n  - name: marketing_dashboard\n    type: dashboard\n    maturity: high\n    url: https:\u002F\u002Flookerstudio.google.com\u002Freporting\u002Fabc123\n    description: \"Ежедневный дашборд перформанса каналов для CMO\"\n    depends_on:\n      - ref('fct_daily_channel_performance')\n    owner:\n      name: Marketing Analytics Team\n      email: analytics@company.com\n",[1970],{"type":31,"tag":51,"props":1971,"children":1972},{"__ignoreMap":15},[1973,1985,2005,2021,2038,2055,2072,2084,2095,2107,2124],{"type":31,"tag":75,"props":1974,"children":1975},{"class":77,"line":78},[1976,1981],{"type":31,"tag":75,"props":1977,"children":1978},{"style":82},[1979],{"type":36,"value":1980},"exposures",{"type":31,"tag":75,"props":1982,"children":1983},{"style":88},[1984],{"type":36,"value":121},{"type":31,"tag":75,"props":1986,"children":1987},{"class":77,"line":100},[1988,1992,1996,2000],{"type":31,"tag":75,"props":1989,"children":1990},{"style":88},[1991],{"type":36,"value":130},{"type":31,"tag":75,"props":1993,"children":1994},{"style":82},[1995],{"type":36,"value":135},{"type":31,"tag":75,"props":1997,"children":1998},{"style":88},[1999],{"type":36,"value":91},{"type":31,"tag":75,"props":2001,"children":2002},{"style":142},[2003],{"type":36,"value":2004},"marketing_dashboard\n",{"type":31,"tag":75,"props":2006,"children":2007},{"class":77,"line":110},[2008,2012,2016],{"type":31,"tag":75,"props":2009,"children":2010},{"style":82},[2011],{"type":36,"value":1839},{"type":31,"tag":75,"props":2013,"children":2014},{"style":88},[2015],{"type":36,"value":91},{"type":31,"tag":75,"props":2017,"children":2018},{"style":142},[2019],{"type":36,"value":2020},"dashboard\n",{"type":31,"tag":75,"props":2022,"children":2023},{"class":77,"line":124},[2024,2029,2033],{"type":31,"tag":75,"props":2025,"children":2026},{"style":82},[2027],{"type":36,"value":2028},"    maturity",{"type":31,"tag":75,"props":2030,"children":2031},{"style":88},[2032],{"type":36,"value":91},{"type":31,"tag":75,"props":2034,"children":2035},{"style":142},[2036],{"type":36,"value":2037},"high\n",{"type":31,"tag":75,"props":2039,"children":2040},{"class":77,"line":148},[2041,2046,2050],{"type":31,"tag":75,"props":2042,"children":2043},{"style":82},[2044],{"type":36,"value":2045},"    url",{"type":31,"tag":75,"props":2047,"children":2048},{"style":88},[2049],{"type":36,"value":91},{"type":31,"tag":75,"props":2051,"children":2052},{"style":142},[2053],{"type":36,"value":2054},"https:\u002F\u002Flookerstudio.google.com\u002Freporting\u002Fabc123\n",{"type":31,"tag":75,"props":2056,"children":2057},{"class":77,"line":166},[2058,2063,2067],{"type":31,"tag":75,"props":2059,"children":2060},{"style":82},[2061],{"type":36,"value":2062},"    description",{"type":31,"tag":75,"props":2064,"children":2065},{"style":88},[2066],{"type":36,"value":91},{"type":31,"tag":75,"props":2068,"children":2069},{"style":142},[2070],{"type":36,"value":2071},"\"Ежедневный дашборд перформанса каналов для CMO\"\n",{"type":31,"tag":75,"props":2073,"children":2074},{"class":77,"line":184},[2075,2080],{"type":31,"tag":75,"props":2076,"children":2077},{"style":82},[2078],{"type":36,"value":2079},"    depends_on",{"type":31,"tag":75,"props":2081,"children":2082},{"style":88},[2083],{"type":36,"value":121},{"type":31,"tag":75,"props":2085,"children":2086},{"class":77,"line":25},[2087,2091],{"type":31,"tag":75,"props":2088,"children":2089},{"style":88},[2090],{"type":36,"value":202},{"type":31,"tag":75,"props":2092,"children":2093},{"style":142},[2094],{"type":36,"value":1560},{"type":31,"tag":75,"props":2096,"children":2097},{"class":77,"line":218},[2098,2103],{"type":31,"tag":75,"props":2099,"children":2100},{"style":82},[2101],{"type":36,"value":2102},"    owner",{"type":31,"tag":75,"props":2104,"children":2105},{"style":88},[2106],{"type":36,"value":121},{"type":31,"tag":75,"props":2108,"children":2109},{"class":77,"line":231},[2110,2115,2119],{"type":31,"tag":75,"props":2111,"children":2112},{"style":82},[2113],{"type":36,"value":2114},"      name",{"type":31,"tag":75,"props":2116,"children":2117},{"style":88},[2118],{"type":36,"value":91},{"type":31,"tag":75,"props":2120,"children":2121},{"style":142},[2122],{"type":36,"value":2123},"Marketing Analytics Team\n",{"type":31,"tag":75,"props":2125,"children":2126},{"class":77,"line":283},[2127,2132,2136],{"type":31,"tag":75,"props":2128,"children":2129},{"style":82},[2130],{"type":36,"value":2131},"      email",{"type":31,"tag":75,"props":2133,"children":2134},{"style":88},[2135],{"type":36,"value":91},{"type":31,"tag":75,"props":2137,"children":2138},{"style":142},[2139],{"type":36,"value":2140},"analytics@company.com\n",{"type":31,"tag":32,"props":2142,"children":2143},{},[2144,2146,2151,2153,2158],{"type":36,"value":2145},"Определение exposure даёт два преимущества: ",{"type":31,"tag":475,"props":2147,"children":2148},{},[2149],{"type":36,"value":2150},"impact analysis",{"type":36,"value":2152}," (если я изменю эту модель, какие дашборды сломаются?) и ",{"type":31,"tag":475,"props":2154,"children":2155},{},[2156],{"type":36,"value":2157},"stakeholder mapping",{"type":36,"value":2159}," (кто владеет дашбордом, на кого эскалировать проблему?).",{"type":31,"tag":32,"props":2161,"children":2162},{},[2163],{"type":36,"value":2164},"В production exposures работают так: dbt build → тест падает → граф lineage показывает затронутые exposure'ы → автоматическое уведомление в Slack → владелец дашборда предупреждён рано. Вопрос \"почему дашборд пуст?\" поступит от системы CI\u002FCD, а не от пользователя.",{"type":31,"tag":32,"props":2166,"children":2167},{},[2168],{"type":36,"value":2169},"Без exposures data team deployит модель вслепую, не зная, кого затрагивает. С exposures каждая модель имеет метку \"эта таблица в production, трогать опасно\".",{"type":31,"tag":39,"props":2171,"children":2173},{"id":2172},"incremental-models-и-partitioning-стоимость-производительность",[2174],{"type":36,"value":2175},"Incremental Models и Partitioning: стоимость + производительность",{"type":31,"tag":32,"props":2177,"children":2178},{},[2179],{"type":36,"value":2180},"В BigQuery полное сканирование таблицы дорого. За 1 TB данных query стоит $5, 10 queries в день = $50, месяц = $1500. dbt incremental model обрабатывает только новые строки, исторические данные остаются неизменяемыми.",{"type":31,"tag":65,"props":2182,"children":2184},{"className":484,"code":2183,"language":486,"meta":15,"style":15},"{{ config(\n    materialized='incremental',\n    unique_key='event_id',\n    partition_by={'field': 'event_at', 'data_type': 'timestamp', 'granularity': 'day'},\n    cluster_by=['user_id', 'event_name']\n) }}\n\nSELECT * FROM {{ ref('stg_ga4__events') }}\nWHERE event_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 2 DAY)\n\n{% if is_incremental() %}\n    AND event_at > (SELECT MAX(event_at) FROM {{ this }})\n{% endif %}\n",[2185],{"type":31,"tag":51,"props":2186,"children":2187},{"__ignoreMap":15},[2188,2196,2218,2239,2311,2328,2335,2342,2369,2414,2421,2439,2481],{"type":31,"tag":75,"props":2189,"children":2190},{"class":77,"line":78},[2191],{"type":31,"tag":75,"props":2192,"children":2193},{"style":88},[2194],{"type":36,"value":2195},"{{ config(\n",{"type":31,"tag":75,"props":2197,"children":2198},{"class":77,"line":100},[2199,2204,2209,2214],{"type":31,"tag":75,"props":2200,"children":2201},{"style":88},[2202],{"type":36,"value":2203},"    materialized",{"type":31,"tag":75,"props":2205,"children":2206},{"style":505},[2207],{"type":36,"value":2208},"=",{"type":31,"tag":75,"props":2210,"children":2211},{"style":142},[2212],{"type":36,"value":2213},"'incremental'",{"type":31,"tag":75,"props":2215,"children":2216},{"style":88},[2217],{"type":36,"value":1272},{"type":31,"tag":75,"props":2219,"children":2220},{"class":77,"line":110},[2221,2226,2230,2235],{"type":31,"tag":75,"props":2222,"children":2223},{"style":88},[2224],{"type":36,"value":2225},"    unique_key",{"type":31,"tag":75,"props":2227,"children":2228},{"style":505},[2229],{"type":36,"value":2208},{"type":31,"tag":75,"props":2231,"children":2232},{"style":142},[2233],{"type":36,"value":2234},"'event_id'",{"type":31,"tag":75,"props":2236,"children":2237},{"style":88},[2238],{"type":36,"value":1272},{"type":31,"tag":75,"props":2240,"children":2241},{"class":77,"line":124},[2242,2247,2251,2256,2261,2265,2270,2274,2279,2283,2288,2292,2297,2301,2306],{"type":31,"tag":75,"props":2243,"children":2244},{"style":88},[2245],{"type":36,"value":2246},"    partition_by",{"type":31,"tag":75,"props":2248,"children":2249},{"style":505},[2250],{"type":36,"value":2208},{"type":31,"tag":75,"props":2252,"children":2253},{"style":88},[2254],{"type":36,"value":2255},"{",{"type":31,"tag":75,"props":2257,"children":2258},{"style":142},[2259],{"type":36,"value":2260},"'field'",{"type":31,"tag":75,"props":2262,"children":2263},{"style":88},[2264],{"type":36,"value":91},{"type":31,"tag":75,"props":2266,"children":2267},{"style":142},[2268],{"type":36,"value":2269},"'event_at'",{"type":31,"tag":75,"props":2271,"children":2272},{"style":88},[2273],{"type":36,"value":261},{"type":31,"tag":75,"props":2275,"children":2276},{"style":142},[2277],{"type":36,"value":2278},"'data_type'",{"type":31,"tag":75,"props":2280,"children":2281},{"style":88},[2282],{"type":36,"value":91},{"type":31,"tag":75,"props":2284,"children":2285},{"style":142},[2286],{"type":36,"value":2287},"'timestamp'",{"type":31,"tag":75,"props":2289,"children":2290},{"style":88},[2291],{"type":36,"value":261},{"type":31,"tag":75,"props":2293,"children":2294},{"style":142},[2295],{"type":36,"value":2296},"'granularity'",{"type":31,"tag":75,"props":2298,"children":2299},{"style":88},[2300],{"type":36,"value":91},{"type":31,"tag":75,"props":2302,"children":2303},{"style":142},[2304],{"type":36,"value":2305},"'day'",{"type":31,"tag":75,"props":2307,"children":2308},{"style":88},[2309],{"type":36,"value":2310},"},\n",{"type":31,"tag":75,"props":2312,"children":2313},{"class":77,"line":148},[2314,2319,2323],{"type":31,"tag":75,"props":2315,"children":2316},{"style":88},[2317],{"type":36,"value":2318},"    cluster_by",{"type":31,"tag":75,"props":2320,"children":2321},{"style":505},[2322],{"type":36,"value":2208},{"type":31,"tag":75,"props":2324,"children":2325},{"style":88},[2326],{"type":36,"value":2327},"['user_id', 'event_name']\n",{"type":31,"tag":75,"props":2329,"children":2330},{"class":77,"line":166},[2331],{"type":31,"tag":75,"props":2332,"children":2333},{"style":88},[2334],{"type":36,"value":565},{"type":31,"tag":75,"props":2336,"children":2337},{"class":77,"line":184},[2338],{"type":31,"tag":75,"props":2339,"children":2340},{"emptyLinePlaceholder":104},[2341],{"type":36,"value":107},{"type":31,"tag":75,"props":2343,"children":2344},{"class":77,"line":25},[2345,2349,2353,2357,2361,2365],{"type":31,"tag":75,"props":2346,"children":2347},{"style":505},[2348],{"type":36,"value":643},{"type":31,"tag":75,"props":2350,"children":2351},{"style":505},[2352],{"type":36,"value":536},{"type":31,"tag":75,"props":2354,"children":2355},{"style":505},[2356],{"type":36,"value":541},{"type":31,"tag":75,"props":2358,"children":2359},{"style":88},[2360],{"type":36,"value":811},{"type":31,"tag":75,"props":2362,"children":2363},{"style":142},[2364],{"type":36,"value":816},{"type":31,"tag":75,"props":2366,"children":2367},{"style":88},[2368],{"type":36,"value":565},{"type":31,"tag":75,"props":2370,"children":2371},{"class":77,"line":218},[2372,2376,2381,2385,2390,2395,2400,2405,2410],{"type":31,"tag":75,"props":2373,"children":2374},{"style":505},[2375],{"type":36,"value":672},{"type":31,"tag":75,"props":2377,"children":2378},{"style":88},[2379],{"type":36,"value":2380}," event_at ",{"type":31,"tag":75,"props":2382,"children":2383},{"style":505},[2384],{"type":36,"value":731},{"type":31,"tag":75,"props":2386,"children":2387},{"style":88},[2388],{"type":36,"value":2389}," TIMESTAMP_SUB(",{"type":31,"tag":75,"props":2391,"children":2392},{"style":94},[2393],{"type":36,"value":2394},"CURRENT_TIMESTAMP",{"type":31,"tag":75,"props":2396,"children":2397},{"style":88},[2398],{"type":36,"value":2399},"(), INTERVAL ",{"type":31,"tag":75,"props":2401,"children":2402},{"style":94},[2403],{"type":36,"value":2404},"2",{"type":31,"tag":75,"props":2406,"children":2407},{"style":505},[2408],{"type":36,"value":2409}," DAY",{"type":31,"tag":75,"props":2411,"children":2412},{"style":88},[2413],{"type":36,"value":573},{"type":31,"tag":75,"props":2415,"children":2416},{"class":77,"line":231},[2417],{"type":31,"tag":75,"props":2418,"children":2419},{"emptyLinePlaceholder":104},[2420],{"type":36,"value":107},{"type":31,"tag":75,"props":2422,"children":2423},{"class":77,"line":283},[2424,2429,2434],{"type":31,"tag":75,"props":2425,"children":2426},{"style":88},[2427],{"type":36,"value":2428},"{% ",{"type":31,"tag":75,"props":2430,"children":2431},{"style":505},[2432],{"type":36,"value":2433},"if",{"type":31,"tag":75,"props":2435,"children":2436},{"style":88},[2437],{"type":36,"value":2438}," is_incremental() %}\n",{"type":31,"tag":75,"props":2440,"children":2441},{"class":77,"line":329},[2442,2447,2451,2455,2459,2463,2468,2472,2476],{"type":31,"tag":75,"props":2443,"children":2444},{"style":505},[2445],{"type":36,"value":2446},"    AND",{"type":31,"tag":75,"props":2448,"children":2449},{"style":88},[2450],{"type":36,"value":2380},{"type":31,"tag":75,"props":2452,"children":2453},{"style":505},[2454],{"type":36,"value":962},{"type":31,"tag":75,"props":2456,"children":2457},{"style":88},[2458],{"type":36,"value":923},{"type":31,"tag":75,"props":2460,"children":2461},{"style":505},[2462],{"type":36,"value":643},{"type":31,"tag":75,"props":2464,"children":2465},{"style":94},[2466],{"type":36,"value":2467}," MAX",{"type":31,"tag":75,"props":2469,"children":2470},{"style":88},[2471],{"type":36,"value":913},{"type":31,"tag":75,"props":2473,"children":2474},{"style":505},[2475],{"type":36,"value":709},{"type":31,"tag":75,"props":2477,"children":2478},{"style":88},[2479],{"type":36,"value":2480}," {{ this }})\n",{"type":31,"tag":75,"props":2482,"children":2483},{"class":77,"line":342},[2484],{"type":31,"tag":75,"props":2485,"children":2486},{"style":88},[2487],{"type":36,"value":2488},"{% endif %}\n",{"type":31,"tag":32,"props":2490,"children":2491},{},[2492,2494,2500,2502,2508],{"type":36,"value":2493},"Эта конфигурация делает следующее: в каждом run обрабатываются только последние 2 дня, старые данные не трогаются. ",{"type":31,"tag":51,"props":2495,"children":2497},{"className":2496},[],[2498],{"type":36,"value":2499},"partition_by",{"type":36,"value":2501}," включает partition pruning в BigQuery, ",{"type":31,"tag":51,"props":2503,"children":2505},{"className":2504},[],[2506],{"type":36,"value":2507},"cluster_by",{"type":36,"value":2509}," улучшает selectivity query. На том же наборе данных вы снижаете стоимость на 90%.",{"type":31,"tag":32,"props":2511,"children":2512},{},[2513],{"type":36,"value":2514},"В production incremental model + dbt snapshot реализуют SCD Type 2: вы отслеживаете исторические изменения в dimension-таблицах (изменение сегмента пользователя, переклассификация категории продукта). Когда аналитик спрашивает \"в какой сегмент пользователь X входил в прошлом месяце?\", вы берёте данные из snapshot, и они совпадают.",{"type":31,"tag":39,"props":2516,"children":2518},{"id":2517},"production-pipeline-cicd-tests-alerts",[2519],{"type":36,"value":2520},"Production Pipeline: CI\u002FCD, Tests, Alerts",{"type":31,"tag":32,"props":2522,"children":2523},{},[2524],{"type":36,"value":2525},"dbt-проект хранится в GitHub, каждый commit запускает CI pipeline:",{"type":31,"tag":2527,"props":2528,"children":2529},"ol",{},[2530,2549,2566,2583],{"type":31,"tag":2531,"props":2532,"children":2533},"li",{},[2534,2539,2541,2547],{"type":31,"tag":475,"props":2535,"children":2536},{},[2537],{"type":36,"value":2538},"Lint:",{"type":36,"value":2540}," ",{"type":31,"tag":51,"props":2542,"children":2544},{"className":2543},[],[2545],{"type":36,"value":2546},"sqlfluff",{"type":36,"value":2548}," проверяет формат SQL",{"type":31,"tag":2531,"props":2550,"children":2551},{},[2552,2557,2558,2564],{"type":31,"tag":475,"props":2553,"children":2554},{},[2555],{"type":36,"value":2556},"Test:",{"type":36,"value":2540},{"type":31,"tag":51,"props":2559,"children":2561},{"className":2560},[],[2562],{"type":36,"value":2563},"dbt test",{"type":36,"value":2565}," запускает schema-тесты (not_null, unique, foreign_key) и data-тесты (revenue > 0, session_duration \u003C 24h)",{"type":31,"tag":2531,"props":2567,"children":2568},{},[2569,2574,2575,2581],{"type":31,"tag":475,"props":2570,"children":2571},{},[2572],{"type":36,"value":2573},"Build:",{"type":36,"value":2540},{"type":31,"tag":51,"props":2576,"children":2578},{"className":2577},[],[2579],{"type":36,"value":2580},"dbt build --select state:modified+",{"type":36,"value":2582}," перестраивает только изменённые модели",{"type":31,"tag":2531,"props":2584,"children":2585},{},[2586,2591],{"type":31,"tag":475,"props":2587,"children":2588},{},[2589],{"type":36,"value":2590},"Deploy:",{"type":36,"value":2592}," при merge в production обновляются таблицы в BigQuery",{"type":31,"tag":32,"props":2594,"children":2595},{},[2596],{"type":36,"value":2597},"Если тест падает, merge блокируется. Пример data-теста:",{"type":31,"tag":65,"props":2599,"children":2601},{"className":484,"code":2600,"language":486,"meta":15,"style":15},"-- tests\u002Fassert_no_negative_revenue.sql\nSELECT * FROM {{ ref('fct_daily_channel_performance') }}\nWHERE revenue \u003C 0\n",[2602],{"type":31,"tag":51,"props":2603,"children":2604},{"__ignoreMap":15},[2605,2613,2641],{"type":31,"tag":75,"props":2606,"children":2607},{"class":77,"line":78},[2608],{"type":31,"tag":75,"props":2609,"children":2610},{"style":496},[2611],{"type":36,"value":2612},"-- tests\u002Fassert_no_negative_revenue.sql\n",{"type":31,"tag":75,"props":2614,"children":2615},{"class":77,"line":100},[2616,2620,2624,2628,2632,2637],{"type":31,"tag":75,"props":2617,"children":2618},{"style":505},[2619],{"type":36,"value":643},{"type":31,"tag":75,"props":2621,"children":2622},{"style":505},[2623],{"type":36,"value":536},{"type":31,"tag":75,"props":2625,"children":2626},{"style":505},[2627],{"type":36,"value":541},{"type":31,"tag":75,"props":2629,"children":2630},{"style":88},[2631],{"type":36,"value":811},{"type":31,"tag":75,"props":2633,"children":2634},{"style":142},[2635],{"type":36,"value":2636},"'fct_daily_channel_performance'",{"type":31,"tag":75,"props":2638,"children":2639},{"style":88},[2640],{"type":36,"value":565},{"type":31,"tag":75,"props":2642,"children":2643},{"class":77,"line":110},[2644,2648,2653,2658],{"type":31,"tag":75,"props":2645,"children":2646},{"style":505},[2647],{"type":36,"value":672},{"type":31,"tag":75,"props":2649,"children":2650},{"style":88},[2651],{"type":36,"value":2652}," revenue ",{"type":31,"tag":75,"props":2654,"children":2655},{"style":505},[2656],{"type":36,"value":2657},"\u003C",{"type":31,"tag":75,"props":2659,"children":2660},{"style":94},[2661],{"type":36,"value":2662}," 0\n",{"type":31,"tag":32,"props":2664,"children":2665},{},[2666],{"type":36,"value":2667},"Если тест вернёт 0 строк — он пройден. Если вернёт хотя бы одну строку — падает. В production отрицательный доход считается аномалией, pipeline останавливается.",{"type":31,"tag":32,"props":2669,"children":2670},{},[2671,2673,2679],{"type":36,"value":2672},"Сценарий с алертами: в dbt Cloud вы schedule'ите job (каждый день 06:00), hook ",{"type":31,"tag":51,"props":2674,"children":2676},{"className":2675},[],[2677],{"type":36,"value":2678},"on-run-end",{"type":36,"value":2680}," отправляет уведомление в Slack:",{"type":31,"tag":65,"props":2682,"children":2684},{"className":67,"code":2683,"language":69,"meta":15,"style":15},"on-run-end:\n  - \"{{ post_to_slack_on_failure() }}\"\n",[2685],{"type":31,"tag":51,"props":2686,"children":2687},{"__ignoreMap":15},[2688,2699],{"type":31,"tag":75,"props":2689,"children":2690},{"class":77,"line":78},[2691,2695],{"type":31,"tag":75,"props":2692,"children":2693},{"style":82},[2694],{"type":36,"value":2678},{"type":31,"tag":75,"props":2696,"children":2697},{"style":88},[2698],{"type":36,"value":121},{"type":31,"tag":75,"props":2700,"children":2701},{"class":77,"line":100},[2702,2706],{"type":31,"tag":75,"props":2703,"children":2704},{"style":88},[2705],{"type":36,"value":130},{"type":31,"tag":75,"props":2707,"children":2708},{"style":142},[2709],{"type":36,"value":2710},"\"{{ post_to_slack_on_failure() }}\"\n",{"type":31,"tag":32,"props":2712,"children":2713},{},[2714,2716,2723],{"type":36,"value":2715},"Внедрение этого pipeline с ",{"type":31,"tag":1937,"props":2717,"children":2720},{"href":2718,"rel":2719},"https:\u002F\u002Fwww.roibase.com.tr\u002Fru\u002Fverianalizi",[1941],[2721],{"type":36,"value":2722},"Инженерией сохранения и аналитикой данных",{"type":36,"value":2724}," занимает 4–6 недель: source mapping + staging layer + intermediate layer + mart + semantic model + exposure + тесты + CI\u002FCD.",{"type":31,"tag":39,"props":2726,"children":2728},{"id":2727},"компромиссы-сложность-против-контроля",[2729],{"type":36,"value":2730},"Компромиссы: сложность против контроля",{"type":31,"tag":32,"props":2732,"children":2733},{},[2734],{"type":36,"value":2735},"Stack dbt + BigQuery имеет крутую кривую обучения. Знания SQL недостаточно — нужны Jinja-шаблоны, YAML-конфигурация, Git-workflow, CI\u002FCD. Для маленьких команд (1–2 человека) этот overhead может быть избыточным — быстрее начать с прямых view'ов в BigQuery + Looker Studio.",{"type":31,"tag":32,"props":2737,"children":2738},{},[2739],{"type":36,"value":2740},"Но когда масштаб растёт (10+ дашбордов, 50+ источников, 5+ аналитиков), без dbt теряется контроль. Каждый аналитик пишет свой SQL, определения метрик конфликтуют, нет тестов, нет документации. dbt в этот момент предотвращает накопление технического долга вместо его погашения.",{"type":31,"tag":32,"props":2742,"children":2743},{},[2744],{"type":36,"value":2745},"Альтернативный подход: LookML в Looker для semantic layer. LookML похож на dbt (определение метрик через код), но есть vendor lock-in, интеграция с non-BigQuery источниками сложнее. dbt — open source, переносим, работает с BigQuery\u002FSnowflake\u002FRedshift.",{"type":31,"tag":32,"props":2747,"children":2748},{},[2749],{"type":36,"value":2750},"Современный маркетинг-стек данных начинается с source mapping, масштабируется semantic layer, мониторится через exposure'ы. dbt + BigQuery кодируют эти три слоя, делая их тестируемыми, версионируемыми, воспроизводимыми. Вы гарантируете согласованность метрик без необходимости смотреть на дашборд.",{"type":31,"tag":2752,"props":2753,"children":2754},"style",{},[2755],{"type":36,"value":2756},"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":15,"searchDepth":110,"depth":110,"links":2758},[2759,2760,2761,2762,2763,2764,2765],{"id":41,"depth":100,"text":44},{"id":462,"depth":100,"text":465},{"id":1483,"depth":100,"text":1486},{"id":1949,"depth":100,"text":1952},{"id":2172,"depth":100,"text":2175},{"id":2517,"depth":100,"text":2520},{"id":2727,"depth":100,"text":2730},"markdown","content:ru:data:dbt-bigquery-pazarlama-data-stack.md","content","ru\u002Fdata\u002Fdbt-bigquery-pazarlama-data-stack.md","ru\u002Fdata\u002Fdbt-bigquery-pazarlama-data-stack","md",1782050767427]