BizSpring.ai

์ง€์‹์„ผํ„ฐ / ๋ ˆํผ๋Ÿฐ์Šค

๐Ÿ“ JUVIS UTM ํ’€ํผ๋„ + ์ง€์ ๋ธ”๋กœ๊ทธ ํƒญ ์„ค๊ณ„ v1.0 (์˜ฅ๊ฒฝํ™” ์ƒ๋ฌด ์š”์ฒญ)

# JUVIS UTM ํ’€ํผ๋„ + ์ง€์ ๋ธ”๋กœ๊ทธ ํƒญ ์„ค๊ณ„ v1.0 > ์ž‘์„ฑ: 2026-04-20 | DATA_ENG_BQ | Phase: ๐Ÿ“‹ PLAN (G1 ๋Œ€๊ธฐ) > ์š”์ฒญ: ์˜ฅ๊ฒฝํ™” ์ƒ๋ฌด (Asana 1210900334445452) > ์ถœ์ฒ˜: ๋‹ค์ธ  ๊ด‘๊ณ ๋Œ€ํ–‰์‚ฌ ์š”๊ตฌ์‚ฌํ•ญ 2๊ฑด + ์ฅฌ๋น„์Šค UT

ํ•ต์‹ฌ ์š”์•ฝ

    # JUVIS UTM ํ’€ํผ๋„ + ์ง€์ ๋ธ”๋กœ๊ทธ ํƒญ ์„ค๊ณ„ v1.0

    > ์ž‘์„ฑ: 2026-04-20 | DATA_ENG_BQ | Phase: ๐Ÿ“‹ PLAN (G1 ๋Œ€๊ธฐ)

    > ์š”์ฒญ: ์˜ฅ๊ฒฝํ™” ์ƒ๋ฌด (Asana 1210900334445452)

    > ์ถœ์ฒ˜: ๋‹ค์ธ  ๊ด‘๊ณ ๋Œ€ํ–‰์‚ฌ ์š”๊ตฌ์‚ฌํ•ญ 2๊ฑด + ์ฅฌ๋น„์Šค UTM ์ฝ”๋”ฉ ๊ฐ€์ด๋“œ PDF

    ---

    0. ์š”๊ตฌ์‚ฌํ•ญ ์š”์•ฝ (์˜ฅ๊ฒฝํ™” ์ƒ๋ฌด 2026-04-20)

    ๊ด‘๊ณ  ๋Œ€ํ–‰์‚ฌ(๋‹ค์ธ ) ์š”๊ตฌ 2๊ฑด โ€” ๊ธฐ์—ฌ๋ชจ๋ธ ๋ฏธ์ ์šฉ

    ์š”๊ตฌ โ‘ : UTM ๊ธฐ์ค€ ํ’€ํผ๋„ ๋ถ„์„

    ์š”๊ตฌ โ‘ก: ์ง€์  ๋ธ”๋กœ๊ทธ ์ฝ˜ํ…์ธ  ์„ฑ๊ณผ ํƒญ (์‹ ๊ทœ)

    ์ œ์•ฝ์‚ฌํ•ญ

    ---

    1. UTM ์ฝ”๋”ฉ ๊ฐ€์ด๋“œ (์ฅฌ๋น„์Šค ์ œ๊ณต PDF ๋ฐ˜์˜)

    1-1. ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค๊ณ„์•ˆ

    ํŒŒ๋ผ๋ฏธํ„ฐ๊ถŒ์žฅ ๊ฐ’์ •์˜/ํ™œ์šฉ
    utm_sourceblog์œ ์ž… ์ฑ„๋„ ๊ตฌ๋ถ„ (๋„ค์ด๋ฒ„ ๋ธ”๋กœ๊ทธ, ํ‹ฐ์Šคํ† ๋ฆฌ ๋“ฑ)
    utm_mediumbranch_post์˜์—…ํŒ€ ์ง€์  ๊ฒŒ์‹œ๋ฌผ ๋ช…์‹œ (๋ณธ์‚ฌ ๊ด‘๊ณ ์™€ ๊ตฌ๋ถ„)
    utm_campaignjv_gangnam ๋“ฑ[ํ•ต์‹ฌ] ๊ฐ ์ง€์ ์˜ ๊ณ ์œ  ์˜๋ฌธ ์ฝ”๋“œ
    utm_termsuccess, info, program, event, daily์ฝ˜ํ…์ธ  ์„ฑ๊ฒฉ ๊ตฌ๋ถ„
    utm_content260415_manager_cgh์ž‘์„ฑ์ผ์ž_์ง์ฑ…_์ด๋‹ˆ์…œ

    1-2. ์ง€์  ์ฝ”๋“œ ๋งคํ•‘ (42๊ฐœ)

    ์„œ์šธ (19๊ฐœ)

    ์ง€์ ์ฝ”๋“œ์ง€์ ์ฝ”๋“œ
    ๊ฐ•๋‚จ์ jv_gangnam๋งˆํฌ์ jv_mapo
    ์†กํŒŒ์ jv_songpa๊ฐ•์„œ์ jv_gangseo
    ์ž ์‹ค์ jv_jamsil์‹œ์ฒญ์ jv_sicheong
    ๋…ธ์›์ jv_nowon๊ด€์•…์ jv_gwanak
    ์™•์‹ญ๋ฆฌ์ jv_wangsimni์„ฑ๋ถ์ jv_seongbuk
    ์‚ผ์„ฑ๋™์ jv_samseong๋ฌต๋™์ jv_mukdong
    ๋ชฉ๋™์ jv_mokdong๋ฌธ์ •์ (6๊ทธ๋ฃน)jv_munjeong
    ์—ฌ์˜๋„์ jv_yeouido๋„๊ณก์ (6๊ทธ๋ฃน)jv_dogok
    ์„ฑ์ˆ˜์ jv_seongsuโ€”โ€”
    ์€ํ‰์ jv_eunpyeongโ€”โ€”
    ์„œ์ดˆ์ jv_seochoโ€”โ€”

    ๊ฒฝ๊ธฐ/์ธ์ฒœ (10๊ฐœ)

    ์ผ์‚ฐ jv_ilsan / ํ‰์ดŒ jv_pyeongchon / ๋ถ„๋‹น jv_bundang / ์†ก๋„ jv_songdo / ์ˆ˜์›์˜ํ†ต jv_suwon_yt / ์ˆ˜์›์ธ๊ณ„ jv_suwon_ig / ์ˆ˜์ง€๊ตฌ์ฒญ jv_suji / ๋ถ€์ฒœ jv_bucheon / ์ธ์ฒœ jv_incheon / ์˜์ •๋ถ€ jv_uijeongbu

    ์ถฉ์ฒญ/์ „๋ผ (7๊ฐœ)

    ์ˆœ์ฒœ jv_suncheon / ์ „์ฃผ jv_jeonju / ๋Œ€์ „๋‘”์‚ฐ jv_daejeon_ds / ๋Œ€์ „์œ ์„ฑ jv_daejeon_ys / ๊ด‘์ฃผ๊ด‘์ฒœ jv_gwangju_gc / ๊ด‘์ฃผ์ˆ˜์™„ jv_gwangju_sw / ์ฒญ์ฃผ jv_cheongju

    ๊ฒฝ์ƒ (6๊ฐœ)

    ์šธ์‚ฐ jv_ulsan / ๋ถ€์‚ฐ์„œ๋ฉด jv_busan_sm / ๋ถ€์‚ฐ์„ผํ…€์‹œํ‹ฐ jv_busan_ct / ๋Œ€๊ตฌ์ฃฝ์ „ jv_daegu_jj / ๋Œ€๊ตฌ๋ฒ”์–ด jv_daegu_bo / ์ฐฝ์› jv_changwon

    1-3. utm_term 5์ข…

    ๊ฐ’์ฝ˜ํ…์ธ  ํ…Œ๋งˆ๋ถ„์„ ๋ชฉ์ 
    success์„ฑ๊ณต ํ›„๊ธฐ (๊ฐ๋Ÿ‰ ์ „/ํ›„, ์ธํ„ฐ๋ทฐ)์‹ ๋ขฐ๋„ ๊ธฐ๋ฐ˜ ๊ฒฐ์ œ ์œ ๋„ ํšจ๊ณผ ๋ถ„์„
    info์ •๋ณด์„ฑ ํŒ (์‹๋‹จ/์›๋ฆฌ/์šด๋™๋ฒ•)์ •๋ณด ๊ฒ€์ƒ‰ ์œ ์ž…์˜ ์ƒ๋‹ด ์ „ํ™˜์œจ
    programํ”„๋กœ๊ทธ๋žจ ์†Œ๊ฐœ (๊ธฐ๊ธฐ/ํ‘ธ๋“œ/์ปจ์„คํŒ…)์ƒํ’ˆ๋ณ„ ๊ด€์‹ฌ๋„ ์ง์ ‘ ์ธก์ •
    event์ด๋ฒคํŠธ/ํ˜œํƒ (์›”๋ณ„ ํ”„๋กœ๋ชจ์…˜)๋‹จ๊ธฐ ํ”„๋กœ๋ชจ์…˜ ๋ฐ˜์‘ ์†๋„
    daily์ง€์  ์ผ์ƒ (๋งค๋‹ˆ์ € ์†Œ๊ฐœ/๋ถ„์œ„๊ธฐ)์žฅ๊ธฐ ๋ธŒ๋žœ๋”ฉ์˜ ๊ฒฐ์ œ ์˜ํ–ฅ

    1-4. utm_content ๊ทœ์น™

    ---

    2. ํ˜„ํ™ฉ ๋ถ„์„ โ€” ์ฆ‰์‹œ ํ™œ์šฉ ๊ฐ€๋Šฅํ•œ ์ธํ”„๋ผ

    2-1. ํ…Œ์ด๋ธ” โ€” lift_utm_attribution_v2

    ๊ฒฐ๋ก : ์‹ ๊ทœ ํ…Œ์ด๋ธ” ๋ถˆํ•„์š”. ํ˜„์žฌ ๊ตฌ์กฐ์— 5๊ฐœ UTM ์ฐจ์› + ํ’€ํผ๋„ ์ง€ํ‘œ๊ฐ€ ์ด๋ฏธ ๋ชจ๋‘ ์กด์žฌ.

    ์ปฌ๋Ÿผ ๊ทธ๋ฃน๋ณด์œ  ํ•„๋“œ
    UTM 5์ฐจ์›utm_source, utm_medium, utm_campaign, utm_term, utm_content
    ํผ๋„ ์ง€ํ‘œlanding, active_user, g6(๋ฌธ์˜), g7(์ƒ๋‹ด์˜ˆ์•ฝ), odr_count(๊ฒฐ์ œ), order_amount(๋งค์ถœ)
    ๋ถ€๊ฐ€stat_date, attribution_model, g1~g10, g6_user, pageview, landing_user/session
    ๊ทœ๋ชจ228MB, ๊ธฐ๊ฐ„๋ณ„ ํŒŒํ‹ฐ์…˜ ์—†์Œ(๋‹จ์ˆœ ํ…Œ์ด๋ธ”)

    2-2. ๊ธฐ์กด RPC

    2-3. ๊ฐญ ๋ถ„์„

    ์š”๊ตฌ๊ธฐ์กด ๋Œ€์‘์‹ ๊ทœ ํ•„์š”
    UTM 5์ฐจ์› ๋“œ๋ฆด๋‹ค์šดโŒ (source/medium๋งŒ ๋ฐ˜ํ™˜)RPC ํ™•์žฅ ๋˜๋Š” ์‹ ๊ทœ
    ํ’€ํผ๋„ ์ง€ํ‘œ 6๊ฐœโœ… ๋ชจ๋“  ์ปฌ๋Ÿผ ์กด์žฌ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ
    ์†Œ์žฌ ์ธ๋„ค์ผโš ๏ธ ga4_get_creative_meta RPC ์กด์žฌ(CreativePathsTab ์‚ฌ์šฉ)์žฌ์‚ฌ์šฉ
    ์ง€์ (campaign) ํ•„ํ„ฐโŒ ํ”„๋ก ํŠธ ํ•„ํ„ฐ ์—†์Œํ”„๋ก ํŠธ ์ถ”๊ฐ€
    ์ž‘์„ฑ์ž(content) ์ง‘๊ณ„โŒRPC + ํ”„๋ก ํŠธ

    ---

    3. ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„

    [๋ฐ์ดํ„ฐ ๋ ˆ์ด์–ด]
      BQ gp-juvis-107339 mart_tables (์›๋ณธ)
        โ†“ FDW
      Supabase.lift_utm_attribution_v2 (๊ธฐ์กด, ์žฌ์‚ฌ์šฉ)
        โ”œโ”€ attribution_model='last' ๋‹จ์ผ ์‚ฌ์šฉ
    
    [RPC ๋ ˆ์ด์–ด] โ€” ์‹ ๊ทœ 2๊ฐœ
      ga4_get_utm_fullfunnel(client_code, date_from, date_to, dims[])
        โ†’ dims๋ณ„ ๊ทธ๋ฃนํ•‘์œผ๋กœ ํ’€ํผ๋„ 6๊ฐœ ์ง‘๊ณ„ ๋ฐ˜ํ™˜
        โ†’ dims = ['utm_source','utm_medium','utm_campaign','utm_term','utm_content']
           ์ค‘ ์š”์ฒญํ•œ ์กฐํ•ฉ์œผ๋กœ GROUP BY
      
      ga4_get_branch_blog_perf(client_code, date_from, date_to, branch?, term?, author?)
        โ†’ utm_medium='branch_post' ํ•„ํ„ฐ
        โ†’ ์ง€์ (campaign) ร— ์ฝ˜ํ…์ธ ์œ ํ˜•(term) ร— ์ž‘์„ฑ์ž(content) 3์ถ• ๋“œ๋ฆด๋‹ค์šด
        โ†’ 5๊ฐœ ์ง€ํ‘œ ๋ฐ˜ํ™˜ (landing, active_user, g6, odr_count, order_amount)
    
      ga4_get_creative_meta(client_code) โ€” ๊ธฐ์กด ์žฌ์‚ฌ์šฉ (์ธ๋„ค์ผ์šฉ)
    
    [ํ”„๋ก ํŠธ ๋ ˆ์ด์–ด] โ€” ์‹ ๊ทœ ํƒญ 2๊ฐœ
      โ”Œโ”€โ”€ ์›์ฒœ ๋ฐ์ดํ„ฐ ํƒ์ƒ‰ (๊ธฐ์กด ๊ทธ๋ฃน)
      โ”‚   โ”œโ”€โ”€ ์ผ๋ณ„ KPI ํŠธ๋ Œ๋“œ (๊ธฐ์กด)
      โ”‚   โ”œโ”€โ”€ ์ „ํ™˜ ํผ๋„ ๋ถ„์„ (๊ธฐ์กด)
      โ”‚   โ”œโ”€โ”€ ๋งค์ฒด๋ณ„ ์„ฑ๊ณผ (๊ธฐ์กด)
      โ”‚   โ”œโ”€โ”€ ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ ๋น„๊ต (๊ธฐ์กด)
      โ”‚   โ”œโ”€โ”€ UTM ํ’€ํผ๋„ ํƒ์ƒ‰ โญ NEW
      โ”‚   โ””โ”€โ”€ ์ง€์  ๋ธ”๋กœ๊ทธ ์„ฑ๊ณผ โญ NEW
      
      ๊ฐ ํƒญ์€ AiInsightSection ๋ถˆํฌํ•จ (๊ธฐ์—ฌ๋ชจ๋ธ ๋ฏธ์ ์šฉ์ด๋ฏ€๋กœ AI ์ธ์‚ฌ์ดํŠธ ๋ถˆํ•„์š”)

    ---

    4. ์‹ ๊ทœ ํƒญ โ‘  UTM ํ’€ํผ๋„ ํƒ์ƒ‰

    4-1. UX ์™€์ด์–ดํ”„๋ ˆ์ž„

    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚ UTM ํ’€ํผ๋„ ํƒ์ƒ‰                          ๊ธฐ๊ฐ„: [2026-04-01 ~ 04-20] โ”‚
    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
    โ”‚ ๋“œ๋ฆด๋‹ค์šด ์ถ• (๋‹ค์ค‘์„ ํƒ):                                      โ”‚
    โ”‚ [โœ“ Source] [โœ“ Medium] [  Campaign] [  Term] [  Content]    โ”‚
    โ”‚                                                              โ”‚
    โ”‚ ํผ๋„ ์š”์•ฝ ๋ฐ” (์ „์ฒด)                                          โ”‚
    โ”‚  ์œ ์ž…(54,904) โ”€โ”€โ–ถ ํ™œ์„ฑ์‚ฌ์šฉ์ž(48,231) โ”€โ”€โ–ถ ๋ฌธ์˜(1,344) โ”€โ”€โ–ถ      โ”‚
    โ”‚  ์ƒ๋‹ด์˜ˆ์•ฝ(198) โ”€โ”€โ–ถ ๊ฒฐ์ œ(79)    ๋งค์ถœ: โ‚ฉ441,494,700           โ”‚
    โ”‚                                                              โ”‚
    โ”‚ ๋งค์ฒด ร— ํผ๋„ ํžˆํŠธ๋งต                                           โ”‚
    โ”‚ source/medium      ์œ ์ž…      ํ™œ์„ฑ    ๋ฌธ์˜    ์ƒ๋‹ด์˜ˆ์•ฝ  ๊ฒฐ์ œ  ๋งค์ถœ โ”‚
    โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚
    โ”‚ (not set)          131,936   54,904  989     43      79   โ‚ฉ441M โ”‚
    โ”‚ Meta / feed         โ€ฆ                                       โ”‚
    โ”‚ Naver / BSA_MO      โ€ฆ                                       โ”‚
    โ”‚                                                              โ”‚
    โ”‚ [๐Ÿ”ฝ Naver/BSA_MO ํ–‰ ํด๋ฆญ โ†’ Campaign ๋“œ๋ฆด๋‹ค์šด]                โ”‚
    โ”‚                                                              โ”‚
    โ”‚ Term ์ƒ์„ธ (์†Œ์žฌ ์ธ๋„ค์ผ ํฌํ•จ)                                 โ”‚
    โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”           โ”‚
    โ”‚ โ”‚ [์ธ๋„ค์ผ]  โ”‚ utm_term     โ”‚ ์œ ์ž…  โ”‚ ๋ฌธ์˜  โ”‚ ๊ฒฐ์ œ โ”‚           โ”‚
    โ”‚ โ”‚ ๐Ÿ“ท100x100 โ”‚ tiktok_tcpa  โ”‚ 12,070โ”‚ 2     โ”‚ 2    โ”‚           โ”‚
    โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”˜           โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

    4-2. ๊ธฐ๋Šฅ ์š”๊ตฌ

    4-3. RPC ์„ค๊ณ„

    CREATE OR REPLACE FUNCTION ga4_get_utm_fullfunnel(
      p_client_code varchar,
      p_date_from date,
      p_date_to date,
      p_dims text[] DEFAULT ARRAY['utm_source','utm_medium']
    )
    RETURNS jsonb
    LANGUAGE plpgsql
    SECURITY DEFINER
    AS $$
    DECLARE
      v_result jsonb;
      v_dim_cols text;
      v_group_cols text;
    BEGIN
      -- ํ—ˆ์šฉ dims๋งŒ ํ•„ํ„ฐ๋ง (SQL injection ๋ฐฉ์–ด)
      SELECT string_agg(quote_ident(d), ', '), string_agg(quote_ident(d), ', ')
      INTO v_dim_cols, v_group_cols
      FROM unnest(p_dims) d
      WHERE d IN ('utm_source','utm_medium','utm_campaign','utm_term','utm_content');
      
      -- ๋™์  SQL๋กœ GROUP BY ์‹คํ–‰
      EXECUTE format($sql$
        SELECT jsonb_build_object(
          'dims', %L::jsonb,
          'date_range', jsonb_build_object('from', %L::text, 'to', %L::text),
          'client_code', %L,
          'totals', jsonb_build_object(
            'landing', COALESCE(SUM(landing), 0),
            'active_user', COALESCE(SUM(active_user), 0),
            'g6', COALESCE(SUM(g6), 0),
            'g7', COALESCE(SUM(g7), 0),
            'odr_count', COALESCE(SUM(odr_count), 0),
            'order_amount', COALESCE(SUM(order_amount), 0)
          ),
          'rows', COALESCE(jsonb_agg(row_data ORDER BY landing_sum DESC), '[]'::jsonb)
        )
        FROM (
          SELECT 
            jsonb_build_object(
              %s,
              'landing', SUM(landing),
              'active_user', SUM(active_user),
              'g6', SUM(g6),
              'g7', SUM(g7),
              'odr_count', SUM(odr_count),
              'order_amount', SUM(order_amount)
            ) AS row_data,
            SUM(landing) AS landing_sum
          FROM lift_utm_attribution_v2
          WHERE client_code = %L
            AND stat_date BETWEEN %L AND %L
            AND attribution_model = 'last'
          GROUP BY %s
        ) t
      $sql$,
        to_jsonb(p_dims), p_date_from, p_date_to, p_client_code,
        -- dim key ํŽ˜์–ด ์ƒ์„ฑ
        (SELECT string_agg(quote_literal(d)||', '||quote_ident(d), ', ')
         FROM unnest(p_dims) d
         WHERE d IN ('utm_source','utm_medium','utm_campaign','utm_term','utm_content')),
        p_client_code, p_date_from, p_date_to, v_group_cols
      ) INTO v_result;
      
      RETURN v_result;
    END;
    $$;

    ํ•ต์‹ฌ ์•ˆ์ „์žฅ์น˜:

    4-4. ์‹ ๊ทœ ํŒŒ์ผ: UtmFullFunnelTab.tsx

    ---

    5. ์‹ ๊ทœ ํƒญ โ‘ก ์ง€์  ๋ธ”๋กœ๊ทธ ์ฝ˜ํ…์ธ  ์„ฑ๊ณผ

    5-1. UX ์™€์ด์–ดํ”„๋ ˆ์ž„

    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚ ์ง€์  ๋ธ”๋กœ๊ทธ ์ฝ˜ํ…์ธ  ์„ฑ๊ณผ          ๊ธฐ๊ฐ„: [2026-04-01 ~ 04-20] โ”‚
    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
    โ”‚ ํ•„ํ„ฐ                                                         โ”‚
    โ”‚ ์ง€์ : [์ „์ฒด 42๊ฐœ โ–ผ] ์ฝ˜ํ…์ธ ์œ ํ˜•: [์ „์ฒด โ–ผ] ์ž‘์„ฑ์ž: [์ „์ฒด โ–ผ]    โ”‚
    โ”‚                                                              โ”‚
    โ”‚ ์ „์ฒด ์š”์•ฝ                                                    โ”‚
    โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                    โ”‚
    โ”‚ โ”‚ ์œ ์ž…  โ”‚ํ™œ์„ฑ์‚ฌ์šฉ์žโ”‚์ด์ƒ๋‹ด์‹ ์ฒญโ”‚ ๊ฒฐ์ œ  โ”‚ ๊ฒฐ์ œ์ˆ˜์ต โ”‚                    โ”‚
    โ”‚ โ”‚ 3,241 โ”‚ 2,876 โ”‚ 47    โ”‚ 12   โ”‚ โ‚ฉ68M   โ”‚                    โ”‚
    โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                    โ”‚
    โ”‚                                                              โ”‚
    โ”‚ [์ง€์ ๋ณ„] ํƒญ โ”‚ [์ฝ˜ํ…์ธ ์œ ํ˜•๋ณ„] ํƒญ โ”‚ [์ž‘์„ฑ์ž๋ณ„] ํƒญ โ”‚ [์ƒ์„ธ] ํƒญ  โ”‚
    โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚
    โ”‚ ์ง€์  (campaign)   ์œ ์ž…  ํ™œ์„ฑ  ๋ฌธ์˜  ๊ฒฐ์ œ  ๋งค์ถœ  CVR          โ”‚
    โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚
    โ”‚ ๊ฐ•๋‚จ์             812   721   14    4     โ‚ฉ22M  1.7%        โ”‚
    โ”‚ ๋ถ„๋‹น์             543   489   9     3     โ‚ฉ16M  1.7%        โ”‚
    โ”‚ โ€ฆ                                                            โ”‚
    โ”‚                                                              โ”‚
    โ”‚ [์ „์ฒด ํ…Œ์ด๋ธ” CSV ๋‹ค์šด๋กœ๋“œ]                                   โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

    5-2. ๊ธฐ๋Šฅ ์š”๊ตฌ

    - ์ง€์  ๋“œ๋กญ๋‹ค์šด: ์ง€์ ์ฝ”๋“œ+ํ•œ๊ธ€๋ช… ๋งคํ•‘ ํ…Œ์ด๋ธ”๋กœ ํ‘œ์‹œ ("jv_gangnam โ†’ ๊ฐ•๋‚จ์ ")

    - ์ฝ˜ํ…์ธ ์œ ํ˜• ๋“œ๋กญ๋‹ค์šด: success/info/program/event/daily 5์ข…

    - ์ž‘์„ฑ์ž ๋“œ๋กญ๋‹ค์šด: DB์—์„œ distinct utm_content ์ถ”์ถœ

    1. ์ง€์ ๋ณ„: campaign์œผ๋กœ ๊ทธ๋ฃนํ•‘, ์ „ ์ง€ํ‘œ ํ‘œ์‹œ

    2. ์ฝ˜ํ…์ธ ์œ ํ˜•๋ณ„: term์œผ๋กœ ๊ทธ๋ฃนํ•‘

    3. ์ž‘์„ฑ์ž๋ณ„: content๋กœ ๊ทธ๋ฃนํ•‘

    4. ์ƒ์„ธ(๊ต์ฐจ): campaign ร— term ร— content ์ „์ฒด ๊ต์ฐจ

    5-3. RPC ์„ค๊ณ„

    CREATE OR REPLACE FUNCTION ga4_get_branch_blog_perf(
      p_client_code varchar,
      p_date_from date,
      p_date_to date,
      p_group_by text DEFAULT 'campaign',   -- campaign | term | content | all
      p_branch text DEFAULT NULL,           -- ํ•„ํ„ฐ: utm_campaign ๊ฐ’
      p_term text DEFAULT NULL,             -- ํ•„ํ„ฐ: utm_term ๊ฐ’
      p_author text DEFAULT NULL            -- ํ•„ํ„ฐ: utm_content ๊ฐ’
    )
    RETURNS jsonb
    LANGUAGE plpgsql
    SECURITY DEFINER
    AS $$
    DECLARE
      v_result jsonb;
      v_group_col text;
    BEGIN
      -- ๊ทธ๋ฃนํ•‘ ์ปฌ๋Ÿผ ๊ฒฐ์ • (whitelist)
      v_group_col := CASE p_group_by
        WHEN 'campaign' THEN 'utm_campaign'
        WHEN 'term' THEN 'utm_term'
        WHEN 'content' THEN 'utm_content'
        WHEN 'all' THEN 'utm_campaign, utm_term, utm_content'
        ELSE 'utm_campaign'
      END;
      
      EXECUTE format($sql$
        WITH base AS (
          SELECT utm_campaign, utm_term, utm_content,
                 landing, active_user, g6, odr_count, order_amount
          FROM lift_utm_attribution_v2
          WHERE client_code = %L
            AND stat_date BETWEEN %L AND %L
            AND attribution_model = 'last'
            AND utm_medium = 'branch_post'
            AND (%L IS NULL OR utm_campaign = %L)
            AND (%L IS NULL OR utm_term = %L)
            AND (%L IS NULL OR utm_content = %L)
        )
        SELECT jsonb_build_object(
          'totals', jsonb_build_object(
            'landing', COALESCE(SUM(landing), 0),
            'active_user', COALESCE(SUM(active_user), 0),
            'g6', COALESCE(SUM(g6), 0),
            'odr_count', COALESCE(SUM(odr_count), 0),
            'order_amount', COALESCE(SUM(order_amount), 0)
          ),
          'rows', (
            SELECT COALESCE(jsonb_agg(
              jsonb_build_object(
                %s,
                'landing', landing_sum,
                'active_user', active_user_sum,
                'g6', g6_sum,
                'odr_count', odr_count_sum,
                'order_amount', order_amount_sum,
                'cvr', CASE WHEN landing_sum > 0 
                  THEN ROUND((odr_count_sum::numeric / landing_sum) * 100, 2) 
                  ELSE 0 END
              ) ORDER BY landing_sum DESC
            ), '[]'::jsonb)
            FROM (
              SELECT %s,
                     SUM(landing) AS landing_sum,
                     SUM(active_user) AS active_user_sum,
                     SUM(g6) AS g6_sum,
                     SUM(odr_count) AS odr_count_sum,
                     SUM(order_amount) AS order_amount_sum
              FROM base
              GROUP BY %s
            ) g
          )
        )
        FROM base
      $sql$,
        p_client_code, p_date_from, p_date_to,
        p_branch, p_branch, p_term, p_term, p_author, p_author,
        -- jsonb ํ‚ค-๊ฐ’ ํŽ˜์–ด
        '...',  -- group_by์— ๋”ฐ๋ผ ๋™์  ์ƒ์„ฑ
        v_group_col, v_group_col
      ) INTO v_result;
      
      RETURN v_result;
    END;
    $$;

    5-4. ๋ณด์กฐ ํ…Œ์ด๋ธ”: lift_juvis_branch_mapping

    CREATE TABLE lift_juvis_branch_mapping (
      branch_code varchar(50) PRIMARY KEY,       -- 'jv_gangnam'
      branch_name varchar(50) NOT NULL,          -- '๊ฐ•๋‚จ์ '
      region varchar(20) NOT NULL,               -- '์„œ์šธ'|'๊ฒฝ๊ธฐ/์ธ์ฒœ'|'์ถฉ์ฒญ/์ „๋ผ'|'๊ฒฝ์ƒ'
      is_active boolean DEFAULT true,
      created_at timestamptz DEFAULT now()
    );
    
    -- 42๊ฐœ ์ง€์  INSERT (UTM ์ฝ”๋”ฉ ๊ฐ€์ด๋“œ ๊ธฐ์ค€)

    5-5. ์‹ ๊ทœ ํŒŒ์ผ: BranchBlogTab.tsx

    ---

    6. ํ”„๋ก ํŠธ ๋ผ์šฐํŒ…

    6-1. ๋ฉ”๋‰ด ํŠธ๋ฆฌ ํ™•์žฅ

    ์›์ฒœ ๋ฐ์ดํ„ฐ ํƒ์ƒ‰ (๊ธฐ์กด ๊ทธ๋ฃน, ํŽผ์นจ)
      โ”œโ”€โ”€ ์ผ๋ณ„ KPI ํŠธ๋ Œ๋“œ
      โ”œโ”€โ”€ ์ „ํ™˜ ํผ๋„ ๋ถ„์„
      โ”œโ”€โ”€ ๋งค์ฒด๋ณ„ ์„ฑ๊ณผ
      โ”œโ”€โ”€ ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ ๋น„๊ต
      โ”œโ”€โ”€ UTM ํ’€ํผ๋„ ํƒ์ƒ‰         โญ NEW
      โ””โ”€โ”€ ์ง€์  ๋ธ”๋กœ๊ทธ ์„ฑ๊ณผ        โญ NEW (JUVIS์—์„œ๋งŒ ํ‘œ์‹œ)

    6-2. ํ…Œ๋„ŒํŠธ ์กฐ๊ฑด๋ถ€ ํ‘œ์‹œ

    ---

    7. ์ž‘์—… ์‚ฐ์ •

    ์ž‘์—…๋‹ด๋‹น๊ณต์ˆ˜
    โ‘  BranchMapping ํ…Œ์ด๋ธ” ์ƒ์„ฑ + 42๊ฐœ INSERT์ฐฐ์Šค0.5์ผ
    โ‘ก ga4_get_utm_fullfunnel RPC ๊ฐœ๋ฐœ+ํ…Œ์ŠคํŠธ์ฐฐ์Šค1์ผ
    โ‘ข ga4_get_branch_blog_perf RPC ๊ฐœ๋ฐœ+ํ…Œ์ŠคํŠธ์ฐฐ์Šค1์ผ
    โ‘ฃ UtmFullFunnelTab.tsx ํ”„๋ก ํŠธ (Lovable)Claude1์ผ
    โ‘ค BranchBlogTab.tsx ํ”„๋ก ํŠธ (Lovable)Claude1์ผ
    โ‘ฅ ๋ฉ”๋‰ด ๋ผ์šฐํŒ… + config show_branch_blogClaude0.3์ผ
    โ‘ฆ UTM ์ฝ”๋”ฉ ๊ฐ€์ด๋“œ Asana ์ฒจ๋ถ€ + ๋‹ค์ธ  ๊ณต์œ ์˜ฅ๊ฒฝํ™”/์ฐฐ์Šค0.2์ผ
    โ‘ง ๊ฒ€์ฆ (๋ธŒ๋ผ์šฐ์ €, ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ)์ฐฐ์Šค0.5์ผ
    ํ•ฉ๊ณ„์•ฝ 5.5์ผ(MD)

    ---

    8. ๋ฆฌ์Šคํฌ & ๊ฒ€ํ† ์‚ฌํ•ญ

    ๐Ÿšจ ๋ฐ์ดํ„ฐ ์กด์žฌ์„ฑ ํ™•์ธ ํ•„์š”

    โš ๏ธ ์ธ๋„ค์ผ ๋งคํ•‘ ๋ฒ”์œ„

    โš ๏ธ ์ง€์  ์ฝ”๋“œ ํ‘œ์ค€ํ™”

    โš ๏ธ JUVIS ๋ธ”๋กœ๊ทธ ๋งˆ์ผ€ํŒ… ํ™•์‚ฐ ์ผ์ •

    ---

    9. G1 ๊ฒฐ์ • ํ•„์š” ์‚ฌํ•ญ

    ์ฐฐ์Šค ์Šน์ธ ํ•„์š” ํ•ญ๋ชฉ 4๊ฐ€์ง€:

    Q1. ๋ฐ์ดํ„ฐ ์กด์žฌ์„ฑ ํ™•์ธ

    ํ˜„์žฌ branch_post medium ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š”์ง€ ๋จผ์ € ํ™•์ธํ•˜๊ณ , 0๊ฑด์ด๋ฉด ๋‹ค์ธ ์— "ํƒœ๊น… ๊ฐ€์ด๋“œ ๋ฐฐํฌ ํ›„ ๋Œ€์‹œ๋ณด๋“œ ์˜คํ”ˆ" ์ˆœ์„œ๋กœ ํ• ๊นŒ์š”, ์•„๋‹ˆ๋ฉด UI ๋จผ์ € ๋งŒ๋“ค๊นŒ์š”?

    Q2. ์ธ๋„ค์ผ ์ฒ˜๋ฆฌ

    ๋ธ”๋กœ๊ทธ ์ฝ˜ํ…์ธ ๋Š” ์ธ๋„ค์ผ์ด ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€๋ฐ:

    Q3. ๊ตฌํ˜„ ์ˆœ์„œ

    Q4. ๊ธฐ์กด "๋งค์ฒด๋ณ„ ์„ฑ๊ณผ" ํƒญ๊ณผ์˜ ๊ด€๊ณ„

    "์›์ฒœ ๋ฐ์ดํ„ฐ ํƒ์ƒ‰ > ๋งค์ฒด๋ณ„ ์„ฑ๊ณผ" ํƒญ๊ณผ ์‹ ๊ทœ "UTM ํ’€ํผ๋„ ํƒ์ƒ‰"์ด ๊ฒน์น  ์ˆ˜ ์žˆ์Œ.

    ์ถ”์ฒœ์•ˆ: Q1=A(๋ฐ์ดํ„ฐ ๋จผ์ € ํ™•์ธ), Q2=C(์ ์ง„์ ), Q3=C(๋ณ‘๋ ฌ), Q4=A(์—ญํ•  ๋ถ„๋ฆฌ)

    ---

    10. ์—ฐ๊ด€ ๋ฌธ์„œ

    ๋‹ค๋ฅธ ํ‘œํ˜„: Markdown ยท JSON ยท ์ตœ์ข… ๊ฐฑ์‹  2026-08-24