Skip to main content
Glama
johnoconnor0

Google Ads MCP Server

by johnoconnor0

google_ads_pmax_insights

Retrieve performance insights for Performance Max campaigns, including all-conversions data across Google properties, by specifying customer ID, campaign ID, and date range.

Instructions

Get performance insights for a Performance Max campaign.

Provides comprehensive metrics including all-conversions data which captures conversions across all Google properties.

Args: customer_id: Google Ads customer ID (10 digits, no hyphens) campaign_id: Performance Max campaign ID date_range: Date range (LAST_7_DAYS, LAST_30_DAYS, LAST_90_DAYS)

Returns: Performance Max campaign insights

Example: google_ads_pmax_insights( customer_id="1234567890", campaign_id="12345678", date_range="LAST_30_DAYS" )

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
customer_idYes
campaign_idYes
date_rangeNoLAST_30_DAYS

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The MCP tool handler function that receives the request, delegates to the manager, and formats the response output with performance metrics, asset group details, and optimization tips.
    @mcp.tool()
    def google_ads_pmax_insights(
        customer_id: str,
        campaign_id: str,
        date_range: str = "LAST_30_DAYS"
    ) -> str:
        """Get performance insights for a Performance Max campaign.
    
        Provides comprehensive metrics including all-conversions data which
        captures conversions across all Google properties.
    
        Args:
            customer_id: Google Ads customer ID (10 digits, no hyphens)
            campaign_id: Performance Max campaign ID
            date_range: Date range (LAST_7_DAYS, LAST_30_DAYS, LAST_90_DAYS)
    
        Returns:
            Performance Max campaign insights
    
        Example:
            google_ads_pmax_insights(
                customer_id="1234567890",
                campaign_id="12345678",
                date_range="LAST_30_DAYS"
            )
        """
        with performance_logger.track_operation('pmax_insights', customer_id=customer_id):
            try:
                client = get_auth_manager().get_client()
                shopping_manager = ShoppingPMaxManager(client)
    
                result = shopping_manager.get_pmax_insights(
                    customer_id=customer_id,
                    campaign_id=campaign_id,
                    date_range=date_range
                )
    
                if 'error' in result:
                    return f"❌ {result['error']}"
    
                audit_logger.log_api_call(
                    customer_id=customer_id,
                    operation='pmax_insights',
                    campaign_id=campaign_id,
                    status='success'
                )
    
                metrics = result['metrics']
    
                output = f"# 🚀 Performance Max Insights\n\n"
                output += f"**Campaign**: {result['campaign_name']}\n"
                output += f"**Campaign ID**: {result['campaign_id']}\n"
                output += f"**Date Range**: {date_range}\n\n"
    
                output += "## Campaign Performance\n\n"
                output += f"- **Impressions**: {metrics['impressions']:,}\n"
                output += f"- **Clicks**: {metrics['clicks']:,}\n"
                output += f"- **CTR**: {metrics['ctr']:.2%}\n"
                output += f"- **Cost**: ${metrics['cost']:,.2f}\n"
                output += f"- **Conversions**: {metrics['conversions']:.1f}\n"
                output += f"- **Conversion Value**: ${metrics['conversion_value']:,.2f}\n"
                output += f"- **ROAS**: {metrics['roas']:.2f}x\n\n"
    
                output += "## All-Conversions Metrics\n\n"
                output += "*Includes conversions from all Google properties*\n\n"
                output += f"- **All Conversions**: {metrics['all_conversions']:.1f}\n"
                output += f"- **All Conversion Value**: ${metrics['all_conversions_value']:,.2f}\n\n"
    
                # Asset Groups
                output += f"## Asset Groups ({result['total_asset_groups']})\n\n"
    
                if result['total_asset_groups'] > 0:
                    output += "| Asset Group | Status | Impressions | Clicks | Conv. |\n"
                    output += "|-------------|--------|-------------|--------|-------|\n"
    
                    for ag in result['asset_groups'][:5]:  # Top 5
                        output += f"| {ag['asset_group_name'][:20]} | "
                        output += f"{ag['status']} | "
                        output += f"{ag['impressions']:,} | "
                        output += f"{ag['clicks']:,} | "
                        output += f"{ag['conversions']:.1f} |\n"
                else:
                    output += "No asset groups found. Create asset groups to start serving ads.\n"
    
                output += "\n## Performance Analysis\n\n"
    
                # ROAS analysis
                if metrics['roas'] > 4.0:
                    output += "✅ **Excellent ROAS!** Campaign is highly profitable.\n"
                    output += "💡 Consider increasing budget to scale.\n"
                elif metrics['roas'] > 2.0:
                    output += "💚 **Good ROAS.** Campaign is performing well.\n"
                    output += "💡 Monitor and optimize asset groups.\n"
                elif metrics['roas'] > 1.0:
                    output += "⚠️ **Marginal ROAS.** Room for improvement.\n"
                    output += "💡 Review assets and audience signals.\n"
                else:
                    output += "🚨 **Low ROAS.** Campaign needs optimization.\n"
                    output += "💡 Check assets, budgets, and conversion tracking.\n"
    
                output += "\n## Optimization Tips\n\n"
                output += "1. 📝 Test different headlines and descriptions\n"
                output += "2. 🖼️ Add high-quality images in multiple sizes\n"
                output += "3. 🎯 Refine audience signals based on performance\n"
                output += "4. 💰 Ensure adequate budget (at least 10x target CPA)\n"
                output += "5. ⏱️ Allow 6-8 weeks for AI learning\n"
    
                return output
    
            except Exception as e:
                error_msg = ErrorHandler.handle_error(e, context="pmax_insights")
                return f"❌ Failed to get Performance Max insights: {error_msg}"
  • The manager helper that executes GAQL queries via GoogleAdsService to fetch campaign-level metrics (impressions, clicks, cost, conversions, ROAS) and asset-group-level performance data, then returns structured results.
    def get_pmax_insights(
        self,
        customer_id: str,
        campaign_id: str,
        date_range: str = "LAST_30_DAYS"
    ) -> Dict[str, Any]:
        """Get Performance Max campaign insights.
    
        Args:
            customer_id: Customer ID (without hyphens)
            campaign_id: Performance Max campaign ID
            date_range: Date range for metrics
    
        Returns:
            Performance Max insights
        """
        ga_service = self.client.get_service("GoogleAdsService")
    
        # Get campaign performance
        campaign_query = f"""
            SELECT
                campaign.id,
                campaign.name,
                metrics.impressions,
                metrics.clicks,
                metrics.ctr,
                metrics.cost_micros,
                metrics.conversions,
                metrics.conversions_value,
                metrics.all_conversions,
                metrics.all_conversions_value
            FROM campaign
            WHERE campaign.id = {campaign_id}
              AND segments.date DURING {date_range}
        """
    
        campaign_response = ga_service.search(customer_id=customer_id, query=campaign_query)
        campaign_results = list(campaign_response)
    
        if not campaign_results:
            return {'error': 'Campaign not found or no data available'}
    
        row = campaign_results[0]
    
        # Get asset group performance
        asset_group_query = f"""
            SELECT
                asset_group.id,
                asset_group.name,
                asset_group.status,
                metrics.impressions,
                metrics.clicks,
                metrics.conversions
            FROM asset_group
            WHERE campaign.id = {campaign_id}
              AND segments.date DURING {date_range}
        """
    
        asset_group_response = ga_service.search(customer_id=customer_id, query=asset_group_query)
    
        asset_groups = []
        for ag_row in asset_group_response:
            asset_groups.append({
                'asset_group_id': str(ag_row.asset_group.id),
                'asset_group_name': ag_row.asset_group.name,
                'status': ag_row.asset_group.status.name,
                'impressions': ag_row.metrics.impressions,
                'clicks': ag_row.metrics.clicks,
                'conversions': ag_row.metrics.conversions
            })
    
        cost = row.metrics.cost_micros / 1_000_000
        roas = (row.metrics.conversions_value / cost) if cost > 0 else 0
    
        return {
            'campaign_id': str(row.campaign.id),
            'campaign_name': row.campaign.name,
            'metrics': {
                'impressions': row.metrics.impressions,
                'clicks': row.metrics.clicks,
                'ctr': row.metrics.ctr,
                'cost': cost,
                'conversions': row.metrics.conversions,
                'conversion_value': row.metrics.conversions_value,
                'all_conversions': row.metrics.all_conversions,
                'all_conversions_value': row.metrics.all_conversions_value,
                'roas': roas
            },
            'asset_groups': asset_groups,
            'total_asset_groups': len(asset_groups)
        }
  • The registration function that uses the @mcp.tool() decorator to register google_ads_pmax_insights (and other tools) as MCP tools.
    def register_shopping_pmax_tools(mcp):
  • The module registration entry in the _TOOL_MODULES list in the main MCP server file, which triggers dynamic import and registration.
    ("shopping_pmax", "tools.shopping_pmax.mcp_tools_shopping_pmax", "register_shopping_pmax_tools"),
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are given, so the description must fully disclose behavior. It mentions it returns metrics but does not explain auth requirements, rate limits, error handling, or any side effects. The 'all-conversions data' hint is useful but insufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with Args, Returns, Example. Concise but informative. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not detail return fields. However, it lacks mention that the campaign must be a Performance Max campaign and does not clarify the scope of 'all-conversions data'. Adequate but could be more complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds value by explaining customer_id format and date_range options, and provides an example. However, campaign_id is not described, and schema coverage is 0%. The docstring partly compensates for schema gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it retrieves performance insights for Performance Max campaigns, including all-conversions data. However, it does not differentiate from sibling tools like 'campaign_performance' or 'performance_insights', which could cause confusion.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives. The description provides an example but lacks context on selection criteria or prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/johnoconnor0/google-ads-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server