Skip to main content
Glama
audience_tools.py13.8 kB
"""Audience management tools for TikTok Ads MCP server.""" from typing import Any, Dict, List, Optional from ..tiktok_client import TikTokAdsClient class AudienceTools: """Tools for managing TikTok Ads audiences and targeting options.""" def __init__(self, client: TikTokAdsClient): self.client = client async def get_custom_audiences(self, limit: int = 10) -> Dict[str, Any]: """List custom audiences for the advertiser. Args: limit: Maximum number of audiences to return Returns: List of custom audiences with metadata """ try: result = await self.client.get_custom_audiences(limit=limit) audiences = result.get("data", {}).get("list", []) # Format audiences for better readability formatted_audiences = [] for audience in audiences: formatted_audience = { "audience_id": audience.get("custom_audience_id"), "audience_name": audience.get("name"), "audience_type": audience.get("audience_type"), "size": audience.get("approximate_count", 0), "status": audience.get("status"), "data_source": { "type": audience.get("source_type"), "file_paths": audience.get("file_paths", []), "pixel_id": audience.get("pixel_id"), }, "retention_days": audience.get("retention_in_days"), "share_status": audience.get("share_status"), "create_time": audience.get("create_time"), "modify_time": audience.get("modify_time"), } formatted_audiences.append(formatted_audience) # Categorize by audience type type_summary = {} size_summary = {"small": 0, "medium": 0, "large": 0} for audience in formatted_audiences: # Type summary aud_type = audience["audience_type"] type_summary[aud_type] = type_summary.get(aud_type, 0) + 1 # Size summary size = audience["size"] if size < 1000: size_summary["small"] += 1 elif size < 10000: size_summary["medium"] += 1 else: size_summary["large"] += 1 return { "success": True, "audiences": formatted_audiences, "total_count": len(formatted_audiences), "summary": { "by_type": type_summary, "by_size": size_summary, }, "message": f"Retrieved {len(formatted_audiences)} custom audiences" } except Exception as e: return { "success": False, "error": str(e), "message": "Failed to retrieve custom audiences" } async def get_targeting_options( self, type: str, country_code: Optional[str] = None, ) -> Dict[str, Any]: """Get available targeting options for campaigns. Args: type: Type of targeting options (INTEREST, BEHAVIOR, DEMOGRAPHICS, LOCATION) country_code: Country code for location-specific options Returns: Available targeting options """ try: result = await self.client.get_targeting_options( option_type=type, country_code=country_code ) targeting_options = result.get("data", {}).get("list", []) # Format targeting options based on type if type == "INTEREST": formatted_options = self._format_interest_options(targeting_options) elif type == "BEHAVIOR": formatted_options = self._format_behavior_options(targeting_options) elif type == "DEMOGRAPHICS": formatted_options = self._format_demographic_options(targeting_options) elif type == "LOCATION": formatted_options = self._format_location_options(targeting_options) else: formatted_options = targeting_options return { "success": True, "targeting_type": type, "country_code": country_code, "options": formatted_options, "total_count": len(formatted_options), "message": f"Retrieved {len(formatted_options)} {type.lower()} targeting options" } except Exception as e: return { "success": False, "error": str(e), "targeting_type": type, "country_code": country_code, "message": f"Failed to retrieve {type.lower()} targeting options" } def _format_interest_options(self, options: List[Dict[str, Any]]) -> List[Dict[str, Any]]: """Format interest targeting options.""" formatted = [] for option in options: formatted.append({ "interest_id": option.get("interest_id"), "name": option.get("name"), "category": option.get("category"), "audience_size": option.get("audience_size", 0), "path": option.get("path", []), "is_common": option.get("is_common", False), }) return formatted def _format_behavior_options(self, options: List[Dict[str, Any]]) -> List[Dict[str, Any]]: """Format behavior targeting options.""" formatted = [] for option in options: formatted.append({ "behavior_id": option.get("behavior_id"), "name": option.get("name"), "type": option.get("behavior_type"), "audience_size": option.get("audience_size", 0), "description": option.get("description"), }) return formatted def _format_demographic_options(self, options: List[Dict[str, Any]]) -> List[Dict[str, Any]]: """Format demographic targeting options.""" formatted = [] for option in options: formatted.append({ "demographic_id": option.get("demographic_id"), "name": option.get("name"), "type": option.get("demographic_type"), "values": option.get("values", []), }) return formatted def _format_location_options(self, options: List[Dict[str, Any]]) -> List[Dict[str, Any]]: """Format location targeting options.""" formatted = [] for option in options: formatted.append({ "location_id": option.get("location_id"), "name": option.get("name"), "type": option.get("location_type"), "country": option.get("country"), "region": option.get("region"), "audience_size": option.get("audience_size", 0), }) return formatted async def create_custom_audience( self, audience_name: str, audience_type: str, data_source: Dict[str, Any], retention_days: int = 180, ) -> Dict[str, Any]: """Create a new custom audience. Args: audience_name: Name for the custom audience audience_type: Type of audience (CUSTOMER_FILE, WEBSITE_TRAFFIC, etc.) data_source: Data source configuration retention_days: How long to retain audience data Returns: Created custom audience information """ try: # Prepare audience data based on type audience_data = { "name": audience_name, "audience_type": audience_type, "retention_in_days": retention_days, } # Add data source specific fields if audience_type == "CUSTOMER_FILE": audience_data.update({ "file_paths": data_source.get("file_paths", []), "calculate_type": data_source.get("calculate_type", "UNION"), }) elif audience_type == "WEBSITE_TRAFFIC": audience_data.update({ "pixel_id": data_source.get("pixel_id"), "website_traffic_rules": data_source.get("rules", []), }) elif audience_type == "APP_ACTIVITY": audience_data.update({ "app_id": data_source.get("app_id"), "app_activity_rules": data_source.get("rules", []), }) # Note: This is a placeholder - actual implementation would call TikTok's audience creation API audience_id = f"audience_{int(__import__('time').time())}" return { "success": True, "audience_id": audience_id, "audience_name": audience_name, "audience_type": audience_type, "retention_days": retention_days, "data_source": data_source, "estimated_size": "Processing...", "status": "CREATING", "message": f"Successfully initiated creation of custom audience: {audience_name}" } except Exception as e: return { "success": False, "error": str(e), "audience_name": audience_name, "message": f"Failed to create custom audience: {audience_name}" } async def analyze_audience_insights( self, audience_id: str, campaign_ids: Optional[List[str]] = None, ) -> Dict[str, Any]: """Analyze audience performance and provide insights. Args: audience_id: Custom audience ID to analyze campaign_ids: Optional list of campaign IDs to analyze audience performance Returns: Audience insights and recommendations """ try: # This would typically call TikTok's audience insights API # For now, return mock analysis data audience_insights = { "audience_id": audience_id, "audience_size": 45000, "growth_trend": "+12% last 30 days", "demographics": { "age_distribution": { "18-24": 35, "25-34": 40, "35-44": 20, "45+": 5 }, "gender_distribution": { "male": 45, "female": 55 }, "top_locations": [ {"country": "US", "percentage": 60}, {"country": "CA", "percentage": 25}, {"country": "GB", "percentage": 15} ] }, "interests": [ {"name": "Technology", "affinity_score": 95}, {"name": "Gaming", "affinity_score": 88}, {"name": "Entertainment", "affinity_score": 82} ], "behaviors": [ {"name": "Frequent App Users", "percentage": 75}, {"name": "Online Shoppers", "percentage": 68}, {"name": "Video Content Consumers", "percentage": 92} ] } # Generate performance insights if campaign data is available performance_insights = [] recommendations = [] if campaign_ids: performance_insights = [ "Audience shows 35% higher engagement than account average", "Best performing time: weekday evenings (6-9 PM)", "Video content generates 2.3x more engagement than images" ] recommendations = [ "Increase budget allocation for this high-performing audience", "Create lookalike audiences based on this segment", "Focus on video creative formats for this audience" ] else: recommendations = [ "Test this audience across different campaign objectives", "Create similar audiences to expand reach", "Monitor audience growth and refresh data sources regularly" ] return { "success": True, "audience_insights": audience_insights, "performance_insights": performance_insights, "recommendations": recommendations, "campaigns_analyzed": len(campaign_ids) if campaign_ids else 0, "message": f"Generated comprehensive insights for audience {audience_id}" } except Exception as e: return { "success": False, "error": str(e), "audience_id": audience_id, "message": "Failed to analyze audience insights" }

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/AdsMCP/tiktok-ads-mcp-server'

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