From 88a2dfcc2b583e7be7da37c3cb1899e24bafc6fa Mon Sep 17 00:00:00 2001 From: Matt Landers Date: Wed, 13 May 2026 08:30:29 -0500 Subject: [PATCH 1/4] initial implementation for the new conversions api --- analytics_mcp/coordinator.py | 17 ++ analytics_mcp/tools/reporting/conversions.py | 184 +++++++++++++++++++ pyproject.toml | 2 +- 3 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 analytics_mcp/tools/reporting/conversions.py diff --git a/analytics_mcp/coordinator.py b/analytics_mcp/coordinator.py index f1681ac..b53516d 100644 --- a/analytics_mcp/coordinator.py +++ b/analytics_mcp/coordinator.py @@ -50,6 +50,10 @@ run_funnel_report, _run_funnel_report_description, ) +from analytics_mcp.tools.reporting.conversions import ( + run_conversions_report, + _run_conversions_report_description, +) run_report_with_description = FunctionTool(run_report) run_report_with_description.description = _run_report_description() @@ -61,6 +65,10 @@ run_funnel_report_with_description.description = ( _run_funnel_report_description() ) +run_conversions_report_with_description = FunctionTool(run_conversions_report) +run_conversions_report_with_description.description = ( + _run_conversions_report_description() +) # Instantiate the ADK tools tools = [ @@ -72,6 +80,7 @@ run_report_with_description, run_realtime_report_with_description, run_funnel_report_with_description, + run_conversions_report_with_description, ] tool_map = {t.name: t for t in tools} @@ -133,6 +142,14 @@ def sanitize_mcp_schema_properties(node: dict) -> None: ] elif tool.name == "run_realtime_report": tool.inputSchema["required"] = ["property_id", "dimensions", "metrics"] + elif tool.name == "run_conversions_report": + tool.inputSchema["required"] = [ + "property_id", + "date_ranges", + "dimensions", + "metrics", + "conversion_spec", + ] @app.list_tools() diff --git a/analytics_mcp/tools/reporting/conversions.py b/analytics_mcp/tools/reporting/conversions.py new file mode 100644 index 0000000..6431566 --- /dev/null +++ b/analytics_mcp/tools/reporting/conversions.py @@ -0,0 +1,184 @@ +# Copyright 2025 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tools for running conversions reports using the Data API.""" + +import asyncio +from typing import Any, Dict, List + +from analytics_mcp.tools.reporting.metadata import ( + get_date_ranges_hints, + get_dimension_filter_hints, + get_metric_filter_hints, + get_order_bys_hints, +) +from analytics_mcp.tools.utils import ( + construct_property_rn, + proto_to_dict, +) +from analytics_mcp.tools.client import create_data_api_alpha_client +from google.analytics import data_v1alpha + + +def _run_conversions_report_description() -> str: + """Returns the description for the `run_conversions_report` tool.""" + return f""" + {run_conversions_report.__doc__} + + ## Hints for arguments + + Here are some hints that outline the expected format and requirements + for arguments. + + ### Hints for `dimensions` + + The `dimensions` list must consist solely of the following allowed standard dimensions: + - campaignName + - continent + - country + - defaultChannelGroup + - deviceCategory + - medium + - platform + - primaryChannelGroup + - source + - sourceMedium + - sourcePlatform + - subcontinent + + ### Hints for `metrics` + + The `metrics` list must consist solely of the following allowed standard metrics: + - advertiserAdClicks + - advertiserAdCost + - advertiserAdCostPerAllConversionsByConversionDate + - advertiserAdCostPerAllConversionsByInteractionDate + - advertiserAdCostPerClick + - advertiserAdImpressions + - allConversionsByConversionDate + - allConversionsByInteractionDate + - returnOnAdSpendByConversionDate + - returnOnAdSpendByInteractionDate + - totalRevenueByConversionDate + - totalRevenueByInteractionDate + + ### Hints for `conversion_spec` + + The `conversion_spec` argument is required for conversions reporting. + You can pass an empty list for `conversion_actions` if you want all conversion events. + Example: + {{ + "conversion_actions": ["conversionActions/12345"], # Or [] for all actions + "attribution_model": "DATA_DRIVEN" # Or "LAST_CLICK" + }} + + ### Hints for `date_ranges`: + {get_date_ranges_hints()} + + ### Hints for `dimension_filter`: + {get_dimension_filter_hints()} + + ### Hints for `metric_filter`: + {get_metric_filter_hints()} + + ### Hints for `order_bys`: + {get_order_bys_hints()} + + """ + + +async def run_conversions_report( + property_id: int | str, + date_ranges: List[Dict[str, Any]], + dimensions: List[str], + metrics: List[str], + conversion_spec: Dict[str, Any], + dimension_filter: Dict[str, Any] = None, + metric_filter: Dict[str, Any] = None, + order_bys: List[Dict[str, Any]] = None, + limit: int = None, + offset: int = None, + currency_code: str = None, + return_property_quota: bool = False, +) -> Dict[str, Any]: + """Runs a Google Analytics Data API conversions report. + + See the conversions report guide at + https://developers.google.com/analytics/devguides/reporting/data/v1/conversions-api-basics + for details and examples. + + Args: + property_id: The Google Analytics property ID. Accepted formats are: + - A number + - A string consisting of 'properties/' followed by a number + date_ranges: A list of date ranges + (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/DateRange) + to include in the report. + dimensions: A list of dimensions to include in the report. + metrics: A list of metrics to include in the report. + conversion_spec: The specification for conversions reporting. + Should include 'conversion_actions' (list of resource names) and + 'attribution_model'. + dimension_filter: A Data API FilterExpression + (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/FilterExpression) + to apply to the dimensions. + metric_filter: A Data API FilterExpression + (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/FilterExpression) + to apply to the metrics. + order_bys: A list of Data API OrderBy + (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/OrderBy) + objects to apply to the dimensions and metrics. + limit: The maximum number of rows to return in each response. Value must + be a positive integer <= 250,000. + offset: The row count of the start row. The first row is counted as row 0. + currency_code: The currency code to use for currency values. + return_property_quota: Whether to return property quota in the response. + """ + request = data_v1alpha.RunReportRequest( + property=construct_property_rn(property_id), + dimensions=[ + data_v1alpha.Dimension(name=dimension) for dimension in dimensions + ], + metrics=[data_v1alpha.Metric(name=metric) for metric in metrics], + date_ranges=[data_v1alpha.DateRange(dr) for dr in date_ranges], + conversion_spec=data_v1alpha.ConversionSpec(conversion_spec), + return_property_quota=return_property_quota, + ) + + if dimension_filter: + request.dimension_filter = data_v1alpha.FilterExpression( + dimension_filter + ) + + if metric_filter: + request.metric_filter = data_v1alpha.FilterExpression(metric_filter) + + if order_bys: + request.order_bys = [ + data_v1alpha.OrderBy(order_by) for order_by in order_bys + ] + + if limit: + request.limit = limit + if offset: + request.offset = offset + if currency_code: + request.currency_code = currency_code + + def _sync_call(): + return create_data_api_alpha_client().run_report(request) + + response = await asyncio.to_thread(_sync_call) + + return proto_to_dict(response) diff --git a/pyproject.toml b/pyproject.toml index a638c56..c37b51d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ requires-python = ">=3.10" license = "Apache-2.0" readme = "README.md" dependencies = [ - "google-analytics-data==0.21.0", + "google-analytics-data==0.22.0", "google-analytics-admin==0.28.0", "google-auth~=2.40", "mcp>=1.24.0", From 79db1e75d83fd1dc2f2c04b4093c2990e1ab5532 Mon Sep 17 00:00:00 2001 From: Matt Landers Date: Wed, 13 May 2026 09:56:52 -0500 Subject: [PATCH 2/4] fix: update documentation links in run_conversions_report to v1alpha --- analytics_mcp/tools/reporting/conversions.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/analytics_mcp/tools/reporting/conversions.py b/analytics_mcp/tools/reporting/conversions.py index 6431566..7339d4f 100644 --- a/analytics_mcp/tools/reporting/conversions.py +++ b/analytics_mcp/tools/reporting/conversions.py @@ -123,7 +123,7 @@ async def run_conversions_report( - A number - A string consisting of 'properties/' followed by a number date_ranges: A list of date ranges - (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/DateRange) + (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha/DateRange) to include in the report. dimensions: A list of dimensions to include in the report. metrics: A list of metrics to include in the report. @@ -131,13 +131,13 @@ async def run_conversions_report( Should include 'conversion_actions' (list of resource names) and 'attribution_model'. dimension_filter: A Data API FilterExpression - (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/FilterExpression) + (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha/FilterExpression) to apply to the dimensions. metric_filter: A Data API FilterExpression - (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/FilterExpression) + (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha/FilterExpression) to apply to the metrics. order_bys: A list of Data API OrderBy - (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/OrderBy) + (https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha/OrderBy) objects to apply to the dimensions and metrics. limit: The maximum number of rows to return in each response. Value must be a positive integer <= 250,000. From 0a8bfa3268e1fd244a48f86f1b416b5af2bfead7 Mon Sep 17 00:00:00 2001 From: Matt Landers Date: Thu, 14 May 2026 07:51:59 -0500 Subject: [PATCH 3/4] docs: enhance run_conversions_report docstring with usage guidelines --- analytics_mcp/tools/reporting/conversions.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/analytics_mcp/tools/reporting/conversions.py b/analytics_mcp/tools/reporting/conversions.py index 7339d4f..a5e7c31 100644 --- a/analytics_mcp/tools/reporting/conversions.py +++ b/analytics_mcp/tools/reporting/conversions.py @@ -114,6 +114,12 @@ async def run_conversions_report( ) -> Dict[str, Any]: """Runs a Google Analytics Data API conversions report. + USE THIS TOOL INSTEAD OF `run_report` WHEN: + - You need to report specifically on conversions, ad performance, return on ad spend (ROAS), or attribution. + - You need to query specific conversion metrics (e.g., advertiserAdCost, returnOnAdSpendByInteractionDate, allConversionsByConversionDate, etc.). + - You need to apply a specific attribution model (e.g., DATA_DRIVEN or LAST_CLICK) to your data. + - The user's query explicitly asks about conversions, ad clicks, ad costs, or campaigns related to conversions. + See the conversions report guide at https://developers.google.com/analytics/devguides/reporting/data/v1/conversions-api-basics for details and examples. From bc956208bb44c6ce41812a5dcaa33623b300afce Mon Sep 17 00:00:00 2001 From: Matt Landers Date: Thu, 14 May 2026 09:46:37 -0500 Subject: [PATCH 4/4] Update analytics_mcp/tools/reporting/conversions.py Co-authored-by: Josh Radcliff --- analytics_mcp/tools/reporting/conversions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analytics_mcp/tools/reporting/conversions.py b/analytics_mcp/tools/reporting/conversions.py index a5e7c31..9dbc7d3 100644 --- a/analytics_mcp/tools/reporting/conversions.py +++ b/analytics_mcp/tools/reporting/conversions.py @@ -1,4 +1,4 @@ -# Copyright 2025 Google LLC All Rights Reserved. +# Copyright 2026 Google LLC All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License.