@@ -270,6 +270,7 @@ async def run_report(
270270
271271 return proto_to_dict (response )
272272
273+
273274async def run_funnel_report (
274275 property_id : int | str ,
275276 funnel_steps : List [Dict [str , Any ]],
@@ -290,7 +291,7 @@ async def run_funnel_report(
290291 - 'name': (str) Display name for the step
291292 - 'filter_expression': (Dict) Complete filter expression for the step
292293 OR for simple event-based steps:
293- - 'name': (str) Display name for the step
294+ - 'name': (str) Display name for the step
294295 - 'event': (str) Event name to filter on
295296 Example:
296297 [
@@ -322,17 +323,17 @@ async def run_funnel_report(
322323 Example: {"next_action_dimension": "eventName", "limit": 5}
323324 segments: Optional list of segments to apply to the funnel.
324325 return_property_quota: Whether to return current property quota information.
325-
326+
326327 Returns:
327328 Dict containing the funnel report response with funnel results including:
328329 - funnel_table: Table showing progression through funnel steps
329330 - funnel_visualization: Data for visualizing the funnel
330331 - property_quota: (if requested) Current quota usage information
331-
332+
332333 Raises:
333334 ValueError: If funnel_steps is empty or contains invalid configurations
334335 Exception: If the API request fails
335-
336+
336337 Example:
337338 # Simple event-based funnel
338339 result = await run_funnel_report(
@@ -343,7 +344,7 @@ async def run_funnel_report(
343344 {"name": "Purchase", "event": "purchase"}
344345 ]
345346 )
346-
347+
347348 # Advanced funnel with page path filtering
348349 result = await run_funnel_report(
349350 property_id="123456789",
@@ -375,109 +376,65 @@ async def run_funnel_report(
375376 date_ranges=[{"start_date": "7daysAgo", "end_date": "today"}]
376377 )
377378 """
378- # Validate inputs
379- if not funnel_steps :
380- raise ValueError ("funnel_steps cannot be empty" )
381-
382- if len (funnel_steps ) < 2 :
383- raise ValueError ("funnel_steps must contain at least 2 steps" )
384-
385- # Set default date range if not provided
386- if not date_ranges :
387- date_ranges = [{"start_date" : "30daysAgo" , "end_date" : "today" }]
388-
389- # Validate and create funnel steps
379+
390380 steps = []
391381 for i , step in enumerate (funnel_steps ):
392382 if not isinstance (step , dict ):
393383 raise ValueError (f"Step { i + 1 } must be a dictionary" )
394-
395- step_name = step .get ('name' , f'Step { i + 1 } ' )
396-
397- # Build filter expression
398- if 'filter_expression' in step :
399- # Use provided filter expression
400- filter_expr = data_v1alpha .FunnelFilterExpression (step ['filter_expression' ])
401- elif 'event' in step :
402- # Simple event-based filter
384+
385+ step_name = step .get ("name" , f"Step { i + 1 } " )
386+
387+ if "filter_expression" in step :
388+ filter_expr = data_v1alpha .FunnelFilterExpression (
389+ step ["filter_expression" ]
390+ )
391+ elif "event" in step :
403392 filter_expr = data_v1alpha .FunnelFilterExpression (
404393 funnel_event_filter = data_v1alpha .FunnelEventFilter (
405- event_name = step [' event' ]
394+ event_name = step [" event" ]
406395 )
407396 )
408397 else :
409398 raise ValueError (
410399 f"Step { i + 1 } must contain either 'filter_expression' or 'event' key"
411400 )
412-
401+
413402 funnel_step = data_v1alpha .FunnelStep (
414- name = step_name ,
415- filter_expression = filter_expr
403+ name = step_name , filter_expression = filter_expr
416404 )
417405 steps .append (funnel_step )
418-
419- # Create the funnel configuration
420- funnel_config = data_v1alpha .Funnel (steps = steps )
421-
422- # Create date ranges
423- date_range_objects = []
424- for dr in date_ranges :
425- if not isinstance (dr , dict ) or 'start_date' not in dr or 'end_date' not in dr :
426- raise ValueError (
427- "Each date range must be a dictionary with 'start_date' and 'end_date' keys"
428- )
429- date_range_objects .append (
430- data_v1alpha .DateRange (start_date = dr ['start_date' ], end_date = dr ['end_date' ])
431- )
432406
433- # Create the request
434407 request = data_v1alpha .RunFunnelReportRequest (
435408 property = construct_property_rn (property_id ),
436- funnel = funnel_config ,
437- date_ranges = date_range_objects ,
438- return_property_quota = return_property_quota
409+ funnel = data_v1alpha . Funnel ( steps = steps ) ,
410+ date_ranges = [ data_v1alpha . DateRange ( dr ) for dr in date_ranges ] ,
411+ return_property_quota = return_property_quota ,
439412 )
440-
441- # Add breakdown if specified (this goes on the request, not the funnel)
442- if funnel_breakdown and 'breakdown_dimension' in funnel_breakdown :
413+
414+ if funnel_breakdown and "breakdown_dimension" in funnel_breakdown :
443415 request .funnel_breakdown = data_v1alpha .FunnelBreakdown (
444416 breakdown_dimension = data_v1alpha .Dimension (
445- name = funnel_breakdown [' breakdown_dimension' ]
417+ name = funnel_breakdown [" breakdown_dimension" ]
446418 )
447419 )
448-
449- # Add next action if specified (this also goes on the request, not the funnel)
450- if funnel_next_action and 'next_action_dimension' in funnel_next_action :
420+
421+ if funnel_next_action and "next_action_dimension" in funnel_next_action :
451422 next_action_config = data_v1alpha .FunnelNextAction (
452423 next_action_dimension = data_v1alpha .Dimension (
453- name = funnel_next_action [' next_action_dimension' ]
424+ name = funnel_next_action [" next_action_dimension" ]
454425 )
455426 )
456- if ' limit' in funnel_next_action :
457- next_action_config .limit = funnel_next_action [' limit' ]
427+ if " limit" in funnel_next_action :
428+ next_action_config .limit = funnel_next_action [" limit" ]
458429 request .funnel_next_action = next_action_config
459-
460- # Add segments if provided
430+
461431 if segments :
462- request .segments = [data_v1alpha .Segment (segment ) for segment in segments ]
463-
464- # Execute the request with enhanced error handling
465- try :
466- client = create_data_api_alpha_client ()
467- response = await client .run_funnel_report (request = request )
468- return proto_to_dict (response )
469- except Exception as e :
470- error_msg = str (e )
471- if "INVALID_ARGUMENT" in error_msg :
472- raise ValueError (f"Invalid funnel configuration: { error_msg } " )
473- elif "PERMISSION_DENIED" in error_msg :
474- raise PermissionError (f"Permission denied accessing property: { error_msg } " )
475- elif "NOT_FOUND" in error_msg :
476- raise ValueError (f"Property not found: { error_msg } " )
477- elif "QUOTA_EXCEEDED" in error_msg :
478- raise RuntimeError (f"API quota exceeded: { error_msg } " )
479- else :
480- raise Exception (f"Failed to run funnel report: { error_msg } " )
432+ request .segments = [
433+ data_v1alpha .Segment (segment ) for segment in segments
434+ ]
435+
436+ response = await create_data_api_alpha_client ().run_funnel_report (request )
437+ return proto_to_dict (response )
481438
482439
483440# The `run_report` tool requires a more complex description that's generated at
0 commit comments