@@ -637,7 +637,7 @@ def correlate_impression_share(
637637 ] = 7 ,
638638 country : Annotated [
639639 str | None ,
640- typer .Option ("--country" , "-c" , help = "Filter by country code (required for correlation )" ),
640+ typer .Option ("--country" , "-c" , help = "Filter by country code (optional, defaults to all )" ),
641641 ] = None ,
642642 min_share : Annotated [
643643 float | None ,
@@ -673,16 +673,12 @@ def correlate_impression_share(
673673 campaign-level attribution for impression share data.
674674
675675 Examples:
676- asa impression-share correlate --country US
677- asa impression-share correlate --country AU --min-share 30
678- asa impression-share correlate --country US --unmatched # New keyword opportunities
679- asa impression-share correlate --country US --matched --min-share 40 # Bid increase candidates
676+ asa impression-share correlate # All countries
677+ asa impression-share correlate --country US # Single country
678+ asa impression-share correlate --min-share 30 # Low share only
679+ asa impression-share correlate --unmatched # New keyword opportunities
680+ asa impression-share correlate --matched --min-share 40 # Bid increase candidates
680681 """
681- if not country :
682- print_error ("Error" , "Country is required for correlation. Use --country/-c" )
683- raise typer .Exit (1 )
684-
685- country = country .upper ()
686682 client = get_client ()
687683
688684 if days > 30 :
@@ -692,6 +688,8 @@ def correlate_impression_share(
692688 end_date = date .today () - timedelta (days = 1 )
693689 start_date = end_date - timedelta (days = days - 1 )
694690
691+ country_codes = [country .upper ()] if country else None
692+
695693 try :
696694 with client :
697695 # Step 1: Get impression share data
@@ -700,39 +698,47 @@ def correlate_impression_share(
700698 start_date = start_date ,
701699 end_date = end_date ,
702700 granularity = GranularityType .DAILY ,
703- country_codes = [ country ] ,
701+ country_codes = country_codes ,
704702 poll_interval = 3.0 ,
705703 timeout = 120.0 ,
706704 )
707705
708706 if not report .row :
709- print_warning (f "No impression share data available for { country } " )
707+ print_warning ("No impression share data available" )
710708 return
711709
712710 print_success (f"Retrieved { len (report .row )} impression share records" )
713711
714- # Step 2: Build keyword index for this country
715- with spinner (f"Building keyword index for { country } ..." ):
716- keyword_index = _build_keyword_index (client , country )
717-
718- total_kw = sum (len (v ) for v in keyword_index .values ())
719- print_info (f"Indexed { total_kw } keywords from { len (keyword_index )} unique terms" )
720-
721- # Step 3: Correlate data
712+ # Parse and aggregate data
722713 share_data = _parse_report_data (report )
723714 aggregated = _aggregate_by_search_term (share_data )
724715
716+ # Find all unique countries in the data
717+ countries_in_data = {item .country .upper () for item in aggregated .values () if item .country }
718+ print_info (f"Found data for { len (countries_in_data )} countries: { ', ' .join (sorted (countries_in_data ))} " )
719+
720+ # Step 2: Build keyword index for each country
721+ keyword_indices : dict [str , dict [str , list [KeywordInfo ]]] = {}
722+ total_keywords = 0
723+
724+ for ctry in countries_in_data :
725+ with spinner (f"Building keyword index for { ctry } ..." ):
726+ keyword_indices [ctry ] = _build_keyword_index (client , ctry )
727+ kw_count = sum (len (v ) for v in keyword_indices [ctry ].values ())
728+ total_keywords += kw_count
729+
730+ print_info (f"Indexed { total_keywords } keywords across { len (countries_in_data )} countries" )
731+
732+ # Step 3: Correlate data
725733 correlated : list [CorrelatedSearchTerm ] = []
726734 for item in aggregated .values ():
727- if item .country .upper () != country :
728- continue
729-
735+ ctry = item .country .upper ()
736+ keyword_index = keyword_indices .get (ctry , {})
730737 search_term_lower = item .search_term .lower ()
731738 matched_keywords = keyword_index .get (search_term_lower , [])
732739
733740 if matched_keywords :
734741 # Use first match (could be multiple campaigns with same keyword)
735- # TODO: Could show all matches or pick based on criteria
736742 match = matched_keywords [0 ]
737743 correlated .append (
738744 CorrelatedSearchTerm (
@@ -782,7 +788,7 @@ def correlate_impression_share(
782788 return
783789
784790 # Sort by share (lowest first)
785- correlated .sort (key = lambda x : x .avg_share )
791+ correlated .sort (key = lambda x : ( x .avg_share , x . country , x . search_term ) )
786792
787793 # Stats
788794 matched_count = sum (1 for c in correlated if c .is_matched )
@@ -835,8 +841,15 @@ def correlate_impression_share(
835841 # Display table
836842 display_limit = len (correlated ) if limit == 0 else limit
837843
838- table = Table (title = f"Impression Share Correlation - { country } " )
844+ title = "Impression Share Correlation"
845+ if country :
846+ title += f" - { country .upper ()} "
847+ else :
848+ title += f" - All Countries ({ len (countries_in_data )} )"
849+
850+ table = Table (title = title )
839851 table .add_column ("Search Term" , style = "cyan" , max_width = 30 )
852+ table .add_column ("Ctry" , style = "dim" , width = 4 )
840853 table .add_column ("Share" , justify = "right" , width = 8 )
841854 table .add_column ("Campaign" , style = "magenta" , max_width = 25 )
842855 table .add_column ("Keyword" , style = "dim" , max_width = 20 )
@@ -857,6 +870,7 @@ def correlate_impression_share(
857870
858871 table .add_row (
859872 row .search_term [:30 ],
873+ row .country ,
860874 f"[{ share_style } ]{ row .share_range } [/{ share_style } ]" ,
861875 campaign_display ,
862876 keyword_display ,
0 commit comments