Skip to main content
Glama
MatiousCorp

Google Ad Manager MCP Server

by MatiousCorp
verification.py9.85 kB
"""Verification tools for Google Ad Manager.""" import logging from typing import Optional from ..client import get_gam_client from ..utils import safe_get, extract_date logger = logging.getLogger(__name__) def verify_line_item_setup(line_item_id: int) -> dict: """Verify line item setup including creative placeholders and associations. Args: line_item_id: The line item ID to verify Returns: dict with verification results """ client = get_gam_client() result = { "line_item_id": line_item_id, "line_item": None, "creative_placeholders": [], "creative_associations": [], "issues": [], "status": "OK" } # Get line item details using bind variable line_item_service = client.get_service('LineItemService') statement = client.create_statement() statement = statement.Where("id = :id").WithBindVariable('id', line_item_id) response = line_item_service.getLineItemsByStatement(statement.ToStatement()) if 'results' not in response or len(response['results']) == 0: return {"error": f"Line item {line_item_id} not found"} line_item = response['results'][0] result["line_item"] = { "id": line_item['id'], "name": line_item['name'], "status": line_item['status'], "type": line_item.get('lineItemType'), "order_id": line_item['orderId'] } # Extract creative placeholders if line_item.get('creativePlaceholders'): for ph in line_item['creativePlaceholders']: size = ph.get('size', {}) result["creative_placeholders"].append({ "width": size.get('width'), "height": size.get('height'), "size_string": f"{size.get('width')}x{size.get('height')}" }) # Get creative associations using bind variable lica_service = client.get_service('LineItemCreativeAssociationService') lica_statement = client.create_statement() lica_statement = lica_statement.Where( "lineItemId = :lineItemId" ).WithBindVariable('lineItemId', line_item_id) lica_response = lica_service.getLineItemCreativeAssociationsByStatement(lica_statement.ToStatement()) creative_service = client.get_service('CreativeService') if 'results' in lica_response: for lica in lica_response['results']: creative_id = lica['creativeId'] status = lica.get('status', 'UNKNOWN') # Get creative details using bind variable creative_statement = client.create_statement() creative_statement = creative_statement.Where( "id = :id" ).WithBindVariable('id', creative_id) creative_response = creative_service.getCreativesByStatement(creative_statement.ToStatement()) creative_info = { "creative_id": creative_id, "association_status": status, "creative_name": None, "creative_size": None, "size_overrides": [] } if 'results' in creative_response and len(creative_response['results']) > 0: creative = creative_response['results'][0] creative_size = creative.get('size', {}) creative_info["creative_name"] = creative.get('name') creative_info["creative_size"] = f"{creative_size.get('width')}x{creative_size.get('height')}" # Check for size overrides in LICA if lica.get('sizes'): for size in lica['sizes']: creative_info["size_overrides"].append( f"{size.get('width')}x{size.get('height')}" ) result["creative_associations"].append(creative_info) # Analyze for issues placeholder_sizes = set(p["size_string"] for p in result["creative_placeholders"]) for assoc in result["creative_associations"]: creative_size = assoc["creative_size"] size_overrides = assoc["size_overrides"] # Determine effective sizes this creative targets effective_sizes = set(size_overrides) if size_overrides else {creative_size} # Check if any effective size matches a placeholder if not effective_sizes.intersection(placeholder_sizes): result["issues"].append({ "type": "SIZE_MISMATCH", "creative_id": assoc["creative_id"], "creative_size": creative_size, "size_overrides": size_overrides, "available_placeholders": list(placeholder_sizes), "message": f"Creative {assoc['creative_id']} ({creative_size}) doesn't match any placeholder" }) # Set overall status if result["issues"]: result["status"] = "ISSUES_FOUND" elif not result["creative_associations"]: result["status"] = "NO_CREATIVES" result["issues"].append({ "type": "NO_CREATIVES", "message": "Line item has no creative associations" }) # Summary result["summary"] = { "placeholder_count": len(result["creative_placeholders"]), "creative_count": len(result["creative_associations"]), "issue_count": len(result["issues"]), "placeholder_sizes": list(placeholder_sizes) } return result def check_line_item_delivery_status(line_item_id: int) -> dict: """Check detailed delivery status for a line item. Args: line_item_id: The line item ID to check Returns: dict with delivery status details """ client = get_gam_client() line_item_service = client.get_service('LineItemService') statement = client.create_statement() statement = statement.Where("id = :id").WithBindVariable('id', line_item_id) response = line_item_service.getLineItemsByStatement(statement.ToStatement()) if 'results' not in response or len(response['results']) == 0: return {"error": f"Line item {line_item_id} not found"} li = response['results'][0] stats = li.get('stats', {}) or {} primary_goal = li.get('primaryGoal', {}) or {} # Calculate progress goal_units = primary_goal.get('units', 0) or 0 impressions = stats.get('impressionsDelivered', 0) or 0 progress_pct = 0 if goal_units > 0: progress_pct = round((impressions / goal_units) * 100, 2) return { "line_item_id": li['id'], "name": li['name'], "status": li['status'], "type": li.get('lineItemType'), "delivery": { "impressions_delivered": impressions, "clicks_delivered": stats.get('clicksDelivered', 0) or 0, "goal_type": primary_goal.get('goalType'), "goal_unit_type": primary_goal.get('unitType'), "goal_units": goal_units, "progress_percent": progress_pct }, "needs_creatives": li.get('isMissingCreatives', False), "is_set_to_deliver": li.get('isSetTopBoxEnabled', False), "delivery_rate_type": li.get('deliveryRateType') } def verify_order_setup(order_id: int) -> dict: """Verify complete order setup including all line items. Args: order_id: The order ID to verify Returns: dict with complete order verification """ client = get_gam_client() # Get order using bind variable order_service = client.get_service('OrderService') order_statement = client.create_statement() order_statement = order_statement.Where("id = :id").WithBindVariable('id', order_id) order_response = order_service.getOrdersByStatement(order_statement.ToStatement()) if 'results' not in order_response or len(order_response['results']) == 0: return {"error": f"Order {order_id} not found"} order = order_response['results'][0] result = { "order_id": order['id'], "order_name": order['name'], "order_status": order['status'], "advertiser_id": order.get('advertiserId'), "line_items": [], "issues": [], "overall_status": "OK" } # Get all line items using bind variable line_item_service = client.get_service('LineItemService') li_statement = client.create_statement() li_statement = li_statement.Where("orderId = :orderId").WithBindVariable('orderId', order_id) li_response = line_item_service.getLineItemsByStatement(li_statement.ToStatement()) if 'results' in li_response: for li in li_response['results']: li_verification = verify_line_item_setup(li['id']) if "error" in li_verification: result["line_items"].append({ "id": li['id'], "name": li['name'], "error": li_verification["error"] }) else: result["line_items"].append({ "id": li['id'], "name": li_verification["line_item"]["name"], "status": li_verification["line_item"]["status"], "creative_count": li_verification["summary"]["creative_count"], "issue_count": li_verification["summary"]["issue_count"], "issues": li_verification["issues"] }) if li_verification["issues"]: result["issues"].extend([ {**issue, "line_item_id": li['id'], "line_item_name": li['name']} for issue in li_verification["issues"] ]) # Set overall status if result["issues"]: result["overall_status"] = "ISSUES_FOUND" result["summary"] = { "line_item_count": len(result["line_items"]), "total_issues": len(result["issues"]) } return result

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/MatiousCorp/google-ad-manager-mcp'

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