Skip to main content
Glama
johnoconnor0

Google Ads MCP Server

by johnoconnor0
labels_manager.py18.4 kB
""" Google Ads Account Labels Manager Handles label creation, application, and management for organizing campaigns, ad groups, ads, and keywords. """ from typing import Dict, List, Optional, Any from google.ads.googleads.client import GoogleAdsClient from performance_logger import performance_logger from audit_logger import audit_logger class LabelsManager: """Manager for Google Ads account labels.""" def __init__(self, client: GoogleAdsClient): """Initialize the labels manager. Args: client: Google Ads API client instance """ self.client = client def manage_account_labels( self, customer_id: str, action: str, label_name: Optional[str] = None, resource_type: Optional[str] = None, resource_id: Optional[str] = None, label_id: Optional[str] = None, description: Optional[str] = None, background_color: str = "#FFFFFF", text_color: str = "#000000" ) -> Dict[str, Any]: """Manage account labels (create, apply, remove, list). Args: customer_id: Google Ads customer ID (without hyphens) action: Action to perform (create, apply, remove, list, delete) label_name: Label name (required for create, apply, remove) resource_type: Resource type (campaign, ad_group, ad, keyword) - required for apply/remove resource_id: Resource ID - required for apply/remove label_id: Label ID - required for delete description: Optional label description (for create) background_color: Label background color hex code (for create) text_color: Label text color hex code (for create) Returns: Dictionary with action result """ with performance_logger.track_operation(self, 'manage_account_labels'): if action == "create": return self._create_label( customer_id, label_name, description, background_color, text_color ) elif action == "apply": return self._apply_label( customer_id, label_name, resource_type, resource_id ) elif action == "remove": return self._remove_label( customer_id, label_name, resource_type, resource_id ) elif action == "list": return self._list_labels(customer_id, resource_type, resource_id) elif action == "delete": return self._delete_label(customer_id, label_id or label_name) else: raise ValueError(f"Invalid action: {action}. Must be create, apply, remove, list, or delete") def _create_label( self, customer_id: str, label_name: str, description: Optional[str] = None, background_color: str = "#FFFFFF", text_color: str = "#000000" ) -> Dict[str, Any]: """Create a new label. Args: customer_id: Customer ID label_name: Label name description: Optional description background_color: Background color hex text_color: Text color hex Returns: Created label details """ if not label_name: raise ValueError("label_name is required for create action") label_service = self.client.get_service("LabelService") label_operation = self.client.get_type("LabelOperation") label = label_operation.create label.name = label_name if description: label.description = description # Set status label.status = self.client.enums.LabelStatusEnum.ENABLED # Set colors if background_color: label.background_color = background_color if text_color: label.text_color = text_color response = label_service.mutate_labels( customer_id=customer_id, operations=[label_operation] ) label_resource_name = response.results[0].resource_name label_id = label_resource_name.split('/')[-1] audit_logger.log_api_call( operation='create_label', customer_id=customer_id, details={'label_name': label_name, 'label_id': label_id} ) return { 'action': 'created', 'label_id': label_id, 'label_name': label_name, 'description': description, 'background_color': background_color, 'text_color': text_color, 'resource_name': label_resource_name } def _apply_label( self, customer_id: str, label_name: str, resource_type: str, resource_id: str ) -> Dict[str, Any]: """Apply label to a resource. Args: customer_id: Customer ID label_name: Label name resource_type: Resource type (campaign, ad_group, ad, keyword) resource_id: Resource ID Returns: Application confirmation """ if not all([label_name, resource_type, resource_id]): raise ValueError("label_name, resource_type, and resource_id are required for apply action") # Get label ID by name label_id = self._get_label_id_by_name(customer_id, label_name) if not label_id: raise ValueError(f"Label '{label_name}' not found. Create it first.") # Apply label based on resource type if resource_type == "campaign": service_name = "CampaignLabelService" operation_type = "CampaignLabelOperation" label_operation = self.client.get_type(operation_type) label_link = label_operation.create label_link.campaign = self.client.get_service("CampaignService").campaign_path(customer_id, resource_id) label_link.label = self.client.get_service("LabelService").label_path(customer_id, label_id) elif resource_type == "ad_group": service_name = "AdGroupLabelService" operation_type = "AdGroupLabelOperation" label_operation = self.client.get_type(operation_type) label_link = label_operation.create label_link.ad_group = self.client.get_service("AdGroupService").ad_group_path(customer_id, resource_id) label_link.label = self.client.get_service("LabelService").label_path(customer_id, label_id) elif resource_type == "ad": service_name = "AdGroupAdLabelService" operation_type = "AdGroupAdLabelOperation" # For ads, resource_id should be in format "adGroupId_adId" ad_group_id, ad_id = resource_id.split('_') label_operation = self.client.get_type(operation_type) label_link = label_operation.create label_link.ad_group_ad = self.client.get_service("AdGroupAdService").ad_group_ad_path( customer_id, ad_group_id, ad_id ) label_link.label = self.client.get_service("LabelService").label_path(customer_id, label_id) elif resource_type == "keyword": service_name = "AdGroupCriterionLabelService" operation_type = "AdGroupCriterionLabelOperation" # For keywords, resource_id should be in format "adGroupId_criterionId" ad_group_id, criterion_id = resource_id.split('_') label_operation = self.client.get_type(operation_type) label_link = label_operation.create label_link.ad_group_criterion = self.client.get_service("AdGroupCriterionService").ad_group_criterion_path( customer_id, ad_group_id, criterion_id ) label_link.label = self.client.get_service("LabelService").label_path(customer_id, label_id) else: raise ValueError(f"Invalid resource_type: {resource_type}. Must be campaign, ad_group, ad, or keyword") # Apply the label service = self.client.get_service(service_name) response = service.mutate( customer_id=customer_id, operations=[label_operation] ) audit_logger.log_api_call( operation='apply_label', customer_id=customer_id, details={ 'label_name': label_name, 'resource_type': resource_type, 'resource_id': resource_id } ) return { 'action': 'applied', 'label_name': label_name, 'label_id': label_id, 'resource_type': resource_type, 'resource_id': resource_id } def _remove_label( self, customer_id: str, label_name: str, resource_type: str, resource_id: str ) -> Dict[str, Any]: """Remove label from a resource. Args: customer_id: Customer ID label_name: Label name resource_type: Resource type resource_id: Resource ID Returns: Removal confirmation """ if not all([label_name, resource_type, resource_id]): raise ValueError("label_name, resource_type, and resource_id are required for remove action") # Get label ID by name label_id = self._get_label_id_by_name(customer_id, label_name) if not label_id: raise ValueError(f"Label '{label_name}' not found") # Build resource name to remove if resource_type == "campaign": service_name = "CampaignLabelService" operation_type = "CampaignLabelOperation" resource_name = self.client.get_service(service_name).campaign_label_path( customer_id, resource_id, label_id ) elif resource_type == "ad_group": service_name = "AdGroupLabelService" operation_type = "AdGroupLabelOperation" resource_name = self.client.get_service(service_name).ad_group_label_path( customer_id, resource_id, label_id ) elif resource_type == "ad": service_name = "AdGroupAdLabelService" operation_type = "AdGroupAdLabelOperation" ad_group_id, ad_id = resource_id.split('_') resource_name = self.client.get_service(service_name).ad_group_ad_label_path( customer_id, ad_group_id, ad_id, label_id ) elif resource_type == "keyword": service_name = "AdGroupCriterionLabelService" operation_type = "AdGroupCriterionLabelOperation" ad_group_id, criterion_id = resource_id.split('_') resource_name = self.client.get_service(service_name).ad_group_criterion_label_path( customer_id, ad_group_id, criterion_id, label_id ) else: raise ValueError(f"Invalid resource_type: {resource_type}") # Remove the label label_operation = self.client.get_type(operation_type) label_operation.remove = resource_name service = self.client.get_service(service_name) service.mutate( customer_id=customer_id, operations=[label_operation] ) audit_logger.log_api_call( operation='remove_label', customer_id=customer_id, details={ 'label_name': label_name, 'resource_type': resource_type, 'resource_id': resource_id } ) return { 'action': 'removed', 'label_name': label_name, 'resource_type': resource_type, 'resource_id': resource_id } def _list_labels( self, customer_id: str, resource_type: Optional[str] = None, resource_id: Optional[str] = None ) -> Dict[str, Any]: """List all labels or labels for a specific resource. Args: customer_id: Customer ID resource_type: Optional resource type filter resource_id: Optional resource ID filter Returns: List of labels """ if resource_type and resource_id: # Get labels for specific resource query_parts = [] if resource_type == "campaign": query_parts = [ "SELECT campaign_label.label, label.name, label.description,", "label.status, label.background_color, label.text_color", "FROM campaign_label", f"WHERE campaign.id = {resource_id}" ] elif resource_type == "ad_group": query_parts = [ "SELECT ad_group_label.label, label.name, label.description,", "label.status, label.background_color, label.text_color", "FROM ad_group_label", f"WHERE ad_group.id = {resource_id}" ] elif resource_type == "ad": ad_group_id, ad_id = resource_id.split('_') query_parts = [ "SELECT ad_group_ad_label.label, label.name, label.description,", "label.status, label.background_color, label.text_color", "FROM ad_group_ad_label", f"WHERE ad_group.id = {ad_group_id} AND ad_group_ad.ad.id = {ad_id}" ] elif resource_type == "keyword": ad_group_id, criterion_id = resource_id.split('_') query_parts = [ "SELECT ad_group_criterion_label.label, label.name, label.description,", "label.status, label.background_color, label.text_color", "FROM ad_group_criterion_label", f"WHERE ad_group.id = {ad_group_id} AND ad_group_criterion.criterion_id = {criterion_id}" ] else: raise ValueError(f"Invalid resource_type: {resource_type}") query = " ".join(query_parts) else: # Get all labels query = """ SELECT label.id, label.name, label.description, label.status, label.background_color, label.text_color FROM label ORDER BY label.name """ ga_service = self.client.get_service("GoogleAdsService") request = self.client.get_type("SearchGoogleAdsRequest") request.customer_id = customer_id request.query = query.strip() response = ga_service.search(request=request) labels = [] for row in response: label_data = { 'label_id': row.label.id if hasattr(row, 'label') else None, 'label_name': row.label.name, 'description': row.label.description if row.label.description else '', 'status': row.label.status.name, 'background_color': row.label.background_color, 'text_color': row.label.text_color } labels.append(label_data) audit_logger.log_api_call( operation='list_labels', customer_id=customer_id, details={'resource_type': resource_type, 'resource_id': resource_id} ) return { 'action': 'listed', 'total_labels': len(labels), 'labels': labels, 'resource_type': resource_type, 'resource_id': resource_id } def _delete_label( self, customer_id: str, label_identifier: str ) -> Dict[str, Any]: """Delete a label entirely. Args: customer_id: Customer ID label_identifier: Label ID or label name Returns: Deletion confirmation """ if not label_identifier: raise ValueError("label_id or label_name is required for delete action") # Check if identifier is a name or ID if label_identifier.isdigit(): label_id = label_identifier else: label_id = self._get_label_id_by_name(customer_id, label_identifier) if not label_id: raise ValueError(f"Label '{label_identifier}' not found") label_service = self.client.get_service("LabelService") label_operation = self.client.get_type("LabelOperation") label_operation.remove = label_service.label_path(customer_id, label_id) label_service.mutate_labels( customer_id=customer_id, operations=[label_operation] ) audit_logger.log_api_call( operation='delete_label', customer_id=customer_id, details={'label_id': label_id} ) return { 'action': 'deleted', 'label_id': label_id } def _get_label_id_by_name( self, customer_id: str, label_name: str ) -> Optional[str]: """Get label ID by label name. Args: customer_id: Customer ID label_name: Label name Returns: Label ID if found, None otherwise """ query = f""" SELECT label.id FROM label WHERE label.name = '{label_name}' LIMIT 1 """ ga_service = self.client.get_service("GoogleAdsService") request = self.client.get_type("SearchGoogleAdsRequest") request.customer_id = customer_id request.query = query try: response = ga_service.search(request=request) for row in response: return str(row.label.id) except Exception: return None return None def create_labels_manager(client: GoogleAdsClient) -> LabelsManager: """Create a labels manager instance. Args: client: Google Ads client Returns: Labels manager instance """ return LabelsManager(client)

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