[{"data":1,"prerenderedAt":3486},["ShallowReactive",2],{"article-alternates":3,"article-\u002Fru\u002Fdata\u002Fdbt-bigquery-modern-marketing-data-stack":13},{"i18nKey":4,"paths":5},"data-002-2026-07",{"de":6,"en":7,"es":8,"fr":9,"it":10,"ru":11,"tr":12},"\u002Fde\u002Fdata\u002Fdbt-bigquery-moderner-marketing-data-stack","\u002Fen\u002Fdata\u002Fdbt-bigquery-modern-marketing-data-stack","\u002Fes\u002Fdata\u002Fdbt-bigquery-modern-pila-datos-marketing","\u002Ffr\u002Fdata\u002Fdbt-bigquery-stack-marketing-data-moderne","\u002Fit\u002Fdata\u002Fdbt-bigquery-modern-stack-marketing-data","\u002Fru\u002Fdata\u002Fdbt-bigquery-modern-marketing-data-stack","\u002Ftr\u002Fdata\u002Fdbt-bigquery-ile-modern-pazarlama-data-stack",{"_path":11,"_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":3480,"_id":3481,"_source":3482,"_file":3483,"_stem":3484,"_extension":3485},"data",false,"","dbt + BigQuery для современного маркетингового хранилища данных","Source mapping, modeling layer, semantic layer, exposures: четырёхслойная архитектура, связывающая маркетинговые данные с механизмом принятия решений.","2026-07-17",[21,22,23,24,25],"dbt","bigquery","data-modeling","semantic-layer","marketing-analytics",9,"Roibase",{"type":29,"children":30,"toc":3472},"root",[31,39,46,90,565,594,615,621,656,1129,1150,1177,1636,1664,1728,1734,1763,2140,2169,2216,2222,2227,2612,2632,2661,2667,2679,3166,3187,3200,3400,3405,3411,3432,3445,3457,3461,3466],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36],{"type":37,"value":38},"text","Отчёт Google Analytics 4 показывает производительность по каналам, Klaviyo регистрирует отправленные письма, панель Meta Ads выводит CPA — но могут ли эти три показателя находиться рядом в одном SQL-запросе? Если нет, механизм принятия решений опирается на предположения. Обещание stack'а dbt + BigQuery просто: смоделировать маркетинговые данные через четыре слоя — от источника к exposure'ам — превратив вопрос \"какой канал, какому клиенту, какую ценность создал\" в повторяемый SQL pipeline. По мере того как world post-cookie, multi-touch attribution и incrementality становятся обязательными, эта архитектура для boutique-агентства уже не опция, а необходимость.",{"type":32,"tag":40,"props":41,"children":43},"h2",{"id":42},"source-mapping-разбиение-сырых-кластеров-данных-на-группы-таблиц",[44],{"type":37,"value":45},"Source mapping: разбиение сырых кластеров данных на группы таблиц",{"type":32,"tag":33,"props":47,"children":48},{},[49,51,58,60,66,67,73,74,80,82,88],{"type":37,"value":50},"В BigQuery каждая платформа создаёт собственный dataset: ",{"type":32,"tag":52,"props":53,"children":55},"code",{"className":54},[],[56],{"type":37,"value":57},"ga4_export",{"type":37,"value":59},", ",{"type":32,"tag":52,"props":61,"children":63},{"className":62},[],[64],{"type":37,"value":65},"facebook_ads",{"type":37,"value":59},{"type":32,"tag":52,"props":68,"children":70},{"className":69},[],[71],{"type":37,"value":72},"klaviyo_events",{"type":37,"value":59},{"type":32,"tag":52,"props":75,"children":77},{"className":76},[],[78],{"type":37,"value":79},"shopify_orders",{"type":37,"value":81},". Их сырые схемы несовместимы — GA4 возвращает вложенный JSON, Facebook API плоский CSV, Klaviyo webhook вообще без нормализации. dbt source mapping — первый слой: написать YAML manifest поверх этого хаоса, зарегистрировать каждую таблицу в блоке ",{"type":32,"tag":52,"props":83,"children":85},{"className":84},[],[86],{"type":37,"value":87},"sources",{"type":37,"value":89},", объявить типы данных, свежесть и частоту загрузки.",{"type":32,"tag":91,"props":92,"children":96},"pre",{"className":93,"code":94,"language":95,"meta":16,"style":16},"language-yaml shiki shiki-themes github-dark","# models\u002Fsources\u002Fmarketing_sources.yml\nversion: 2\n\nsources:\n  - name: ga4_export\n    database: roibase-analytics\n    schema: analytics_123456789\n    tables:\n      - name: events_*\n        identifier: 'events_*'\n        meta:\n          contains_pii: true\n        freshness:\n          warn_after: {count: 25, period: hour}\n          error_after: {count: 49, period: hour}\n\n  - name: facebook_ads\n    schema: facebook_raw\n    tables:\n      - name: ads_insights\n        loaded_at_field: date_start\n        freshness:\n          warn_after: {count: 2, period: day}\n","yaml",[97],{"type":32,"tag":52,"props":98,"children":99},{"__ignoreMap":16},[100,112,134,144,157,181,199,217,230,251,269,282,300,313,364,410,418,439,456,468,489,507,519],{"type":32,"tag":101,"props":102,"children":105},"span",{"class":103,"line":104},"line",1,[106],{"type":32,"tag":101,"props":107,"children":109},{"style":108},"--shiki-default:#6A737D",[110],{"type":37,"value":111},"# models\u002Fsources\u002Fmarketing_sources.yml\n",{"type":32,"tag":101,"props":113,"children":115},{"class":103,"line":114},2,[116,122,128],{"type":32,"tag":101,"props":117,"children":119},{"style":118},"--shiki-default:#85E89D",[120],{"type":37,"value":121},"version",{"type":32,"tag":101,"props":123,"children":125},{"style":124},"--shiki-default:#E1E4E8",[126],{"type":37,"value":127},": ",{"type":32,"tag":101,"props":129,"children":131},{"style":130},"--shiki-default:#79B8FF",[132],{"type":37,"value":133},"2\n",{"type":32,"tag":101,"props":135,"children":137},{"class":103,"line":136},3,[138],{"type":32,"tag":101,"props":139,"children":141},{"emptyLinePlaceholder":140},true,[142],{"type":37,"value":143},"\n",{"type":32,"tag":101,"props":145,"children":147},{"class":103,"line":146},4,[148,152],{"type":32,"tag":101,"props":149,"children":150},{"style":118},[151],{"type":37,"value":87},{"type":32,"tag":101,"props":153,"children":154},{"style":124},[155],{"type":37,"value":156},":\n",{"type":32,"tag":101,"props":158,"children":160},{"class":103,"line":159},5,[161,166,171,175],{"type":32,"tag":101,"props":162,"children":163},{"style":124},[164],{"type":37,"value":165},"  - ",{"type":32,"tag":101,"props":167,"children":168},{"style":118},[169],{"type":37,"value":170},"name",{"type":32,"tag":101,"props":172,"children":173},{"style":124},[174],{"type":37,"value":127},{"type":32,"tag":101,"props":176,"children":178},{"style":177},"--shiki-default:#9ECBFF",[179],{"type":37,"value":180},"ga4_export\n",{"type":32,"tag":101,"props":182,"children":184},{"class":103,"line":183},6,[185,190,194],{"type":32,"tag":101,"props":186,"children":187},{"style":118},[188],{"type":37,"value":189},"    database",{"type":32,"tag":101,"props":191,"children":192},{"style":124},[193],{"type":37,"value":127},{"type":32,"tag":101,"props":195,"children":196},{"style":177},[197],{"type":37,"value":198},"roibase-analytics\n",{"type":32,"tag":101,"props":200,"children":202},{"class":103,"line":201},7,[203,208,212],{"type":32,"tag":101,"props":204,"children":205},{"style":118},[206],{"type":37,"value":207},"    schema",{"type":32,"tag":101,"props":209,"children":210},{"style":124},[211],{"type":37,"value":127},{"type":32,"tag":101,"props":213,"children":214},{"style":177},[215],{"type":37,"value":216},"analytics_123456789\n",{"type":32,"tag":101,"props":218,"children":220},{"class":103,"line":219},8,[221,226],{"type":32,"tag":101,"props":222,"children":223},{"style":118},[224],{"type":37,"value":225},"    tables",{"type":32,"tag":101,"props":227,"children":228},{"style":124},[229],{"type":37,"value":156},{"type":32,"tag":101,"props":231,"children":232},{"class":103,"line":26},[233,238,242,246],{"type":32,"tag":101,"props":234,"children":235},{"style":124},[236],{"type":37,"value":237},"      - ",{"type":32,"tag":101,"props":239,"children":240},{"style":118},[241],{"type":37,"value":170},{"type":32,"tag":101,"props":243,"children":244},{"style":124},[245],{"type":37,"value":127},{"type":32,"tag":101,"props":247,"children":248},{"style":177},[249],{"type":37,"value":250},"events_*\n",{"type":32,"tag":101,"props":252,"children":254},{"class":103,"line":253},10,[255,260,264],{"type":32,"tag":101,"props":256,"children":257},{"style":118},[258],{"type":37,"value":259},"        identifier",{"type":32,"tag":101,"props":261,"children":262},{"style":124},[263],{"type":37,"value":127},{"type":32,"tag":101,"props":265,"children":266},{"style":177},[267],{"type":37,"value":268},"'events_*'\n",{"type":32,"tag":101,"props":270,"children":272},{"class":103,"line":271},11,[273,278],{"type":32,"tag":101,"props":274,"children":275},{"style":118},[276],{"type":37,"value":277},"        meta",{"type":32,"tag":101,"props":279,"children":280},{"style":124},[281],{"type":37,"value":156},{"type":32,"tag":101,"props":283,"children":285},{"class":103,"line":284},12,[286,291,295],{"type":32,"tag":101,"props":287,"children":288},{"style":118},[289],{"type":37,"value":290},"          contains_pii",{"type":32,"tag":101,"props":292,"children":293},{"style":124},[294],{"type":37,"value":127},{"type":32,"tag":101,"props":296,"children":297},{"style":130},[298],{"type":37,"value":299},"true\n",{"type":32,"tag":101,"props":301,"children":303},{"class":103,"line":302},13,[304,309],{"type":32,"tag":101,"props":305,"children":306},{"style":118},[307],{"type":37,"value":308},"        freshness",{"type":32,"tag":101,"props":310,"children":311},{"style":124},[312],{"type":37,"value":156},{"type":32,"tag":101,"props":314,"children":316},{"class":103,"line":315},14,[317,322,327,332,336,341,345,350,354,359],{"type":32,"tag":101,"props":318,"children":319},{"style":118},[320],{"type":37,"value":321},"          warn_after",{"type":32,"tag":101,"props":323,"children":324},{"style":124},[325],{"type":37,"value":326},": {",{"type":32,"tag":101,"props":328,"children":329},{"style":118},[330],{"type":37,"value":331},"count",{"type":32,"tag":101,"props":333,"children":334},{"style":124},[335],{"type":37,"value":127},{"type":32,"tag":101,"props":337,"children":338},{"style":130},[339],{"type":37,"value":340},"25",{"type":32,"tag":101,"props":342,"children":343},{"style":124},[344],{"type":37,"value":59},{"type":32,"tag":101,"props":346,"children":347},{"style":118},[348],{"type":37,"value":349},"period",{"type":32,"tag":101,"props":351,"children":352},{"style":124},[353],{"type":37,"value":127},{"type":32,"tag":101,"props":355,"children":356},{"style":177},[357],{"type":37,"value":358},"hour",{"type":32,"tag":101,"props":360,"children":361},{"style":124},[362],{"type":37,"value":363},"}\n",{"type":32,"tag":101,"props":365,"children":367},{"class":103,"line":366},15,[368,373,377,381,385,390,394,398,402,406],{"type":32,"tag":101,"props":369,"children":370},{"style":118},[371],{"type":37,"value":372},"          error_after",{"type":32,"tag":101,"props":374,"children":375},{"style":124},[376],{"type":37,"value":326},{"type":32,"tag":101,"props":378,"children":379},{"style":118},[380],{"type":37,"value":331},{"type":32,"tag":101,"props":382,"children":383},{"style":124},[384],{"type":37,"value":127},{"type":32,"tag":101,"props":386,"children":387},{"style":130},[388],{"type":37,"value":389},"49",{"type":32,"tag":101,"props":391,"children":392},{"style":124},[393],{"type":37,"value":59},{"type":32,"tag":101,"props":395,"children":396},{"style":118},[397],{"type":37,"value":349},{"type":32,"tag":101,"props":399,"children":400},{"style":124},[401],{"type":37,"value":127},{"type":32,"tag":101,"props":403,"children":404},{"style":177},[405],{"type":37,"value":358},{"type":32,"tag":101,"props":407,"children":408},{"style":124},[409],{"type":37,"value":363},{"type":32,"tag":101,"props":411,"children":413},{"class":103,"line":412},16,[414],{"type":32,"tag":101,"props":415,"children":416},{"emptyLinePlaceholder":140},[417],{"type":37,"value":143},{"type":32,"tag":101,"props":419,"children":421},{"class":103,"line":420},17,[422,426,430,434],{"type":32,"tag":101,"props":423,"children":424},{"style":124},[425],{"type":37,"value":165},{"type":32,"tag":101,"props":427,"children":428},{"style":118},[429],{"type":37,"value":170},{"type":32,"tag":101,"props":431,"children":432},{"style":124},[433],{"type":37,"value":127},{"type":32,"tag":101,"props":435,"children":436},{"style":177},[437],{"type":37,"value":438},"facebook_ads\n",{"type":32,"tag":101,"props":440,"children":442},{"class":103,"line":441},18,[443,447,451],{"type":32,"tag":101,"props":444,"children":445},{"style":118},[446],{"type":37,"value":207},{"type":32,"tag":101,"props":448,"children":449},{"style":124},[450],{"type":37,"value":127},{"type":32,"tag":101,"props":452,"children":453},{"style":177},[454],{"type":37,"value":455},"facebook_raw\n",{"type":32,"tag":101,"props":457,"children":459},{"class":103,"line":458},19,[460,464],{"type":32,"tag":101,"props":461,"children":462},{"style":118},[463],{"type":37,"value":225},{"type":32,"tag":101,"props":465,"children":466},{"style":124},[467],{"type":37,"value":156},{"type":32,"tag":101,"props":469,"children":471},{"class":103,"line":470},20,[472,476,480,484],{"type":32,"tag":101,"props":473,"children":474},{"style":124},[475],{"type":37,"value":237},{"type":32,"tag":101,"props":477,"children":478},{"style":118},[479],{"type":37,"value":170},{"type":32,"tag":101,"props":481,"children":482},{"style":124},[483],{"type":37,"value":127},{"type":32,"tag":101,"props":485,"children":486},{"style":177},[487],{"type":37,"value":488},"ads_insights\n",{"type":32,"tag":101,"props":490,"children":492},{"class":103,"line":491},21,[493,498,502],{"type":32,"tag":101,"props":494,"children":495},{"style":118},[496],{"type":37,"value":497},"        loaded_at_field",{"type":32,"tag":101,"props":499,"children":500},{"style":124},[501],{"type":37,"value":127},{"type":32,"tag":101,"props":503,"children":504},{"style":177},[505],{"type":37,"value":506},"date_start\n",{"type":32,"tag":101,"props":508,"children":510},{"class":103,"line":509},22,[511,515],{"type":32,"tag":101,"props":512,"children":513},{"style":118},[514],{"type":37,"value":308},{"type":32,"tag":101,"props":516,"children":517},{"style":124},[518],{"type":37,"value":156},{"type":32,"tag":101,"props":520,"children":522},{"class":103,"line":521},23,[523,527,531,535,539,544,548,552,556,561],{"type":32,"tag":101,"props":524,"children":525},{"style":118},[526],{"type":37,"value":321},{"type":32,"tag":101,"props":528,"children":529},{"style":124},[530],{"type":37,"value":326},{"type":32,"tag":101,"props":532,"children":533},{"style":118},[534],{"type":37,"value":331},{"type":32,"tag":101,"props":536,"children":537},{"style":124},[538],{"type":37,"value":127},{"type":32,"tag":101,"props":540,"children":541},{"style":130},[542],{"type":37,"value":543},"2",{"type":32,"tag":101,"props":545,"children":546},{"style":124},[547],{"type":37,"value":59},{"type":32,"tag":101,"props":549,"children":550},{"style":118},[551],{"type":37,"value":349},{"type":32,"tag":101,"props":553,"children":554},{"style":124},[555],{"type":37,"value":127},{"type":32,"tag":101,"props":557,"children":558},{"style":177},[559],{"type":37,"value":560},"day",{"type":32,"tag":101,"props":562,"children":563},{"style":124},[564],{"type":37,"value":363},{"type":32,"tag":33,"props":566,"children":567},{},[568,570,576,578,584,586,592],{"type":37,"value":569},"Этот manifest даёт dbt две вещи: 1) type-safe ссылку на сырую таблицу через macro ",{"type":32,"tag":52,"props":571,"children":573},{"className":572},[],[574],{"type":37,"value":575},"source()",{"type":37,"value":577}," вместо ",{"type":32,"tag":52,"props":579,"children":581},{"className":580},[],[582],{"type":37,"value":583},"ref()",{"type":37,"value":585},", 2) команда ",{"type":32,"tag":52,"props":587,"children":589},{"className":588},[],[590],{"type":37,"value":591},"dbt source freshness",{"type":37,"value":593}," для определения точки отказа pipeline'а. Если GA4 event не обновлялся 49 часов — BigQuery ошибку не выдаст, но dbt выдаст.",{"type":32,"tag":33,"props":595,"children":596},{},[597,599,605,607,613],{"type":37,"value":598},"Во время source mapping обязательна PII-аннотация: в рамках GDPR и локальных регуляций должна быть отмечена информация о том, где находятся ID пользователя, email, IP. Каждая таблица с ",{"type":32,"tag":52,"props":600,"children":602},{"className":601},[],[603],{"type":37,"value":604},"user_pseudo_id",{"type":37,"value":606}," получает ",{"type":32,"tag":52,"props":608,"children":610},{"className":609},[],[611],{"type":37,"value":612},"meta.contains_pii: true",{"type":37,"value":614},". Этот тег переносится в downstream lineage и связывается с field-level маскированием в semantic layer.",{"type":32,"tag":40,"props":616,"children":618},{"id":617},"modeling-layer-три-этапа-staging-intermediate-mart",[619],{"type":37,"value":620},"Modeling layer: три этапа staging → intermediate → mart",{"type":32,"tag":33,"props":622,"children":623},{},[624,626,632,634,640,641,647,648,654],{"type":37,"value":625},"Staging models переименовывают сырой source, выполняют type casting, удаляют лишние столбцы, предоставляя downstream стандартную схему. Распаковка ",{"type":32,"tag":52,"props":627,"children":629},{"className":628},[],[630],{"type":37,"value":631},"event_params",{"type":37,"value":633}," array'я из GA4 и преобразование в скалярные поля (",{"type":32,"tag":52,"props":635,"children":637},{"className":636},[],[638],{"type":37,"value":639},"page_location",{"type":37,"value":59},{"type":32,"tag":52,"props":642,"children":644},{"className":643},[],[645],{"type":37,"value":646},"session_id",{"type":37,"value":59},{"type":32,"tag":52,"props":649,"children":651},{"className":650},[],[652],{"type":37,"value":653},"transaction_id",{"type":37,"value":655},") — это работа staging:",{"type":32,"tag":91,"props":657,"children":661},{"className":658,"code":659,"language":660,"meta":16,"style":16},"language-sql shiki shiki-themes github-dark","-- models\u002Fstaging\u002Fga4\u002Fstg_ga4__events.sql\nwith source as (\n    select * from {{ source('ga4_export', 'events_*') }}\n    where _table_suffix between format_date('%Y%m%d', date_sub(current_date(), interval 90 day))\n                             and format_date('%Y%m%d', current_date())\n),\n\nunnested as (\n    select\n        event_date,\n        event_timestamp,\n        user_pseudo_id,\n        (select value.string_value from unnest(event_params) where key = 'page_location') as page_location,\n        (select value.int_value from unnest(event_params) where key = 'ga_session_id') as session_id,\n        ecommerce.transaction_id,\n        ecommerce.purchase_revenue_in_usd\n    from source\n    where event_name in ('page_view', 'purchase')\n)\n\nselect * from unnested\n","sql",[662],{"type":32,"tag":52,"props":663,"children":664},{"__ignoreMap":16},[665,673,697,739,787,808,816,823,839,847,855,863,871,942,1004,1025,1041,1054,1095,1102,1109],{"type":32,"tag":101,"props":666,"children":667},{"class":103,"line":104},[668],{"type":32,"tag":101,"props":669,"children":670},{"style":108},[671],{"type":37,"value":672},"-- models\u002Fstaging\u002Fga4\u002Fstg_ga4__events.sql\n",{"type":32,"tag":101,"props":674,"children":675},{"class":103,"line":114},[676,682,687,692],{"type":32,"tag":101,"props":677,"children":679},{"style":678},"--shiki-default:#F97583",[680],{"type":37,"value":681},"with",{"type":32,"tag":101,"props":683,"children":684},{"style":124},[685],{"type":37,"value":686}," source ",{"type":32,"tag":101,"props":688,"children":689},{"style":678},[690],{"type":37,"value":691},"as",{"type":32,"tag":101,"props":693,"children":694},{"style":124},[695],{"type":37,"value":696}," (\n",{"type":32,"tag":101,"props":698,"children":699},{"class":103,"line":136},[700,705,710,715,720,725,729,734],{"type":32,"tag":101,"props":701,"children":702},{"style":678},[703],{"type":37,"value":704},"    select",{"type":32,"tag":101,"props":706,"children":707},{"style":678},[708],{"type":37,"value":709}," *",{"type":32,"tag":101,"props":711,"children":712},{"style":678},[713],{"type":37,"value":714}," from",{"type":32,"tag":101,"props":716,"children":717},{"style":124},[718],{"type":37,"value":719}," {{ source(",{"type":32,"tag":101,"props":721,"children":722},{"style":177},[723],{"type":37,"value":724},"'ga4_export'",{"type":32,"tag":101,"props":726,"children":727},{"style":124},[728],{"type":37,"value":59},{"type":32,"tag":101,"props":730,"children":731},{"style":177},[732],{"type":37,"value":733},"'events_*'",{"type":32,"tag":101,"props":735,"children":736},{"style":124},[737],{"type":37,"value":738},") }}\n",{"type":32,"tag":101,"props":740,"children":741},{"class":103,"line":146},[742,747,752,757,762,767,772,777,782],{"type":32,"tag":101,"props":743,"children":744},{"style":678},[745],{"type":37,"value":746},"    where",{"type":32,"tag":101,"props":748,"children":749},{"style":124},[750],{"type":37,"value":751}," _table_suffix ",{"type":32,"tag":101,"props":753,"children":754},{"style":678},[755],{"type":37,"value":756},"between",{"type":32,"tag":101,"props":758,"children":759},{"style":124},[760],{"type":37,"value":761}," format_date(",{"type":32,"tag":101,"props":763,"children":764},{"style":177},[765],{"type":37,"value":766},"'%Y%m%d'",{"type":32,"tag":101,"props":768,"children":769},{"style":124},[770],{"type":37,"value":771},", date_sub(current_date(), interval ",{"type":32,"tag":101,"props":773,"children":774},{"style":130},[775],{"type":37,"value":776},"90",{"type":32,"tag":101,"props":778,"children":779},{"style":678},[780],{"type":37,"value":781}," day",{"type":32,"tag":101,"props":783,"children":784},{"style":124},[785],{"type":37,"value":786},"))\n",{"type":32,"tag":101,"props":788,"children":789},{"class":103,"line":159},[790,795,799,803],{"type":32,"tag":101,"props":791,"children":792},{"style":678},[793],{"type":37,"value":794},"                             and",{"type":32,"tag":101,"props":796,"children":797},{"style":124},[798],{"type":37,"value":761},{"type":32,"tag":101,"props":800,"children":801},{"style":177},[802],{"type":37,"value":766},{"type":32,"tag":101,"props":804,"children":805},{"style":124},[806],{"type":37,"value":807},", current_date())\n",{"type":32,"tag":101,"props":809,"children":810},{"class":103,"line":183},[811],{"type":32,"tag":101,"props":812,"children":813},{"style":124},[814],{"type":37,"value":815},"),\n",{"type":32,"tag":101,"props":817,"children":818},{"class":103,"line":201},[819],{"type":32,"tag":101,"props":820,"children":821},{"emptyLinePlaceholder":140},[822],{"type":37,"value":143},{"type":32,"tag":101,"props":824,"children":825},{"class":103,"line":219},[826,831,835],{"type":32,"tag":101,"props":827,"children":828},{"style":124},[829],{"type":37,"value":830},"unnested ",{"type":32,"tag":101,"props":832,"children":833},{"style":678},[834],{"type":37,"value":691},{"type":32,"tag":101,"props":836,"children":837},{"style":124},[838],{"type":37,"value":696},{"type":32,"tag":101,"props":840,"children":841},{"class":103,"line":26},[842],{"type":32,"tag":101,"props":843,"children":844},{"style":678},[845],{"type":37,"value":846},"    select\n",{"type":32,"tag":101,"props":848,"children":849},{"class":103,"line":253},[850],{"type":32,"tag":101,"props":851,"children":852},{"style":124},[853],{"type":37,"value":854},"        event_date,\n",{"type":32,"tag":101,"props":856,"children":857},{"class":103,"line":271},[858],{"type":32,"tag":101,"props":859,"children":860},{"style":124},[861],{"type":37,"value":862},"        event_timestamp,\n",{"type":32,"tag":101,"props":864,"children":865},{"class":103,"line":284},[866],{"type":32,"tag":101,"props":867,"children":868},{"style":124},[869],{"type":37,"value":870},"        user_pseudo_id,\n",{"type":32,"tag":101,"props":872,"children":873},{"class":103,"line":302},[874,879,884,889,894,899,903,908,913,918,923,928,933,937],{"type":32,"tag":101,"props":875,"children":876},{"style":124},[877],{"type":37,"value":878},"        (",{"type":32,"tag":101,"props":880,"children":881},{"style":678},[882],{"type":37,"value":883},"select",{"type":32,"tag":101,"props":885,"children":886},{"style":130},[887],{"type":37,"value":888}," value",{"type":32,"tag":101,"props":890,"children":891},{"style":124},[892],{"type":37,"value":893},".",{"type":32,"tag":101,"props":895,"children":896},{"style":130},[897],{"type":37,"value":898},"string_value",{"type":32,"tag":101,"props":900,"children":901},{"style":678},[902],{"type":37,"value":714},{"type":32,"tag":101,"props":904,"children":905},{"style":124},[906],{"type":37,"value":907}," unnest(event_params) ",{"type":32,"tag":101,"props":909,"children":910},{"style":678},[911],{"type":37,"value":912},"where",{"type":32,"tag":101,"props":914,"children":915},{"style":678},[916],{"type":37,"value":917}," key",{"type":32,"tag":101,"props":919,"children":920},{"style":678},[921],{"type":37,"value":922}," =",{"type":32,"tag":101,"props":924,"children":925},{"style":177},[926],{"type":37,"value":927}," 'page_location'",{"type":32,"tag":101,"props":929,"children":930},{"style":124},[931],{"type":37,"value":932},") ",{"type":32,"tag":101,"props":934,"children":935},{"style":678},[936],{"type":37,"value":691},{"type":32,"tag":101,"props":938,"children":939},{"style":124},[940],{"type":37,"value":941}," page_location,\n",{"type":32,"tag":101,"props":943,"children":944},{"class":103,"line":315},[945,949,953,957,961,966,970,974,978,982,986,991,995,999],{"type":32,"tag":101,"props":946,"children":947},{"style":124},[948],{"type":37,"value":878},{"type":32,"tag":101,"props":950,"children":951},{"style":678},[952],{"type":37,"value":883},{"type":32,"tag":101,"props":954,"children":955},{"style":130},[956],{"type":37,"value":888},{"type":32,"tag":101,"props":958,"children":959},{"style":124},[960],{"type":37,"value":893},{"type":32,"tag":101,"props":962,"children":963},{"style":130},[964],{"type":37,"value":965},"int_value",{"type":32,"tag":101,"props":967,"children":968},{"style":678},[969],{"type":37,"value":714},{"type":32,"tag":101,"props":971,"children":972},{"style":124},[973],{"type":37,"value":907},{"type":32,"tag":101,"props":975,"children":976},{"style":678},[977],{"type":37,"value":912},{"type":32,"tag":101,"props":979,"children":980},{"style":678},[981],{"type":37,"value":917},{"type":32,"tag":101,"props":983,"children":984},{"style":678},[985],{"type":37,"value":922},{"type":32,"tag":101,"props":987,"children":988},{"style":177},[989],{"type":37,"value":990}," 'ga_session_id'",{"type":32,"tag":101,"props":992,"children":993},{"style":124},[994],{"type":37,"value":932},{"type":32,"tag":101,"props":996,"children":997},{"style":678},[998],{"type":37,"value":691},{"type":32,"tag":101,"props":1000,"children":1001},{"style":124},[1002],{"type":37,"value":1003}," session_id,\n",{"type":32,"tag":101,"props":1005,"children":1006},{"class":103,"line":366},[1007,1012,1016,1020],{"type":32,"tag":101,"props":1008,"children":1009},{"style":130},[1010],{"type":37,"value":1011},"        ecommerce",{"type":32,"tag":101,"props":1013,"children":1014},{"style":124},[1015],{"type":37,"value":893},{"type":32,"tag":101,"props":1017,"children":1018},{"style":130},[1019],{"type":37,"value":653},{"type":32,"tag":101,"props":1021,"children":1022},{"style":124},[1023],{"type":37,"value":1024},",\n",{"type":32,"tag":101,"props":1026,"children":1027},{"class":103,"line":412},[1028,1032,1036],{"type":32,"tag":101,"props":1029,"children":1030},{"style":130},[1031],{"type":37,"value":1011},{"type":32,"tag":101,"props":1033,"children":1034},{"style":124},[1035],{"type":37,"value":893},{"type":32,"tag":101,"props":1037,"children":1038},{"style":130},[1039],{"type":37,"value":1040},"purchase_revenue_in_usd\n",{"type":32,"tag":101,"props":1042,"children":1043},{"class":103,"line":420},[1044,1049],{"type":32,"tag":101,"props":1045,"children":1046},{"style":678},[1047],{"type":37,"value":1048},"    from",{"type":32,"tag":101,"props":1050,"children":1051},{"style":124},[1052],{"type":37,"value":1053}," source\n",{"type":32,"tag":101,"props":1055,"children":1056},{"class":103,"line":441},[1057,1061,1066,1071,1076,1081,1085,1090],{"type":32,"tag":101,"props":1058,"children":1059},{"style":678},[1060],{"type":37,"value":746},{"type":32,"tag":101,"props":1062,"children":1063},{"style":124},[1064],{"type":37,"value":1065}," event_name ",{"type":32,"tag":101,"props":1067,"children":1068},{"style":678},[1069],{"type":37,"value":1070},"in",{"type":32,"tag":101,"props":1072,"children":1073},{"style":124},[1074],{"type":37,"value":1075}," (",{"type":32,"tag":101,"props":1077,"children":1078},{"style":177},[1079],{"type":37,"value":1080},"'page_view'",{"type":32,"tag":101,"props":1082,"children":1083},{"style":124},[1084],{"type":37,"value":59},{"type":32,"tag":101,"props":1086,"children":1087},{"style":177},[1088],{"type":37,"value":1089},"'purchase'",{"type":32,"tag":101,"props":1091,"children":1092},{"style":124},[1093],{"type":37,"value":1094},")\n",{"type":32,"tag":101,"props":1096,"children":1097},{"class":103,"line":458},[1098],{"type":32,"tag":101,"props":1099,"children":1100},{"style":124},[1101],{"type":37,"value":1094},{"type":32,"tag":101,"props":1103,"children":1104},{"class":103,"line":470},[1105],{"type":32,"tag":101,"props":1106,"children":1107},{"emptyLinePlaceholder":140},[1108],{"type":37,"value":143},{"type":32,"tag":101,"props":1110,"children":1111},{"class":103,"line":491},[1112,1116,1120,1124],{"type":32,"tag":101,"props":1113,"children":1114},{"style":678},[1115],{"type":37,"value":883},{"type":32,"tag":101,"props":1117,"children":1118},{"style":678},[1119],{"type":37,"value":709},{"type":32,"tag":101,"props":1121,"children":1122},{"style":678},[1123],{"type":37,"value":714},{"type":32,"tag":101,"props":1125,"children":1126},{"style":124},[1127],{"type":37,"value":1128}," unnested\n",{"type":32,"tag":33,"props":1130,"children":1131},{},[1132,1134,1140,1142,1148],{"type":37,"value":1133},"Эта модель получает префикс ",{"type":32,"tag":52,"props":1135,"children":1137},{"className":1136},[],[1138],{"type":37,"value":1139},"stg_",{"type":37,"value":1141}," — downstream никто не трогает source, все берут из staging. Staging models могут быть incremental: каждый день обрабатываются только новые партиции. Команда ",{"type":32,"tag":52,"props":1143,"children":1145},{"className":1144},[],[1146],{"type":37,"value":1147},"dbt build --select stg_ga4__events",{"type":37,"value":1149}," выполняется за 30 секунд, не требует переобработки 90 дней истории.",{"type":32,"tag":33,"props":1151,"children":1152},{},[1153,1155,1161,1162,1168,1169,1175],{"type":37,"value":1154},"Intermediate models объединяют staging и создают аналитические концепции: ",{"type":32,"tag":52,"props":1156,"children":1158},{"className":1157},[],[1159],{"type":37,"value":1160},"int_sessions",{"type":37,"value":59},{"type":32,"tag":52,"props":1163,"children":1165},{"className":1164},[],[1166],{"type":37,"value":1167},"int_customer_cohorts",{"type":37,"value":59},{"type":32,"tag":52,"props":1170,"children":1172},{"className":1171},[],[1173],{"type":37,"value":1174},"int_channel_attribution",{"type":37,"value":1176},". Скрывают логику промежуточных таблиц. Например, расчёт multi-touch attribution является intermediate:",{"type":32,"tag":91,"props":1178,"children":1180},{"className":658,"code":1179,"language":660,"meta":16,"style":16},"-- models\u002Fintermediate\u002Fmarketing\u002Fint_channel_attribution.sql\nwith touchpoints as (\n    select\n        user_id,\n        session_start_timestamp,\n        source_medium,\n        row_number() over (partition by user_id order by session_start_timestamp) as touch_position,\n        count(*) over (partition by user_id) as total_touches\n    from {{ ref('stg_sessions') }}\n    where user_id is not null\n),\n\nattributed as (\n    select\n        user_id,\n        source_medium,\n        case\n            when touch_position = 1 then 0.4\n            when touch_position = total_touches then 0.4\n            else 0.2 \u002F (total_touches - 2)\n        end as attribution_weight\n    from touchpoints\n)\n\nselect * from attributed\n",[1181],{"type":32,"tag":52,"props":1182,"children":1183},{"__ignoreMap":16},[1184,1192,1212,1219,1227,1235,1243,1299,1351,1372,1388,1395,1402,1418,1425,1432,1439,1447,1489,1526,1570,1588,1600,1607,1615],{"type":32,"tag":101,"props":1185,"children":1186},{"class":103,"line":104},[1187],{"type":32,"tag":101,"props":1188,"children":1189},{"style":108},[1190],{"type":37,"value":1191},"-- models\u002Fintermediate\u002Fmarketing\u002Fint_channel_attribution.sql\n",{"type":32,"tag":101,"props":1193,"children":1194},{"class":103,"line":114},[1195,1199,1204,1208],{"type":32,"tag":101,"props":1196,"children":1197},{"style":678},[1198],{"type":37,"value":681},{"type":32,"tag":101,"props":1200,"children":1201},{"style":124},[1202],{"type":37,"value":1203}," touchpoints ",{"type":32,"tag":101,"props":1205,"children":1206},{"style":678},[1207],{"type":37,"value":691},{"type":32,"tag":101,"props":1209,"children":1210},{"style":124},[1211],{"type":37,"value":696},{"type":32,"tag":101,"props":1213,"children":1214},{"class":103,"line":136},[1215],{"type":32,"tag":101,"props":1216,"children":1217},{"style":678},[1218],{"type":37,"value":846},{"type":32,"tag":101,"props":1220,"children":1221},{"class":103,"line":146},[1222],{"type":32,"tag":101,"props":1223,"children":1224},{"style":124},[1225],{"type":37,"value":1226},"        user_id,\n",{"type":32,"tag":101,"props":1228,"children":1229},{"class":103,"line":159},[1230],{"type":32,"tag":101,"props":1231,"children":1232},{"style":124},[1233],{"type":37,"value":1234},"        session_start_timestamp,\n",{"type":32,"tag":101,"props":1236,"children":1237},{"class":103,"line":183},[1238],{"type":32,"tag":101,"props":1239,"children":1240},{"style":124},[1241],{"type":37,"value":1242},"        source_medium,\n",{"type":32,"tag":101,"props":1244,"children":1245},{"class":103,"line":201},[1246,1251,1256,1261,1265,1270,1275,1280,1285,1290,1294],{"type":32,"tag":101,"props":1247,"children":1248},{"style":130},[1249],{"type":37,"value":1250},"        row_number",{"type":32,"tag":101,"props":1252,"children":1253},{"style":124},[1254],{"type":37,"value":1255},"() ",{"type":32,"tag":101,"props":1257,"children":1258},{"style":678},[1259],{"type":37,"value":1260},"over",{"type":32,"tag":101,"props":1262,"children":1263},{"style":124},[1264],{"type":37,"value":1075},{"type":32,"tag":101,"props":1266,"children":1267},{"style":678},[1268],{"type":37,"value":1269},"partition",{"type":32,"tag":101,"props":1271,"children":1272},{"style":678},[1273],{"type":37,"value":1274}," by",{"type":32,"tag":101,"props":1276,"children":1277},{"style":124},[1278],{"type":37,"value":1279}," user_id ",{"type":32,"tag":101,"props":1281,"children":1282},{"style":678},[1283],{"type":37,"value":1284},"order by",{"type":32,"tag":101,"props":1286,"children":1287},{"style":124},[1288],{"type":37,"value":1289}," session_start_timestamp) ",{"type":32,"tag":101,"props":1291,"children":1292},{"style":678},[1293],{"type":37,"value":691},{"type":32,"tag":101,"props":1295,"children":1296},{"style":124},[1297],{"type":37,"value":1298}," touch_position,\n",{"type":32,"tag":101,"props":1300,"children":1301},{"class":103,"line":219},[1302,1307,1312,1317,1321,1325,1329,1333,1337,1342,1346],{"type":32,"tag":101,"props":1303,"children":1304},{"style":130},[1305],{"type":37,"value":1306},"        count",{"type":32,"tag":101,"props":1308,"children":1309},{"style":124},[1310],{"type":37,"value":1311},"(",{"type":32,"tag":101,"props":1313,"children":1314},{"style":678},[1315],{"type":37,"value":1316},"*",{"type":32,"tag":101,"props":1318,"children":1319},{"style":124},[1320],{"type":37,"value":932},{"type":32,"tag":101,"props":1322,"children":1323},{"style":678},[1324],{"type":37,"value":1260},{"type":32,"tag":101,"props":1326,"children":1327},{"style":124},[1328],{"type":37,"value":1075},{"type":32,"tag":101,"props":1330,"children":1331},{"style":678},[1332],{"type":37,"value":1269},{"type":32,"tag":101,"props":1334,"children":1335},{"style":678},[1336],{"type":37,"value":1274},{"type":32,"tag":101,"props":1338,"children":1339},{"style":124},[1340],{"type":37,"value":1341}," user_id) ",{"type":32,"tag":101,"props":1343,"children":1344},{"style":678},[1345],{"type":37,"value":691},{"type":32,"tag":101,"props":1347,"children":1348},{"style":124},[1349],{"type":37,"value":1350}," total_touches\n",{"type":32,"tag":101,"props":1352,"children":1353},{"class":103,"line":26},[1354,1358,1363,1368],{"type":32,"tag":101,"props":1355,"children":1356},{"style":678},[1357],{"type":37,"value":1048},{"type":32,"tag":101,"props":1359,"children":1360},{"style":124},[1361],{"type":37,"value":1362}," {{ ref(",{"type":32,"tag":101,"props":1364,"children":1365},{"style":177},[1366],{"type":37,"value":1367},"'stg_sessions'",{"type":32,"tag":101,"props":1369,"children":1370},{"style":124},[1371],{"type":37,"value":738},{"type":32,"tag":101,"props":1373,"children":1374},{"class":103,"line":253},[1375,1379,1383],{"type":32,"tag":101,"props":1376,"children":1377},{"style":678},[1378],{"type":37,"value":746},{"type":32,"tag":101,"props":1380,"children":1381},{"style":124},[1382],{"type":37,"value":1279},{"type":32,"tag":101,"props":1384,"children":1385},{"style":678},[1386],{"type":37,"value":1387},"is not null\n",{"type":32,"tag":101,"props":1389,"children":1390},{"class":103,"line":271},[1391],{"type":32,"tag":101,"props":1392,"children":1393},{"style":124},[1394],{"type":37,"value":815},{"type":32,"tag":101,"props":1396,"children":1397},{"class":103,"line":284},[1398],{"type":32,"tag":101,"props":1399,"children":1400},{"emptyLinePlaceholder":140},[1401],{"type":37,"value":143},{"type":32,"tag":101,"props":1403,"children":1404},{"class":103,"line":302},[1405,1410,1414],{"type":32,"tag":101,"props":1406,"children":1407},{"style":124},[1408],{"type":37,"value":1409},"attributed ",{"type":32,"tag":101,"props":1411,"children":1412},{"style":678},[1413],{"type":37,"value":691},{"type":32,"tag":101,"props":1415,"children":1416},{"style":124},[1417],{"type":37,"value":696},{"type":32,"tag":101,"props":1419,"children":1420},{"class":103,"line":315},[1421],{"type":32,"tag":101,"props":1422,"children":1423},{"style":678},[1424],{"type":37,"value":846},{"type":32,"tag":101,"props":1426,"children":1427},{"class":103,"line":366},[1428],{"type":32,"tag":101,"props":1429,"children":1430},{"style":124},[1431],{"type":37,"value":1226},{"type":32,"tag":101,"props":1433,"children":1434},{"class":103,"line":412},[1435],{"type":32,"tag":101,"props":1436,"children":1437},{"style":124},[1438],{"type":37,"value":1242},{"type":32,"tag":101,"props":1440,"children":1441},{"class":103,"line":420},[1442],{"type":32,"tag":101,"props":1443,"children":1444},{"style":678},[1445],{"type":37,"value":1446},"        case\n",{"type":32,"tag":101,"props":1448,"children":1449},{"class":103,"line":441},[1450,1455,1460,1465,1470,1475,1480,1484],{"type":32,"tag":101,"props":1451,"children":1452},{"style":678},[1453],{"type":37,"value":1454},"            when",{"type":32,"tag":101,"props":1456,"children":1457},{"style":124},[1458],{"type":37,"value":1459}," touch_position ",{"type":32,"tag":101,"props":1461,"children":1462},{"style":678},[1463],{"type":37,"value":1464},"=",{"type":32,"tag":101,"props":1466,"children":1467},{"style":130},[1468],{"type":37,"value":1469}," 1",{"type":32,"tag":101,"props":1471,"children":1472},{"style":678},[1473],{"type":37,"value":1474}," then",{"type":32,"tag":101,"props":1476,"children":1477},{"style":130},[1478],{"type":37,"value":1479}," 0",{"type":32,"tag":101,"props":1481,"children":1482},{"style":124},[1483],{"type":37,"value":893},{"type":32,"tag":101,"props":1485,"children":1486},{"style":130},[1487],{"type":37,"value":1488},"4\n",{"type":32,"tag":101,"props":1490,"children":1491},{"class":103,"line":458},[1492,1496,1500,1504,1509,1514,1518,1522],{"type":32,"tag":101,"props":1493,"children":1494},{"style":678},[1495],{"type":37,"value":1454},{"type":32,"tag":101,"props":1497,"children":1498},{"style":124},[1499],{"type":37,"value":1459},{"type":32,"tag":101,"props":1501,"children":1502},{"style":678},[1503],{"type":37,"value":1464},{"type":32,"tag":101,"props":1505,"children":1506},{"style":124},[1507],{"type":37,"value":1508}," total_touches ",{"type":32,"tag":101,"props":1510,"children":1511},{"style":678},[1512],{"type":37,"value":1513},"then",{"type":32,"tag":101,"props":1515,"children":1516},{"style":130},[1517],{"type":37,"value":1479},{"type":32,"tag":101,"props":1519,"children":1520},{"style":124},[1521],{"type":37,"value":893},{"type":32,"tag":101,"props":1523,"children":1524},{"style":130},[1525],{"type":37,"value":1488},{"type":32,"tag":101,"props":1527,"children":1528},{"class":103,"line":470},[1529,1534,1538,1542,1546,1551,1556,1561,1566],{"type":32,"tag":101,"props":1530,"children":1531},{"style":678},[1532],{"type":37,"value":1533},"            else",{"type":32,"tag":101,"props":1535,"children":1536},{"style":130},[1537],{"type":37,"value":1479},{"type":32,"tag":101,"props":1539,"children":1540},{"style":124},[1541],{"type":37,"value":893},{"type":32,"tag":101,"props":1543,"children":1544},{"style":130},[1545],{"type":37,"value":543},{"type":32,"tag":101,"props":1547,"children":1548},{"style":678},[1549],{"type":37,"value":1550}," \u002F",{"type":32,"tag":101,"props":1552,"children":1553},{"style":124},[1554],{"type":37,"value":1555}," (total_touches ",{"type":32,"tag":101,"props":1557,"children":1558},{"style":678},[1559],{"type":37,"value":1560},"-",{"type":32,"tag":101,"props":1562,"children":1563},{"style":130},[1564],{"type":37,"value":1565}," 2",{"type":32,"tag":101,"props":1567,"children":1568},{"style":124},[1569],{"type":37,"value":1094},{"type":32,"tag":101,"props":1571,"children":1572},{"class":103,"line":491},[1573,1578,1583],{"type":32,"tag":101,"props":1574,"children":1575},{"style":678},[1576],{"type":37,"value":1577},"        end",{"type":32,"tag":101,"props":1579,"children":1580},{"style":678},[1581],{"type":37,"value":1582}," as",{"type":32,"tag":101,"props":1584,"children":1585},{"style":124},[1586],{"type":37,"value":1587}," attribution_weight\n",{"type":32,"tag":101,"props":1589,"children":1590},{"class":103,"line":509},[1591,1595],{"type":32,"tag":101,"props":1592,"children":1593},{"style":678},[1594],{"type":37,"value":1048},{"type":32,"tag":101,"props":1596,"children":1597},{"style":124},[1598],{"type":37,"value":1599}," touchpoints\n",{"type":32,"tag":101,"props":1601,"children":1602},{"class":103,"line":521},[1603],{"type":32,"tag":101,"props":1604,"children":1605},{"style":124},[1606],{"type":37,"value":1094},{"type":32,"tag":101,"props":1608,"children":1610},{"class":103,"line":1609},24,[1611],{"type":32,"tag":101,"props":1612,"children":1613},{"emptyLinePlaceholder":140},[1614],{"type":37,"value":143},{"type":32,"tag":101,"props":1616,"children":1618},{"class":103,"line":1617},25,[1619,1623,1627,1631],{"type":32,"tag":101,"props":1620,"children":1621},{"style":678},[1622],{"type":37,"value":883},{"type":32,"tag":101,"props":1624,"children":1625},{"style":678},[1626],{"type":37,"value":709},{"type":32,"tag":101,"props":1628,"children":1629},{"style":678},[1630],{"type":37,"value":714},{"type":32,"tag":101,"props":1632,"children":1633},{"style":124},[1634],{"type":37,"value":1635}," attributed\n",{"type":32,"tag":33,"props":1637,"children":1638},{},[1639,1641,1647,1649,1655,1657,1663],{"type":37,"value":1640},"U-образная модель — первый и последний контакт получают 40%, промежуточные делят оставшиеся 20%. Эта SQL остаётся в intermediate model, data scientist'ы редактируют файл модели, frontend dashboard не трогает. Если нужна параметризация, в ",{"type":32,"tag":52,"props":1642,"children":1644},{"className":1643},[],[1645],{"type":37,"value":1646},"dbt_project.yml",{"type":37,"value":1648}," определяешь ",{"type":32,"tag":52,"props":1650,"children":1652},{"className":1651},[],[1653],{"type":37,"value":1654},"vars.attribution_model: u_shaped",{"type":37,"value":1656}," и читаешь через ",{"type":32,"tag":52,"props":1658,"children":1660},{"className":1659},[],[1661],{"type":37,"value":1662},"{{ var('attribution_model') }}",{"type":37,"value":893},{"type":32,"tag":33,"props":1665,"children":1666},{},[1667,1669,1675,1677,1683,1685,1691,1692,1698,1699,1705,1707,1712,1714,1720,1721,1727],{"type":37,"value":1668},"Mart models — финальный слой: таблицы, которые dashboard, BI tool или ML pipeline потребляют напрямую. Получают префиксы ",{"type":32,"tag":52,"props":1670,"children":1672},{"className":1671},[],[1673],{"type":37,"value":1674},"fct_",{"type":37,"value":1676}," (fact) или ",{"type":32,"tag":52,"props":1678,"children":1680},{"className":1679},[],[1681],{"type":37,"value":1682},"dim_",{"type":37,"value":1684}," (dimension). ",{"type":32,"tag":52,"props":1686,"children":1688},{"className":1687},[],[1689],{"type":37,"value":1690},"fct_orders",{"type":37,"value":59},{"type":32,"tag":52,"props":1693,"children":1695},{"className":1694},[],[1696],{"type":37,"value":1697},"dim_customers",{"type":37,"value":59},{"type":32,"tag":52,"props":1700,"children":1702},{"className":1701},[],[1703],{"type":37,"value":1704},"fct_ad_performance",{"type":37,"value":1706},". Mart models могут быть денормализованы — overhead join'а остаётся в dbt, не в BI tool. Вместо того чтобы в Looker писать \"join order table к customer\", в ",{"type":32,"tag":52,"props":1708,"children":1710},{"className":1709},[],[1711],{"type":37,"value":1690},{"type":37,"value":1713}," уже есть столбцы ",{"type":32,"tag":52,"props":1715,"children":1717},{"className":1716},[],[1718],{"type":37,"value":1719},"customer_lifetime_value",{"type":37,"value":59},{"type":32,"tag":52,"props":1722,"children":1724},{"className":1723},[],[1725],{"type":37,"value":1726},"customer_cohort",{"type":37,"value":893},{"type":32,"tag":40,"props":1729,"children":1731},{"id":1730},"semantic-layer-централизованное-определение-метрик-и-бизнес-логики",[1732],{"type":37,"value":1733},"Semantic layer: централизованное определение метрик и бизнес-логики",{"type":32,"tag":33,"props":1735,"children":1736},{},[1737,1739,1745,1747,1753,1755,1761],{"type":37,"value":1738},"dbt 1.6+ преобразует SQL в концепцию метрик через semantic layer. Раньше каждый dashboard писал свой ",{"type":32,"tag":52,"props":1740,"children":1742},{"className":1741},[],[1743],{"type":37,"value":1744},"sum(revenue)",{"type":37,"value":1746}," — теперь определяешь одну метрику ",{"type":32,"tag":52,"props":1748,"children":1750},{"className":1749},[],[1751],{"type":37,"value":1752},"revenue",{"type":37,"value":1754}," и все dashboard'ы её потребляют. Определение метрики в YAML в папке ",{"type":32,"tag":52,"props":1756,"children":1758},{"className":1757},[],[1759],{"type":37,"value":1760},"metrics\u002F",{"type":37,"value":1762},":",{"type":32,"tag":91,"props":1764,"children":1766},{"className":93,"code":1765,"language":95,"meta":16,"style":16},"# models\u002Fmetrics\u002Fmarketing_metrics.yml\nversion: 2\n\nmetrics:\n  - name: total_revenue\n    label: Общий доход\n    model: ref('fct_orders')\n    calculation_method: sum\n    expression: order_total\n    timestamp: order_date\n    time_grains: [day, week, month, quarter, year]\n    dimensions:\n      - channel\n      - customer_cohort\n      - product_category\n\n  - name: customer_acquisition_cost\n    label: Стоимость привлечения клиента (CAC)\n    calculation_method: derived\n    expression: \"{{ metric('total_ad_spend') }} \u002F {{ metric('new_customers') }}\"\n    timestamp: order_date\n    time_grains: [month, quarter]\n",[1767],{"type":32,"tag":52,"props":1768,"children":1769},{"__ignoreMap":16},[1770,1778,1793,1800,1812,1832,1849,1866,1883,1900,1917,1975,1987,1999,2011,2023,2030,2050,2066,2082,2098,2113],{"type":32,"tag":101,"props":1771,"children":1772},{"class":103,"line":104},[1773],{"type":32,"tag":101,"props":1774,"children":1775},{"style":108},[1776],{"type":37,"value":1777},"# models\u002Fmetrics\u002Fmarketing_metrics.yml\n",{"type":32,"tag":101,"props":1779,"children":1780},{"class":103,"line":114},[1781,1785,1789],{"type":32,"tag":101,"props":1782,"children":1783},{"style":118},[1784],{"type":37,"value":121},{"type":32,"tag":101,"props":1786,"children":1787},{"style":124},[1788],{"type":37,"value":127},{"type":32,"tag":101,"props":1790,"children":1791},{"style":130},[1792],{"type":37,"value":133},{"type":32,"tag":101,"props":1794,"children":1795},{"class":103,"line":136},[1796],{"type":32,"tag":101,"props":1797,"children":1798},{"emptyLinePlaceholder":140},[1799],{"type":37,"value":143},{"type":32,"tag":101,"props":1801,"children":1802},{"class":103,"line":146},[1803,1808],{"type":32,"tag":101,"props":1804,"children":1805},{"style":118},[1806],{"type":37,"value":1807},"metrics",{"type":32,"tag":101,"props":1809,"children":1810},{"style":124},[1811],{"type":37,"value":156},{"type":32,"tag":101,"props":1813,"children":1814},{"class":103,"line":159},[1815,1819,1823,1827],{"type":32,"tag":101,"props":1816,"children":1817},{"style":124},[1818],{"type":37,"value":165},{"type":32,"tag":101,"props":1820,"children":1821},{"style":118},[1822],{"type":37,"value":170},{"type":32,"tag":101,"props":1824,"children":1825},{"style":124},[1826],{"type":37,"value":127},{"type":32,"tag":101,"props":1828,"children":1829},{"style":177},[1830],{"type":37,"value":1831},"total_revenue\n",{"type":32,"tag":101,"props":1833,"children":1834},{"class":103,"line":183},[1835,1840,1844],{"type":32,"tag":101,"props":1836,"children":1837},{"style":118},[1838],{"type":37,"value":1839},"    label",{"type":32,"tag":101,"props":1841,"children":1842},{"style":124},[1843],{"type":37,"value":127},{"type":32,"tag":101,"props":1845,"children":1846},{"style":177},[1847],{"type":37,"value":1848},"Общий доход\n",{"type":32,"tag":101,"props":1850,"children":1851},{"class":103,"line":201},[1852,1857,1861],{"type":32,"tag":101,"props":1853,"children":1854},{"style":118},[1855],{"type":37,"value":1856},"    model",{"type":32,"tag":101,"props":1858,"children":1859},{"style":124},[1860],{"type":37,"value":127},{"type":32,"tag":101,"props":1862,"children":1863},{"style":177},[1864],{"type":37,"value":1865},"ref('fct_orders')\n",{"type":32,"tag":101,"props":1867,"children":1868},{"class":103,"line":219},[1869,1874,1878],{"type":32,"tag":101,"props":1870,"children":1871},{"style":118},[1872],{"type":37,"value":1873},"    calculation_method",{"type":32,"tag":101,"props":1875,"children":1876},{"style":124},[1877],{"type":37,"value":127},{"type":32,"tag":101,"props":1879,"children":1880},{"style":177},[1881],{"type":37,"value":1882},"sum\n",{"type":32,"tag":101,"props":1884,"children":1885},{"class":103,"line":26},[1886,1891,1895],{"type":32,"tag":101,"props":1887,"children":1888},{"style":118},[1889],{"type":37,"value":1890},"    expression",{"type":32,"tag":101,"props":1892,"children":1893},{"style":124},[1894],{"type":37,"value":127},{"type":32,"tag":101,"props":1896,"children":1897},{"style":177},[1898],{"type":37,"value":1899},"order_total\n",{"type":32,"tag":101,"props":1901,"children":1902},{"class":103,"line":253},[1903,1908,1912],{"type":32,"tag":101,"props":1904,"children":1905},{"style":118},[1906],{"type":37,"value":1907},"    timestamp",{"type":32,"tag":101,"props":1909,"children":1910},{"style":124},[1911],{"type":37,"value":127},{"type":32,"tag":101,"props":1913,"children":1914},{"style":177},[1915],{"type":37,"value":1916},"order_date\n",{"type":32,"tag":101,"props":1918,"children":1919},{"class":103,"line":271},[1920,1925,1930,1934,1938,1943,1947,1952,1956,1961,1965,1970],{"type":32,"tag":101,"props":1921,"children":1922},{"style":118},[1923],{"type":37,"value":1924},"    time_grains",{"type":32,"tag":101,"props":1926,"children":1927},{"style":124},[1928],{"type":37,"value":1929},": [",{"type":32,"tag":101,"props":1931,"children":1932},{"style":177},[1933],{"type":37,"value":560},{"type":32,"tag":101,"props":1935,"children":1936},{"style":124},[1937],{"type":37,"value":59},{"type":32,"tag":101,"props":1939,"children":1940},{"style":177},[1941],{"type":37,"value":1942},"week",{"type":32,"tag":101,"props":1944,"children":1945},{"style":124},[1946],{"type":37,"value":59},{"type":32,"tag":101,"props":1948,"children":1949},{"style":177},[1950],{"type":37,"value":1951},"month",{"type":32,"tag":101,"props":1953,"children":1954},{"style":124},[1955],{"type":37,"value":59},{"type":32,"tag":101,"props":1957,"children":1958},{"style":177},[1959],{"type":37,"value":1960},"quarter",{"type":32,"tag":101,"props":1962,"children":1963},{"style":124},[1964],{"type":37,"value":59},{"type":32,"tag":101,"props":1966,"children":1967},{"style":177},[1968],{"type":37,"value":1969},"year",{"type":32,"tag":101,"props":1971,"children":1972},{"style":124},[1973],{"type":37,"value":1974},"]\n",{"type":32,"tag":101,"props":1976,"children":1977},{"class":103,"line":284},[1978,1983],{"type":32,"tag":101,"props":1979,"children":1980},{"style":118},[1981],{"type":37,"value":1982},"    dimensions",{"type":32,"tag":101,"props":1984,"children":1985},{"style":124},[1986],{"type":37,"value":156},{"type":32,"tag":101,"props":1988,"children":1989},{"class":103,"line":302},[1990,1994],{"type":32,"tag":101,"props":1991,"children":1992},{"style":124},[1993],{"type":37,"value":237},{"type":32,"tag":101,"props":1995,"children":1996},{"style":177},[1997],{"type":37,"value":1998},"channel\n",{"type":32,"tag":101,"props":2000,"children":2001},{"class":103,"line":315},[2002,2006],{"type":32,"tag":101,"props":2003,"children":2004},{"style":124},[2005],{"type":37,"value":237},{"type":32,"tag":101,"props":2007,"children":2008},{"style":177},[2009],{"type":37,"value":2010},"customer_cohort\n",{"type":32,"tag":101,"props":2012,"children":2013},{"class":103,"line":366},[2014,2018],{"type":32,"tag":101,"props":2015,"children":2016},{"style":124},[2017],{"type":37,"value":237},{"type":32,"tag":101,"props":2019,"children":2020},{"style":177},[2021],{"type":37,"value":2022},"product_category\n",{"type":32,"tag":101,"props":2024,"children":2025},{"class":103,"line":412},[2026],{"type":32,"tag":101,"props":2027,"children":2028},{"emptyLinePlaceholder":140},[2029],{"type":37,"value":143},{"type":32,"tag":101,"props":2031,"children":2032},{"class":103,"line":420},[2033,2037,2041,2045],{"type":32,"tag":101,"props":2034,"children":2035},{"style":124},[2036],{"type":37,"value":165},{"type":32,"tag":101,"props":2038,"children":2039},{"style":118},[2040],{"type":37,"value":170},{"type":32,"tag":101,"props":2042,"children":2043},{"style":124},[2044],{"type":37,"value":127},{"type":32,"tag":101,"props":2046,"children":2047},{"style":177},[2048],{"type":37,"value":2049},"customer_acquisition_cost\n",{"type":32,"tag":101,"props":2051,"children":2052},{"class":103,"line":441},[2053,2057,2061],{"type":32,"tag":101,"props":2054,"children":2055},{"style":118},[2056],{"type":37,"value":1839},{"type":32,"tag":101,"props":2058,"children":2059},{"style":124},[2060],{"type":37,"value":127},{"type":32,"tag":101,"props":2062,"children":2063},{"style":177},[2064],{"type":37,"value":2065},"Стоимость привлечения клиента (CAC)\n",{"type":32,"tag":101,"props":2067,"children":2068},{"class":103,"line":458},[2069,2073,2077],{"type":32,"tag":101,"props":2070,"children":2071},{"style":118},[2072],{"type":37,"value":1873},{"type":32,"tag":101,"props":2074,"children":2075},{"style":124},[2076],{"type":37,"value":127},{"type":32,"tag":101,"props":2078,"children":2079},{"style":177},[2080],{"type":37,"value":2081},"derived\n",{"type":32,"tag":101,"props":2083,"children":2084},{"class":103,"line":470},[2085,2089,2093],{"type":32,"tag":101,"props":2086,"children":2087},{"style":118},[2088],{"type":37,"value":1890},{"type":32,"tag":101,"props":2090,"children":2091},{"style":124},[2092],{"type":37,"value":127},{"type":32,"tag":101,"props":2094,"children":2095},{"style":177},[2096],{"type":37,"value":2097},"\"{{ metric('total_ad_spend') }} \u002F {{ metric('new_customers') }}\"\n",{"type":32,"tag":101,"props":2099,"children":2100},{"class":103,"line":491},[2101,2105,2109],{"type":32,"tag":101,"props":2102,"children":2103},{"style":118},[2104],{"type":37,"value":1907},{"type":32,"tag":101,"props":2106,"children":2107},{"style":124},[2108],{"type":37,"value":127},{"type":32,"tag":101,"props":2110,"children":2111},{"style":177},[2112],{"type":37,"value":1916},{"type":32,"tag":101,"props":2114,"children":2115},{"class":103,"line":509},[2116,2120,2124,2128,2132,2136],{"type":32,"tag":101,"props":2117,"children":2118},{"style":118},[2119],{"type":37,"value":1924},{"type":32,"tag":101,"props":2121,"children":2122},{"style":124},[2123],{"type":37,"value":1929},{"type":32,"tag":101,"props":2125,"children":2126},{"style":177},[2127],{"type":37,"value":1951},{"type":32,"tag":101,"props":2129,"children":2130},{"style":124},[2131],{"type":37,"value":59},{"type":32,"tag":101,"props":2133,"children":2134},{"style":177},[2135],{"type":37,"value":1960},{"type":32,"tag":101,"props":2137,"children":2138},{"style":124},[2139],{"type":37,"value":1974},{"type":32,"tag":33,"props":2141,"children":2142},{},[2143,2145,2151,2153,2159,2161,2167],{"type":37,"value":2144},"С этим определением запрос в Looker \"Show me ",{"type":32,"tag":52,"props":2146,"children":2148},{"className":2147},[],[2149],{"type":37,"value":2150},"total_revenue",{"type":37,"value":2152}," by ",{"type":32,"tag":52,"props":2154,"children":2156},{"className":2155},[],[2157],{"type":37,"value":2158},"channel",{"type":37,"value":2160}," for last quarter\" автоматически разворачивается через dbt Semantic Layer API. Не пишешь SQL — вызываешь метрику. ",{"type":32,"tag":52,"props":2162,"children":2164},{"className":2163},[],[2165],{"type":37,"value":2166},"customer_acquisition_cost",{"type":37,"value":2168}," — это derived метрика, вычисляется из двух других метрик. Если формула меняется, редактируешь в одном месте, не обновляешь 12 dashboard'ов вручную.",{"type":32,"tag":33,"props":2170,"children":2171},{},[2172,2174,2183,2185,2190,2192,2198,2200,2206,2208,2214],{"type":37,"value":2173},"Второе преимущество semantic layer: он требует ",{"type":32,"tag":2175,"props":2176,"children":2180},"a",{"href":2177,"rel":2178},"https:\u002F\u002Fwww.roibase.com.tr\u002Fru\u002Ffirstparty",[2179],"nofollow",[2181],{"type":37,"value":2182},"архитектуру first-party данных",{"type":37,"value":2184},", потому что определение метрики опирается на customer ID. Если ",{"type":32,"tag":52,"props":2186,"children":2188},{"className":2187},[],[2189],{"type":37,"value":604},{"type":37,"value":2191}," из GA4 и ",{"type":32,"tag":52,"props":2193,"children":2195},{"className":2194},[],[2196],{"type":37,"value":2197},"customer_id",{"type":37,"value":2199}," из Shopify ссылаются на одного человека, identity resolution должна быть решена в intermediate model. Таблица ",{"type":32,"tag":52,"props":2201,"children":2203},{"className":2202},[],[2204],{"type":37,"value":2205},"dim_unified_customers",{"type":37,"value":2207}," мерджит все сигналы и возвращает ",{"type":32,"tag":52,"props":2209,"children":2211},{"className":2210},[],[2212],{"type":37,"value":2213},"canonical_customer_id",{"type":37,"value":2215},". Этот ID используется как dimension в semantic layer. Без canonical ID метрика CAC будет неправильной — одного клиента посчитаешь дважды.",{"type":32,"tag":40,"props":2217,"children":2219},{"id":2218},"exposures-точки-нижележащего-потребления",[2220],{"type":37,"value":2221},"Exposures: точки нижележащего потребления",{"type":32,"tag":33,"props":2223,"children":2224},{},[2225],{"type":37,"value":2226},"Exposures — последняя концепция dbt: регистрация того, какой dashboard, какой Airflow task, какая модель машинного обучения потребляет данные из этого pipeline. В формате YAML:",{"type":32,"tag":91,"props":2228,"children":2230},{"className":93,"code":2229,"language":95,"meta":16,"style":16},"# models\u002Fexposures\u002Fmarketing_exposures.yml\nversion: 2\n\nexposures:\n  - name: executive_marketing_dashboard\n    type: dashboard\n    maturity: high\n    url: https:\u002F\u002Flookerstudio.google.com\u002Freporting\u002Fabc123\n    description: \"Dashboard CMO: доход, CAC, LTV по каналам\"\n    depends_on:\n      - ref('fct_orders')\n      - ref('fct_ad_performance')\n      - metric('total_revenue')\n      - metric('customer_acquisition_cost')\n    owner:\n      name: Marketing Ops Team\n      email: ops@roibase.com.tr\n\n  - name: klaviyo_segment_sync\n    type: application\n    maturity: medium\n    description: \"BigQuery → Klaviyo segment sync через Hightouch\"\n    depends_on:\n      - ref('dim_unified_customers')\n    owner:\n      name: CRM Automation\n      email: crm@roibase.com.tr\n",[2231],{"type":32,"tag":52,"props":2232,"children":2233},{"__ignoreMap":16},[2234,2242,2257,2264,2276,2296,2313,2330,2347,2364,2376,2387,2399,2411,2423,2435,2452,2469,2476,2496,2512,2528,2544,2555,2567,2578,2595],{"type":32,"tag":101,"props":2235,"children":2236},{"class":103,"line":104},[2237],{"type":32,"tag":101,"props":2238,"children":2239},{"style":108},[2240],{"type":37,"value":2241},"# models\u002Fexposures\u002Fmarketing_exposures.yml\n",{"type":32,"tag":101,"props":2243,"children":2244},{"class":103,"line":114},[2245,2249,2253],{"type":32,"tag":101,"props":2246,"children":2247},{"style":118},[2248],{"type":37,"value":121},{"type":32,"tag":101,"props":2250,"children":2251},{"style":124},[2252],{"type":37,"value":127},{"type":32,"tag":101,"props":2254,"children":2255},{"style":130},[2256],{"type":37,"value":133},{"type":32,"tag":101,"props":2258,"children":2259},{"class":103,"line":136},[2260],{"type":32,"tag":101,"props":2261,"children":2262},{"emptyLinePlaceholder":140},[2263],{"type":37,"value":143},{"type":32,"tag":101,"props":2265,"children":2266},{"class":103,"line":146},[2267,2272],{"type":32,"tag":101,"props":2268,"children":2269},{"style":118},[2270],{"type":37,"value":2271},"exposures",{"type":32,"tag":101,"props":2273,"children":2274},{"style":124},[2275],{"type":37,"value":156},{"type":32,"tag":101,"props":2277,"children":2278},{"class":103,"line":159},[2279,2283,2287,2291],{"type":32,"tag":101,"props":2280,"children":2281},{"style":124},[2282],{"type":37,"value":165},{"type":32,"tag":101,"props":2284,"children":2285},{"style":118},[2286],{"type":37,"value":170},{"type":32,"tag":101,"props":2288,"children":2289},{"style":124},[2290],{"type":37,"value":127},{"type":32,"tag":101,"props":2292,"children":2293},{"style":177},[2294],{"type":37,"value":2295},"executive_marketing_dashboard\n",{"type":32,"tag":101,"props":2297,"children":2298},{"class":103,"line":183},[2299,2304,2308],{"type":32,"tag":101,"props":2300,"children":2301},{"style":118},[2302],{"type":37,"value":2303},"    type",{"type":32,"tag":101,"props":2305,"children":2306},{"style":124},[2307],{"type":37,"value":127},{"type":32,"tag":101,"props":2309,"children":2310},{"style":177},[2311],{"type":37,"value":2312},"dashboard\n",{"type":32,"tag":101,"props":2314,"children":2315},{"class":103,"line":201},[2316,2321,2325],{"type":32,"tag":101,"props":2317,"children":2318},{"style":118},[2319],{"type":37,"value":2320},"    maturity",{"type":32,"tag":101,"props":2322,"children":2323},{"style":124},[2324],{"type":37,"value":127},{"type":32,"tag":101,"props":2326,"children":2327},{"style":177},[2328],{"type":37,"value":2329},"high\n",{"type":32,"tag":101,"props":2331,"children":2332},{"class":103,"line":219},[2333,2338,2342],{"type":32,"tag":101,"props":2334,"children":2335},{"style":118},[2336],{"type":37,"value":2337},"    url",{"type":32,"tag":101,"props":2339,"children":2340},{"style":124},[2341],{"type":37,"value":127},{"type":32,"tag":101,"props":2343,"children":2344},{"style":177},[2345],{"type":37,"value":2346},"https:\u002F\u002Flookerstudio.google.com\u002Freporting\u002Fabc123\n",{"type":32,"tag":101,"props":2348,"children":2349},{"class":103,"line":26},[2350,2355,2359],{"type":32,"tag":101,"props":2351,"children":2352},{"style":118},[2353],{"type":37,"value":2354},"    description",{"type":32,"tag":101,"props":2356,"children":2357},{"style":124},[2358],{"type":37,"value":127},{"type":32,"tag":101,"props":2360,"children":2361},{"style":177},[2362],{"type":37,"value":2363},"\"Dashboard CMO: доход, CAC, LTV по каналам\"\n",{"type":32,"tag":101,"props":2365,"children":2366},{"class":103,"line":253},[2367,2372],{"type":32,"tag":101,"props":2368,"children":2369},{"style":118},[2370],{"type":37,"value":2371},"    depends_on",{"type":32,"tag":101,"props":2373,"children":2374},{"style":124},[2375],{"type":37,"value":156},{"type":32,"tag":101,"props":2377,"children":2378},{"class":103,"line":271},[2379,2383],{"type":32,"tag":101,"props":2380,"children":2381},{"style":124},[2382],{"type":37,"value":237},{"type":32,"tag":101,"props":2384,"children":2385},{"style":177},[2386],{"type":37,"value":1865},{"type":32,"tag":101,"props":2388,"children":2389},{"class":103,"line":284},[2390,2394],{"type":32,"tag":101,"props":2391,"children":2392},{"style":124},[2393],{"type":37,"value":237},{"type":32,"tag":101,"props":2395,"children":2396},{"style":177},[2397],{"type":37,"value":2398},"ref('fct_ad_performance')\n",{"type":32,"tag":101,"props":2400,"children":2401},{"class":103,"line":302},[2402,2406],{"type":32,"tag":101,"props":2403,"children":2404},{"style":124},[2405],{"type":37,"value":237},{"type":32,"tag":101,"props":2407,"children":2408},{"style":177},[2409],{"type":37,"value":2410},"metric('total_revenue')\n",{"type":32,"tag":101,"props":2412,"children":2413},{"class":103,"line":315},[2414,2418],{"type":32,"tag":101,"props":2415,"children":2416},{"style":124},[2417],{"type":37,"value":237},{"type":32,"tag":101,"props":2419,"children":2420},{"style":177},[2421],{"type":37,"value":2422},"metric('customer_acquisition_cost')\n",{"type":32,"tag":101,"props":2424,"children":2425},{"class":103,"line":366},[2426,2431],{"type":32,"tag":101,"props":2427,"children":2428},{"style":118},[2429],{"type":37,"value":2430},"    owner",{"type":32,"tag":101,"props":2432,"children":2433},{"style":124},[2434],{"type":37,"value":156},{"type":32,"tag":101,"props":2436,"children":2437},{"class":103,"line":412},[2438,2443,2447],{"type":32,"tag":101,"props":2439,"children":2440},{"style":118},[2441],{"type":37,"value":2442},"      name",{"type":32,"tag":101,"props":2444,"children":2445},{"style":124},[2446],{"type":37,"value":127},{"type":32,"tag":101,"props":2448,"children":2449},{"style":177},[2450],{"type":37,"value":2451},"Marketing Ops Team\n",{"type":32,"tag":101,"props":2453,"children":2454},{"class":103,"line":420},[2455,2460,2464],{"type":32,"tag":101,"props":2456,"children":2457},{"style":118},[2458],{"type":37,"value":2459},"      email",{"type":32,"tag":101,"props":2461,"children":2462},{"style":124},[2463],{"type":37,"value":127},{"type":32,"tag":101,"props":2465,"children":2466},{"style":177},[2467],{"type":37,"value":2468},"ops@roibase.com.tr\n",{"type":32,"tag":101,"props":2470,"children":2471},{"class":103,"line":441},[2472],{"type":32,"tag":101,"props":2473,"children":2474},{"emptyLinePlaceholder":140},[2475],{"type":37,"value":143},{"type":32,"tag":101,"props":2477,"children":2478},{"class":103,"line":458},[2479,2483,2487,2491],{"type":32,"tag":101,"props":2480,"children":2481},{"style":124},[2482],{"type":37,"value":165},{"type":32,"tag":101,"props":2484,"children":2485},{"style":118},[2486],{"type":37,"value":170},{"type":32,"tag":101,"props":2488,"children":2489},{"style":124},[2490],{"type":37,"value":127},{"type":32,"tag":101,"props":2492,"children":2493},{"style":177},[2494],{"type":37,"value":2495},"klaviyo_segment_sync\n",{"type":32,"tag":101,"props":2497,"children":2498},{"class":103,"line":470},[2499,2503,2507],{"type":32,"tag":101,"props":2500,"children":2501},{"style":118},[2502],{"type":37,"value":2303},{"type":32,"tag":101,"props":2504,"children":2505},{"style":124},[2506],{"type":37,"value":127},{"type":32,"tag":101,"props":2508,"children":2509},{"style":177},[2510],{"type":37,"value":2511},"application\n",{"type":32,"tag":101,"props":2513,"children":2514},{"class":103,"line":491},[2515,2519,2523],{"type":32,"tag":101,"props":2516,"children":2517},{"style":118},[2518],{"type":37,"value":2320},{"type":32,"tag":101,"props":2520,"children":2521},{"style":124},[2522],{"type":37,"value":127},{"type":32,"tag":101,"props":2524,"children":2525},{"style":177},[2526],{"type":37,"value":2527},"medium\n",{"type":32,"tag":101,"props":2529,"children":2530},{"class":103,"line":509},[2531,2535,2539],{"type":32,"tag":101,"props":2532,"children":2533},{"style":118},[2534],{"type":37,"value":2354},{"type":32,"tag":101,"props":2536,"children":2537},{"style":124},[2538],{"type":37,"value":127},{"type":32,"tag":101,"props":2540,"children":2541},{"style":177},[2542],{"type":37,"value":2543},"\"BigQuery → Klaviyo segment sync через Hightouch\"\n",{"type":32,"tag":101,"props":2545,"children":2546},{"class":103,"line":521},[2547,2551],{"type":32,"tag":101,"props":2548,"children":2549},{"style":118},[2550],{"type":37,"value":2371},{"type":32,"tag":101,"props":2552,"children":2553},{"style":124},[2554],{"type":37,"value":156},{"type":32,"tag":101,"props":2556,"children":2557},{"class":103,"line":1609},[2558,2562],{"type":32,"tag":101,"props":2559,"children":2560},{"style":124},[2561],{"type":37,"value":237},{"type":32,"tag":101,"props":2563,"children":2564},{"style":177},[2565],{"type":37,"value":2566},"ref('dim_unified_customers')\n",{"type":32,"tag":101,"props":2568,"children":2569},{"class":103,"line":1617},[2570,2574],{"type":32,"tag":101,"props":2571,"children":2572},{"style":118},[2573],{"type":37,"value":2430},{"type":32,"tag":101,"props":2575,"children":2576},{"style":124},[2577],{"type":37,"value":156},{"type":32,"tag":101,"props":2579,"children":2581},{"class":103,"line":2580},26,[2582,2586,2590],{"type":32,"tag":101,"props":2583,"children":2584},{"style":118},[2585],{"type":37,"value":2442},{"type":32,"tag":101,"props":2587,"children":2588},{"style":124},[2589],{"type":37,"value":127},{"type":32,"tag":101,"props":2591,"children":2592},{"style":177},[2593],{"type":37,"value":2594},"CRM Automation\n",{"type":32,"tag":101,"props":2596,"children":2598},{"class":103,"line":2597},27,[2599,2603,2607],{"type":32,"tag":101,"props":2600,"children":2601},{"style":118},[2602],{"type":37,"value":2459},{"type":32,"tag":101,"props":2604,"children":2605},{"style":124},[2606],{"type":37,"value":127},{"type":32,"tag":101,"props":2608,"children":2609},{"style":177},[2610],{"type":37,"value":2611},"crm@roibase.com.tr\n",{"type":32,"tag":33,"props":2613,"children":2614},{},[2615,2617,2623,2625,2630],{"type":37,"value":2616},"С этим manifest'ом после ",{"type":32,"tag":52,"props":2618,"children":2620},{"className":2619},[],[2621],{"type":37,"value":2622},"dbt docs generate",{"type":37,"value":2624}," exposures видны как конечные точки в DAG. Если ты меняешь модель ",{"type":32,"tag":52,"props":2626,"children":2628},{"className":2627},[],[2629],{"type":37,"value":1690},{"type":37,"value":2631},", в графе lineage становится видно, какой dashboard будет затронут. Exposure также служит правилом alerting'а: в Slack можно послать \"executive_marketing_dashboard upstream failed\".",{"type":32,"tag":33,"props":2633,"children":2634},{},[2635,2637,2643,2645,2651,2653,2659],{"type":37,"value":2636},"Поле maturity exposure'а отслеживает технический долг: exposure с ",{"type":32,"tag":52,"props":2638,"children":2640},{"className":2639},[],[2641],{"type":37,"value":2642},"low",{"type":37,"value":2644}," maturity может быть создан для временного анализа, ",{"type":32,"tag":52,"props":2646,"children":2648},{"className":2647},[],[2649],{"type":37,"value":2650},"high",{"type":37,"value":2652}," maturity — production-critical. Команда ",{"type":32,"tag":52,"props":2654,"children":2656},{"className":2655},[],[2657],{"type":37,"value":2658},"dbt list --select exposure:executive_marketing_dashboard+",{"type":37,"value":2660}," выводит дерево зависимостей этого dashboard'а — при deprecation model'и проводишь анализ влияния.",{"type":32,"tag":40,"props":2662,"children":2664},{"id":2663},"test-coverage-и-контракт-качества-данных",[2665],{"type":37,"value":2666},"Test coverage и контракт качества данных",{"type":32,"tag":33,"props":2668,"children":2669},{},[2670,2672,2678],{"type":37,"value":2671},"Мощь dbt не только в трансформации, но и в test suite. Для каждой модели определяешь тесты в файле ",{"type":32,"tag":52,"props":2673,"children":2675},{"className":2674},[],[2676],{"type":37,"value":2677},"schema.yml",{"type":37,"value":1762},{"type":32,"tag":91,"props":2680,"children":2682},{"className":93,"code":2681,"language":95,"meta":16,"style":16},"# models\u002Fmarts\u002Fmarketing\u002Ffct_orders.yml\nversion: 2\n\nmodels:\n  - name: fct_orders\n    description: \"Денормализованная таблица фактов заказов для BI\"\n    columns:\n      - name: order_id\n        description: \"Primary key\"\n        tests:\n          - unique\n          - not_null\n\n      - name: customer_id\n        description: \"Foreign key to dim_customers\"\n        tests:\n          - not_null\n          - relationships:\n              to: ref('dim_customers')\n              field: customer_id\n\n      - name: order_total\n        description: \"Сумма заказа в USD\"\n        tests:\n          - not_null\n          - dbt_utils.expression_is_true:\n              expression: \">= 0\"\n\n      - name: order_date\n        tests:\n          - not_null\n          - dbt_utils.accepted_range:\n              min_value: \"'2020-01-01'\"\n              max_value: \"current_date()\"\n",[2683],{"type":32,"tag":52,"props":2684,"children":2685},{"__ignoreMap":16},[2686,2694,2709,2716,2728,2748,2764,2776,2796,2813,2825,2838,2850,2857,2877,2893,2904,2915,2931,2948,2964,2971,2990,3006,3017,3028,3044,3061,3069,3089,3101,3113,3130,3148],{"type":32,"tag":101,"props":2687,"children":2688},{"class":103,"line":104},[2689],{"type":32,"tag":101,"props":2690,"children":2691},{"style":108},[2692],{"type":37,"value":2693},"# models\u002Fmarts\u002Fmarketing\u002Ffct_orders.yml\n",{"type":32,"tag":101,"props":2695,"children":2696},{"class":103,"line":114},[2697,2701,2705],{"type":32,"tag":101,"props":2698,"children":2699},{"style":118},[2700],{"type":37,"value":121},{"type":32,"tag":101,"props":2702,"children":2703},{"style":124},[2704],{"type":37,"value":127},{"type":32,"tag":101,"props":2706,"children":2707},{"style":130},[2708],{"type":37,"value":133},{"type":32,"tag":101,"props":2710,"children":2711},{"class":103,"line":136},[2712],{"type":32,"tag":101,"props":2713,"children":2714},{"emptyLinePlaceholder":140},[2715],{"type":37,"value":143},{"type":32,"tag":101,"props":2717,"children":2718},{"class":103,"line":146},[2719,2724],{"type":32,"tag":101,"props":2720,"children":2721},{"style":118},[2722],{"type":37,"value":2723},"models",{"type":32,"tag":101,"props":2725,"children":2726},{"style":124},[2727],{"type":37,"value":156},{"type":32,"tag":101,"props":2729,"children":2730},{"class":103,"line":159},[2731,2735,2739,2743],{"type":32,"tag":101,"props":2732,"children":2733},{"style":124},[2734],{"type":37,"value":165},{"type":32,"tag":101,"props":2736,"children":2737},{"style":118},[2738],{"type":37,"value":170},{"type":32,"tag":101,"props":2740,"children":2741},{"style":124},[2742],{"type":37,"value":127},{"type":32,"tag":101,"props":2744,"children":2745},{"style":177},[2746],{"type":37,"value":2747},"fct_orders\n",{"type":32,"tag":101,"props":2749,"children":2750},{"class":103,"line":183},[2751,2755,2759],{"type":32,"tag":101,"props":2752,"children":2753},{"style":118},[2754],{"type":37,"value":2354},{"type":32,"tag":101,"props":2756,"children":2757},{"style":124},[2758],{"type":37,"value":127},{"type":32,"tag":101,"props":2760,"children":2761},{"style":177},[2762],{"type":37,"value":2763},"\"Денормализованная таблица фактов заказов для BI\"\n",{"type":32,"tag":101,"props":2765,"children":2766},{"class":103,"line":201},[2767,2772],{"type":32,"tag":101,"props":2768,"children":2769},{"style":118},[2770],{"type":37,"value":2771},"    columns",{"type":32,"tag":101,"props":2773,"children":2774},{"style":124},[2775],{"type":37,"value":156},{"type":32,"tag":101,"props":2777,"children":2778},{"class":103,"line":219},[2779,2783,2787,2791],{"type":32,"tag":101,"props":2780,"children":2781},{"style":124},[2782],{"type":37,"value":237},{"type":32,"tag":101,"props":2784,"children":2785},{"style":118},[2786],{"type":37,"value":170},{"type":32,"tag":101,"props":2788,"children":2789},{"style":124},[2790],{"type":37,"value":127},{"type":32,"tag":101,"props":2792,"children":2793},{"style":177},[2794],{"type":37,"value":2795},"order_id\n",{"type":32,"tag":101,"props":2797,"children":2798},{"class":103,"line":26},[2799,2804,2808],{"type":32,"tag":101,"props":2800,"children":2801},{"style":118},[2802],{"type":37,"value":2803},"        description",{"type":32,"tag":101,"props":2805,"children":2806},{"style":124},[2807],{"type":37,"value":127},{"type":32,"tag":101,"props":2809,"children":2810},{"style":177},[2811],{"type":37,"value":2812},"\"Primary key\"\n",{"type":32,"tag":101,"props":2814,"children":2815},{"class":103,"line":253},[2816,2821],{"type":32,"tag":101,"props":2817,"children":2818},{"style":118},[2819],{"type":37,"value":2820},"        tests",{"type":32,"tag":101,"props":2822,"children":2823},{"style":124},[2824],{"type":37,"value":156},{"type":32,"tag":101,"props":2826,"children":2827},{"class":103,"line":271},[2828,2833],{"type":32,"tag":101,"props":2829,"children":2830},{"style":124},[2831],{"type":37,"value":2832},"          - ",{"type":32,"tag":101,"props":2834,"children":2835},{"style":177},[2836],{"type":37,"value":2837},"unique\n",{"type":32,"tag":101,"props":2839,"children":2840},{"class":103,"line":284},[2841,2845],{"type":32,"tag":101,"props":2842,"children":2843},{"style":124},[2844],{"type":37,"value":2832},{"type":32,"tag":101,"props":2846,"children":2847},{"style":177},[2848],{"type":37,"value":2849},"not_null\n",{"type":32,"tag":101,"props":2851,"children":2852},{"class":103,"line":302},[2853],{"type":32,"tag":101,"props":2854,"children":2855},{"emptyLinePlaceholder":140},[2856],{"type":37,"value":143},{"type":32,"tag":101,"props":2858,"children":2859},{"class":103,"line":315},[2860,2864,2868,2872],{"type":32,"tag":101,"props":2861,"children":2862},{"style":124},[2863],{"type":37,"value":237},{"type":32,"tag":101,"props":2865,"children":2866},{"style":118},[2867],{"type":37,"value":170},{"type":32,"tag":101,"props":2869,"children":2870},{"style":124},[2871],{"type":37,"value":127},{"type":32,"tag":101,"props":2873,"children":2874},{"style":177},[2875],{"type":37,"value":2876},"customer_id\n",{"type":32,"tag":101,"props":2878,"children":2879},{"class":103,"line":366},[2880,2884,2888],{"type":32,"tag":101,"props":2881,"children":2882},{"style":118},[2883],{"type":37,"value":2803},{"type":32,"tag":101,"props":2885,"children":2886},{"style":124},[2887],{"type":37,"value":127},{"type":32,"tag":101,"props":2889,"children":2890},{"style":177},[2891],{"type":37,"value":2892},"\"Foreign key to dim_customers\"\n",{"type":32,"tag":101,"props":2894,"children":2895},{"class":103,"line":412},[2896,2900],{"type":32,"tag":101,"props":2897,"children":2898},{"style":118},[2899],{"type":37,"value":2820},{"type":32,"tag":101,"props":2901,"children":2902},{"style":124},[2903],{"type":37,"value":156},{"type":32,"tag":101,"props":2905,"children":2906},{"class":103,"line":420},[2907,2911],{"type":32,"tag":101,"props":2908,"children":2909},{"style":124},[2910],{"type":37,"value":2832},{"type":32,"tag":101,"props":2912,"children":2913},{"style":177},[2914],{"type":37,"value":2849},{"type":32,"tag":101,"props":2916,"children":2917},{"class":103,"line":441},[2918,2922,2927],{"type":32,"tag":101,"props":2919,"children":2920},{"style":124},[2921],{"type":37,"value":2832},{"type":32,"tag":101,"props":2923,"children":2924},{"style":118},[2925],{"type":37,"value":2926},"relationships",{"type":32,"tag":101,"props":2928,"children":2929},{"style":124},[2930],{"type":37,"value":156},{"type":32,"tag":101,"props":2932,"children":2933},{"class":103,"line":458},[2934,2939,2943],{"type":32,"tag":101,"props":2935,"children":2936},{"style":118},[2937],{"type":37,"value":2938},"              to",{"type":32,"tag":101,"props":2940,"children":2941},{"style":124},[2942],{"type":37,"value":127},{"type":32,"tag":101,"props":2944,"children":2945},{"style":177},[2946],{"type":37,"value":2947},"ref('dim_customers')\n",{"type":32,"tag":101,"props":2949,"children":2950},{"class":103,"line":470},[2951,2956,2960],{"type":32,"tag":101,"props":2952,"children":2953},{"style":118},[2954],{"type":37,"value":2955},"              field",{"type":32,"tag":101,"props":2957,"children":2958},{"style":124},[2959],{"type":37,"value":127},{"type":32,"tag":101,"props":2961,"children":2962},{"style":177},[2963],{"type":37,"value":2876},{"type":32,"tag":101,"props":2965,"children":2966},{"class":103,"line":491},[2967],{"type":32,"tag":101,"props":2968,"children":2969},{"emptyLinePlaceholder":140},[2970],{"type":37,"value":143},{"type":32,"tag":101,"props":2972,"children":2973},{"class":103,"line":509},[2974,2978,2982,2986],{"type":32,"tag":101,"props":2975,"children":2976},{"style":124},[2977],{"type":37,"value":237},{"type":32,"tag":101,"props":2979,"children":2980},{"style":118},[2981],{"type":37,"value":170},{"type":32,"tag":101,"props":2983,"children":2984},{"style":124},[2985],{"type":37,"value":127},{"type":32,"tag":101,"props":2987,"children":2988},{"style":177},[2989],{"type":37,"value":1899},{"type":32,"tag":101,"props":2991,"children":2992},{"class":103,"line":521},[2993,2997,3001],{"type":32,"tag":101,"props":2994,"children":2995},{"style":118},[2996],{"type":37,"value":2803},{"type":32,"tag":101,"props":2998,"children":2999},{"style":124},[3000],{"type":37,"value":127},{"type":32,"tag":101,"props":3002,"children":3003},{"style":177},[3004],{"type":37,"value":3005},"\"Сумма заказа в USD\"\n",{"type":32,"tag":101,"props":3007,"children":3008},{"class":103,"line":1609},[3009,3013],{"type":32,"tag":101,"props":3010,"children":3011},{"style":118},[3012],{"type":37,"value":2820},{"type":32,"tag":101,"props":3014,"children":3015},{"style":124},[3016],{"type":37,"value":156},{"type":32,"tag":101,"props":3018,"children":3019},{"class":103,"line":1617},[3020,3024],{"type":32,"tag":101,"props":3021,"children":3022},{"style":124},[3023],{"type":37,"value":2832},{"type":32,"tag":101,"props":3025,"children":3026},{"style":177},[3027],{"type":37,"value":2849},{"type":32,"tag":101,"props":3029,"children":3030},{"class":103,"line":2580},[3031,3035,3040],{"type":32,"tag":101,"props":3032,"children":3033},{"style":124},[3034],{"type":37,"value":2832},{"type":32,"tag":101,"props":3036,"children":3037},{"style":118},[3038],{"type":37,"value":3039},"dbt_utils.expression_is_true",{"type":32,"tag":101,"props":3041,"children":3042},{"style":124},[3043],{"type":37,"value":156},{"type":32,"tag":101,"props":3045,"children":3046},{"class":103,"line":2597},[3047,3052,3056],{"type":32,"tag":101,"props":3048,"children":3049},{"style":118},[3050],{"type":37,"value":3051},"              expression",{"type":32,"tag":101,"props":3053,"children":3054},{"style":124},[3055],{"type":37,"value":127},{"type":32,"tag":101,"props":3057,"children":3058},{"style":177},[3059],{"type":37,"value":3060},"\">= 0\"\n",{"type":32,"tag":101,"props":3062,"children":3064},{"class":103,"line":3063},28,[3065],{"type":32,"tag":101,"props":3066,"children":3067},{"emptyLinePlaceholder":140},[3068],{"type":37,"value":143},{"type":32,"tag":101,"props":3070,"children":3072},{"class":103,"line":3071},29,[3073,3077,3081,3085],{"type":32,"tag":101,"props":3074,"children":3075},{"style":124},[3076],{"type":37,"value":237},{"type":32,"tag":101,"props":3078,"children":3079},{"style":118},[3080],{"type":37,"value":170},{"type":32,"tag":101,"props":3082,"children":3083},{"style":124},[3084],{"type":37,"value":127},{"type":32,"tag":101,"props":3086,"children":3087},{"style":177},[3088],{"type":37,"value":1916},{"type":32,"tag":101,"props":3090,"children":3092},{"class":103,"line":3091},30,[3093,3097],{"type":32,"tag":101,"props":3094,"children":3095},{"style":118},[3096],{"type":37,"value":2820},{"type":32,"tag":101,"props":3098,"children":3099},{"style":124},[3100],{"type":37,"value":156},{"type":32,"tag":101,"props":3102,"children":3104},{"class":103,"line":3103},31,[3105,3109],{"type":32,"tag":101,"props":3106,"children":3107},{"style":124},[3108],{"type":37,"value":2832},{"type":32,"tag":101,"props":3110,"children":3111},{"style":177},[3112],{"type":37,"value":2849},{"type":32,"tag":101,"props":3114,"children":3116},{"class":103,"line":3115},32,[3117,3121,3126],{"type":32,"tag":101,"props":3118,"children":3119},{"style":124},[3120],{"type":37,"value":2832},{"type":32,"tag":101,"props":3122,"children":3123},{"style":118},[3124],{"type":37,"value":3125},"dbt_utils.accepted_range",{"type":32,"tag":101,"props":3127,"children":3128},{"style":124},[3129],{"type":37,"value":156},{"type":32,"tag":101,"props":3131,"children":3133},{"class":103,"line":3132},33,[3134,3139,3143],{"type":32,"tag":101,"props":3135,"children":3136},{"style":118},[3137],{"type":37,"value":3138},"              min_value",{"type":32,"tag":101,"props":3140,"children":3141},{"style":124},[3142],{"type":37,"value":127},{"type":32,"tag":101,"props":3144,"children":3145},{"style":177},[3146],{"type":37,"value":3147},"\"'2020-01-01'\"\n",{"type":32,"tag":101,"props":3149,"children":3151},{"class":103,"line":3150},34,[3152,3157,3161],{"type":32,"tag":101,"props":3153,"children":3154},{"style":118},[3155],{"type":37,"value":3156},"              max_value",{"type":32,"tag":101,"props":3158,"children":3159},{"style":124},[3160],{"type":37,"value":127},{"type":32,"tag":101,"props":3162,"children":3163},{"style":177},[3164],{"type":37,"value":3165},"\"current_date()\"\n",{"type":32,"tag":33,"props":3167,"children":3168},{},[3169,3171,3177,3179,3185],{"type":37,"value":3170},"Команда ",{"type":32,"tag":52,"props":3172,"children":3174},{"className":3173},[],[3175],{"type":37,"value":3176},"dbt test",{"type":37,"value":3178}," выполняет эти проверки. Если есть ",{"type":32,"tag":52,"props":3180,"children":3182},{"className":3181},[],[3183],{"type":37,"value":3184},"order_total \u003C 0",{"type":37,"value":3186}," — build падает, в Slack идёт alert. Downstream exposures могут спокойно использовать этот контракт — качество данных обеспечивается в pipeline, не в BI tool.",{"type":32,"tag":33,"props":3188,"children":3189},{},[3190,3192,3198],{"type":37,"value":3191},"Custom тест добавляется просто: положить SQL файл в папку ",{"type":32,"tag":52,"props":3193,"children":3195},{"className":3194},[],[3196],{"type":37,"value":3197},"tests\u002F",{"type":37,"value":3199},". Пример: \"Каждый клиент должен иметь максимум одну активную подписку\":",{"type":32,"tag":91,"props":3201,"children":3203},{"className":658,"code":3202,"language":660,"meta":16,"style":16},"-- tests\u002Fassert_single_active_subscription.sql\nwith duplicate_subscriptions as (\n    select\n        customer_id,\n        count(*) as active_count\n    from {{ ref('fct_subscriptions') }}\n    where status = 'active'\n    group by 1\n    having count(*) > 1\n)\n\nselect * from duplicate_subscriptions\n",[3204],{"type":32,"tag":52,"props":3205,"children":3206},{"__ignoreMap":16},[3207,3215,3235,3242,3250,3278,3298,3319,3332,3366,3373,3380],{"type":32,"tag":101,"props":3208,"children":3209},{"class":103,"line":104},[3210],{"type":32,"tag":101,"props":3211,"children":3212},{"style":108},[3213],{"type":37,"value":3214},"-- tests\u002Fassert_single_active_subscription.sql\n",{"type":32,"tag":101,"props":3216,"children":3217},{"class":103,"line":114},[3218,3222,3227,3231],{"type":32,"tag":101,"props":3219,"children":3220},{"style":678},[3221],{"type":37,"value":681},{"type":32,"tag":101,"props":3223,"children":3224},{"style":124},[3225],{"type":37,"value":3226}," duplicate_subscriptions ",{"type":32,"tag":101,"props":3228,"children":3229},{"style":678},[3230],{"type":37,"value":691},{"type":32,"tag":101,"props":3232,"children":3233},{"style":124},[3234],{"type":37,"value":696},{"type":32,"tag":101,"props":3236,"children":3237},{"class":103,"line":136},[3238],{"type":32,"tag":101,"props":3239,"children":3240},{"style":678},[3241],{"type":37,"value":846},{"type":32,"tag":101,"props":3243,"children":3244},{"class":103,"line":146},[3245],{"type":32,"tag":101,"props":3246,"children":3247},{"style":124},[3248],{"type":37,"value":3249},"        customer_id,\n",{"type":32,"tag":101,"props":3251,"children":3252},{"class":103,"line":159},[3253,3257,3261,3265,3269,3273],{"type":32,"tag":101,"props":3254,"children":3255},{"style":130},[3256],{"type":37,"value":1306},{"type":32,"tag":101,"props":3258,"children":3259},{"style":124},[3260],{"type":37,"value":1311},{"type":32,"tag":101,"props":3262,"children":3263},{"style":678},[3264],{"type":37,"value":1316},{"type":32,"tag":101,"props":3266,"children":3267},{"style":124},[3268],{"type":37,"value":932},{"type":32,"tag":101,"props":3270,"children":3271},{"style":678},[3272],{"type":37,"value":691},{"type":32,"tag":101,"props":3274,"children":3275},{"style":124},[3276],{"type":37,"value":3277}," active_count\n",{"type":32,"tag":101,"props":3279,"children":3280},{"class":103,"line":183},[3281,3285,3289,3294],{"type":32,"tag":101,"props":3282,"children":3283},{"style":678},[3284],{"type":37,"value":1048},{"type":32,"tag":101,"props":3286,"children":3287},{"style":124},[3288],{"type":37,"value":1362},{"type":32,"tag":101,"props":3290,"children":3291},{"style":177},[3292],{"type":37,"value":3293},"'fct_subscriptions'",{"type":32,"tag":101,"props":3295,"children":3296},{"style":124},[3297],{"type":37,"value":738},{"type":32,"tag":101,"props":3299,"children":3300},{"class":103,"line":201},[3301,3305,3310,3314],{"type":32,"tag":101,"props":3302,"children":3303},{"style":678},[3304],{"type":37,"value":746},{"type":32,"tag":101,"props":3306,"children":3307},{"style":678},[3308],{"type":37,"value":3309}," status",{"type":32,"tag":101,"props":3311,"children":3312},{"style":678},[3313],{"type":37,"value":922},{"type":32,"tag":101,"props":3315,"children":3316},{"style":177},[3317],{"type":37,"value":3318}," 'active'\n",{"type":32,"tag":101,"props":3320,"children":3321},{"class":103,"line":219},[3322,3327],{"type":32,"tag":101,"props":3323,"children":3324},{"style":678},[3325],{"type":37,"value":3326},"    group by",{"type":32,"tag":101,"props":3328,"children":3329},{"style":130},[3330],{"type":37,"value":3331}," 1\n",{"type":32,"tag":101,"props":3333,"children":3334},{"class":103,"line":26},[3335,3340,3345,3349,3353,3357,3362],{"type":32,"tag":101,"props":3336,"children":3337},{"style":678},[3338],{"type":37,"value":3339},"    having",{"type":32,"tag":101,"props":3341,"children":3342},{"style":130},[3343],{"type":37,"value":3344}," count",{"type":32,"tag":101,"props":3346,"children":3347},{"style":124},[3348],{"type":37,"value":1311},{"type":32,"tag":101,"props":3350,"children":3351},{"style":678},[3352],{"type":37,"value":1316},{"type":32,"tag":101,"props":3354,"children":3355},{"style":124},[3356],{"type":37,"value":932},{"type":32,"tag":101,"props":3358,"children":3359},{"style":678},[3360],{"type":37,"value":3361},">",{"type":32,"tag":101,"props":3363,"children":3364},{"style":130},[3365],{"type":37,"value":3331},{"type":32,"tag":101,"props":3367,"children":3368},{"class":103,"line":253},[3369],{"type":32,"tag":101,"props":3370,"children":3371},{"style":124},[3372],{"type":37,"value":1094},{"type":32,"tag":101,"props":3374,"children":3375},{"class":103,"line":271},[3376],{"type":32,"tag":101,"props":3377,"children":3378},{"emptyLinePlaceholder":140},[3379],{"type":37,"value":143},{"type":32,"tag":101,"props":3381,"children":3382},{"class":103,"line":284},[3383,3387,3391,3395],{"type":32,"tag":101,"props":3384,"children":3385},{"style":678},[3386],{"type":37,"value":883},{"type":32,"tag":101,"props":3388,"children":3389},{"style":678},[3390],{"type":37,"value":709},{"type":32,"tag":101,"props":3392,"children":3393},{"style":678},[3394],{"type":37,"value":714},{"type":32,"tag":101,"props":3396,"children":3397},{"style":124},[3398],{"type":37,"value":3399}," duplicate_subscriptions\n",{"type":32,"tag":33,"props":3401,"children":3402},{},[3403],{"type":37,"value":3404},"Если этот запрос вернёт строки — тест падает. Когда test coverage переходит за 80%, количество data incident'ов падает — метрика Roibase за 2023: после 85% test coverage количество dashboard alert'ов от ошибок в данных снизилось на 60%.",{"type":32,"tag":40,"props":3406,"children":3408},{"id":3407},"pipeline-orchestration-и-production-deployment",[3409],{"type":37,"value":3410},"Pipeline orchestration и production deployment",{"type":32,"tag":33,"props":3412,"children":3413},{},[3414,3416,3422,3424,3430],{"type":37,"value":3415},"Если используешь dbt Cloud, настраиваешь scheduled job: каждый день в 04:00 запускается ",{"type":32,"tag":52,"props":3417,"children":3419},{"className":3418},[],[3420],{"type":37,"value":3421},"dbt build --select +fct_orders",{"type":37,"value":3423},". Для self-hosted в Airflow DAG добавляешь ",{"type":32,"tag":52,"props":3425,"children":3427},{"className":3426},[],[3428],{"type":37,"value":3429},"BashOperator",{"type":37,"value":3431}," с dbt команду. Благодаря incremental стратегии dbt 90 дней данных обрабатываются за 5 минут, full-refresh становится ненужным.",{"type":32,"tag":33,"props":3433,"children":3434},{},[3435,3437,3443],{"type":37,"value":3436},"CI\u002FCD процесс: открыл Pull Request — GitHub Actions запускает ",{"type":32,"tag":52,"props":3438,"children":3440},{"className":3439},[],[3441],{"type":37,"value":3442},"dbt build --select state:modified+",{"type":37,"value":3444}," — только изменённые модели и их downstream зависимости. Merge — deploy в production BigQuery dataset. dbt Slim CI сокращает build в PR с 40 минут (full build) до 3 минут для проекта с 200 моделями.",{"type":32,"tag":33,"props":3446,"children":3447},{},[3448,3450,3455],{"type":37,"value":3449},"В production ",{"type":32,"tag":52,"props":3451,"children":3453},{"className":3452},[],[3454],{"type":37,"value":2622},{"type":37,"value":3456}," output загружается в S3\u002FGCS как статический сайт. Документация версионируется — изменения в схеме модели видны в git history. Новый член команды читает на dbt docs сайте, как вычисляется метрика, нет tribal knowledge.",{"type":32,"tag":3458,"props":3459,"children":3460},"hr",{},[],{"type":32,"tag":33,"props":3462,"children":3463},{},[3464],{"type":37,"value":3465},"dbt + BigQuery — не единственный способ связать маркетинговые данные с механизмом принятия решений, но самый повторяемый, тестируемый, версионируем",{"type":32,"tag":3467,"props":3468,"children":3469},"style",{},[3470],{"type":37,"value":3471},"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":3473},[3474,3475,3476,3477,3478,3479],{"id":42,"depth":114,"text":45},{"id":617,"depth":114,"text":620},{"id":1730,"depth":114,"text":1733},{"id":2218,"depth":114,"text":2221},{"id":2663,"depth":114,"text":2666},{"id":3407,"depth":114,"text":3410},"markdown","content:ru:data:dbt-bigquery-modern-marketing-data-stack.md","content","ru\u002Fdata\u002Fdbt-bigquery-modern-marketing-data-stack.md","ru\u002Fdata\u002Fdbt-bigquery-modern-marketing-data-stack","md",1785276288971]