
    SiX"              
          d Z ddlZddlZddlZddlZddlmZmZmZm	Z	m
Z
 ddlmZmZ 	 ddlmZ ddlmZmZmZmZ dZd	Zd
ZdededefdZdee
eef      deeeef      fdZdee
eeef      deeeeef   f   fdZdeeeef      deeeeef   f   dee   fdZdeeeef      fdZ dee
eef      dee
eeef      deeef   fdZ!ddededee
eef      fdZ"deeef   defdZ#d dZ$e%dk(  r e$        yy# e$ r dZY w xY w)!u;  AI 유입 사용자 전환 퍼널 분석기.

GA4 Data API(옵셔널) 또는 CSV 수동 입력으로 퍼널 단계별 드롭오프율을 분석한다.

Usage:
    python3 conversion_tracker.py --property-id 123456 --date-range 30d
    python3 conversion_tracker.py --events-csv events.csv --output funnel-report.md
    N)AnyDictListOptionalTuple)FUNNEL_STAGESis_ga4_configured)BetaAnalyticsDataClient)	DateRange	DimensionMetricRunReportRequestTF   전환u   AI 검색 도착
prev_users
curr_usersreturnc                 $    | dk(  ry| |z
  | z  dz  S )u.   (prev-curr)/prev*100. prev=0이면 0.0 반환.r           d    )r   r   s     W/home/jay/workspace/.worktrees/task-2117-dev1/tools/geo-analytics/conversion_tracker.pycalculate_dropoffr   #   s!    Q#z1C77    
stage_datac                     | sg S | d   d   }g }t        |       D ]Z  \  }\  }}||d}|dk(  rd|d<   n1|r||z  dz  nd}|dd	|d<   t        | |dz
     d   |      dd	|d
<   |j                  |       \ |S )u2   퍼널 단계별 rate 및 dropoff를 계산한다.r      stageusersz100%rater   r   .1f%dropoff)	enumerater   append)r   first_usersfunnelidxr   r   entryr    s           r   calculate_funnelr*   *   s    	Q-"K#%F(4 ^eU*/% @!8"E&M0;5;&,D#CjNE&M"3JsQw4G4JE"RSV!WWXYE)e Mr   source_datac                 j   | si S i }i }| D ]J  \  }}}|t         k(  r|j                  |d      |z   ||<   )|t        k(  s3|j                  |d      |z   ||<   L i }t        |      t        |      z  D ]?  }|j                  |d      }|j                  |d      }	|r|	|z  dz  nd}
||	|
ddd||<   A |S )u8   AI 소스별 arrivals, conversions, CVR을 계산한다.r   r   r   r!   r"   )arrivalsconversionscvr)_ARRIVAL_STAGEget_CONVERSION_STAGEset)r+   r-   r.   r   r   sourceresultsrcarrconvr/   s              r   analyze_ai_sourcesr9   <   s    	!H"$K + EufN"'||FA6>HV''"-//&!"<u"DK	E
 )+F8}s;// Sll3"sA&"%dSj33#&ts3iqMRs	S
 Mr   r'   sourcesc           	         g }| D cg c]	  }d|v s| }}|rRt        |d       }| j                  |      }|dkD  r| |dz
     d   nd}|j                  d| d	|d    d
|d    d       |rqt        |j	                         d d      }|d   \  }	}
|j                  d|	 d|
d    d       t        |      dkD  r#|d   \  }}|j                  d| d|d    d       |S c c}w )uF   퍼널 및 소스 데이터에서 인사이트를 자동 생성한다.r#   c                 >    t        | d   j                  dd            S )Nr#   r"    floatreplace)fs    r   <lambda>z#generate_insights.<locals>.<lambda>U   s    59AUAUVY[]A^;_ r   )keyr   r   r   ?u   최대 이탈 지점: u    → z (u    드롭오프)c                 D    t        | d   d   j                  dd            S )Nr   r/   r"   r=   r>   )kvs    r   rB   z#generate_insights.<locals>.<lambda>Z   s"    E"Q%,BVBVWZ\^B_<` r   T)rC   reverseu   최고 전환 소스: z (CVR r/   )u   최저 전환 소스: )maxindexr%   sorteditemslen)r'   r:   insightsrA   stages_with_dropoff	max_stager(   
prev_stage
sorted_srcbest_srcbest_val	worst_src	worst_vals                r   generate_insightsrX   P   s   H&,?	Q1??+1_`	ll9%14qVC!G_W-c
0E)GBTAUUWXabkXlWmm{|}GMMO1`jno
'](0
&%@QQRSTz?Q#-b> IyOO4YKviPUFVEWWXYZO @s
   	C C c                     t        j                  |       }g }|D ]_  }|d   j                         t        |d   j                               d}d|v r|d   j                         nd|d<   |j	                  |       a |S )u*   CSV(stage,users[,source])를 파싱한다.r   r   r   r4   N)csv
DictReaderstripintr%   )file_objreaderrowsrowr)   s        r   	parse_csvrb   c   s    ^^H%F!#D *-g,*<*<*>SQX\M_M_MaIb c3;s?#h---/hE Kr   c                 N    t        |       }t        |      }||t        ||      dS )uK   퍼널 + 소스 데이터로 최종 리포트 딕셔너리를 생성한다.)r'   ai_source_breakdownrO   )r*   r9   rX   )r   r+   r'   r:   s       r   build_reportre   n   s/    
 j)F -GWJ[\bdkJlmmr   property_id
date_rangec           	         t         r
t               sg S |j                  d      }	 t               }t	        d|  t        d      gt        d      gt        | dd      g	      }|j                  |      }|j                  D ci c]<  }|j                  d
   j                  t        |j                  d
   j                        > }}t        D cg c]  }||v s|||   f c}S c c}w c c}w # t        $ r g cY S w xY w)uF   GA4 API로 퍼널 단계별 사용자 수를 수집한다 (옵셔널).dzproperties/	eventName)name
eventCountdaysAgotoday)
start_dateend_date)property
dimensionsmetricsdate_rangesr   )_GA4_AVAILABLEr	   rstripr
   r   r   r   r   
run_reportr`   dimension_valuesvaluer]   metric_valuesr   	Exception)	rf   rg   daysclientrequestresponsera   	stage_mapss	            r   _fetch_ga4_funnelr   x   s    !2!4	S!D(*"";-0!{34./"g.>QR	
 $$W-_g_l_lmX[S))!,22C8I8I!8L8R8R4SSm	m+8KaANIaL!KK nK 	s7   A C0 AC&
C0 	C+	C+#C0 &
C0 0C>=C>reportc                    g d}| d   D ]:  }|j                  d|d    d|d   dd|d    d|j                  d	d
       d	       < | d   rK|g dz  }| d   j                         D ].  \  }}|j                  d| d|d   dd|d   dd|d    d	       0 | d   r |ddgz  }|| d   D cg c]  }d| 	 c}z  }dj                  |      S c c}w )u7   리포트를 마크다운 형식으로 렌더링한다.)u    # AI 유입 전환 퍼널 분석r=   u   ## 퍼널 단계별 현황u1   | 단계 | 사용자 | 잔존율 | 드롭오프 |z%|------|--------|--------|----------|r'   z| r   z | r   ,r    r#   -z |rd   )r=   u   ## AI 소스별 전환율u"   | 소스 | 유입 | 전환 | CVR |z|------|------|------|-----|r-   r.   r/   rO   r=   u   ## 인사이트z- 
)r%   r1   rM   join)r   linesr   r6   valis         r   _render_markdownr      s(   E H cr!G*S7Ac!F)CiY\H]G^^`abc#$xx45;;= 	eHCLL2cU#c*oa%8C<Nq;QQTUXY^U_T``bcd	ej"'((F:$67qBqc(7799U 8s   +Cc                  $   t        j                  d      } | j                  dd       | j                  ddd	       | j                  d
dd	       | j                  dd       | j                  dd       | j                         }g }g }|j                  rt        |j                  d      5 }t        |      }d d d        t        d D              }|rc|D cg c]  }|d   |d   |d   f }}i }|D ]#  }|j                  |d   d      |d   z   ||d   <   % t        D 	cg c]  }	|	|v s|	||	   f }}	n|D cg c]  }|d   |d   f }}n|j                  rSt        |j                  |j                        }|sVt        dt        j                         t        j                   d       n%| j#                          t        j                   d       t%        ||      }
|j&                  ro|j&                  j)                  d      rTt        |j&                  dd      5 }|j+                  t-        |
             d d d        t        d|j&                          y |j&                  rSt        |j&                  dd      5 }t/        j0                  |
|dd        d d d        t        d!|j&                          y t        t/        j2                  |
dd              y # 1 sw Y   %xY wc c}w c c}	w c c}w # 1 sw Y   xY w# 1 sw Y   lxY w)"Nu!   AI 유입 전환 퍼널 분석기)descriptionz--property-idzGA4 Property ID)helpz--date-range30du   날짜 범위 (예: 30d))defaultr   z--conversion-eventr   u   전환 이벤트명z--events-csvu!   CSV 파일 경로 (수동 모드)z--outputu'   출력 파일 경로 (.md 또는 .json)zutf-8)encodingc              3   >   K   | ]  }|j                  d         yw)r4   N)r1   ).0rs     r   	<genexpr>zmain.<locals>.<genexpr>   s     7Qx7s   r   r   r4   r   uO   [경고] GA4 API 연결 실패 또는 미설정. CSV 모드를 사용하세요.)filer   z.mdwu   [완료] 마크다운 저장: F   )ensure_asciiindentu   [완료] JSON 저장: )argparseArgumentParseradd_argument
parse_args
events_csvopenrb   anyr1   r   rf   r   rg   printsysstderrexit
print_helpre   outputendswithwriter   jsondumpdumps)parserargsr   r+   rA   r`   
has_sourcer   stage_totalsr   r   s              r   mainr      s   $$1TUF
.?@
<VW
,hEZ[
-PQ

)RSD(*J.0K$//G4 	 Q<D	 7$77
JNOQAgJ'
AhK@OKO+-L X+7+;+;AgJ+JQwZ+WQwZ(X8E[1lIZ1l1o.[J[<@Aq1W:qz2AJA			&t'7'7I
cjmjtjtuHHQK*k2F{{t{{++E2$++sW5 	.GG$V,-	..t{{m<=	$++sW5 	?IIfaeA>	?&t{{m45djjeA>??	  	  P \A	. 	.	? 	?s<   /KK+$	K0.	K0>K5!K:LK(:LL__main__)r   )r   N)&__doc__r   rZ   r   r   typingr   r   r   r   r   configr   r	   google.analytics.data_v1betar
   "google.analytics.data_v1beta.typesr   r   r   r   ru   ImportErrorr2   r0   r]   r?   r   strr*   r9   rX   rb   re   r   r   r   __name__r   r   r   <module>r      s    
  
 3 3 3D  N  #8# 83 85 8eCHo!6 4S#X;O $DsC})=$> 4TRUWZRZ^H[C\ (d4S>2 T#tCQTH~BU=V [_`c[d &4S#X/ nU38_%neCcM*+n 
#s(^n3 C DsTWxDY (T#s(^  *,@^ zF i  Ns   C> >DD