create_adset
Create a new Meta Ads ad set by specifying targeting, budget, bidding, and optimization parameters to reach specific audiences within campaigns.
Instructions
Create a new ad set in a Meta Ads account.
Args:
account_id: Meta Ads account ID (format: act_XXXXXXXXX)
campaign_id: Meta Ads campaign ID this ad set belongs to
name: Ad set name
optimization_goal: Conversion optimization goal (e.g., 'LINK_CLICKS', 'REACH', 'CONVERSIONS', 'APP_INSTALLS')
billing_event: How you're charged (e.g., 'IMPRESSIONS', 'LINK_CLICKS')
status: Initial ad set status (default: PAUSED)
daily_budget: Daily budget in account currency (in cents) as a string
lifetime_budget: Lifetime budget in account currency (in cents) as a string
targeting: Targeting specifications including age, location, interests, etc.
Use targeting_automation.advantage_audience=1 for automatic audience finding
bid_amount: Bid amount in account currency (in cents)
bid_strategy: Bid strategy (e.g., 'LOWEST_COST', 'LOWEST_COST_WITH_BID_CAP')
start_time: Start time in ISO 8601 format (e.g., '2023-12-01T12:00:00-0800')
end_time: End time in ISO 8601 format
dsa_beneficiary: DSA beneficiary (person/organization benefiting from ads) for European compliance
promoted_object: Mobile app configuration for APP_INSTALLS campaigns. Required fields: application_id, object_store_url.
Optional fields: custom_event_type, pixel_id, page_id.
Example: {"application_id": "123456789012345", "object_store_url": "https://apps.apple.com/app/id123456789"}
destination_type: Where users are directed after clicking the ad (e.g., 'APP_STORE', 'DEEPLINK', 'APP_INSTALL', 'ON_AD').
Required for mobile app campaigns and lead generation campaigns.
Use 'ON_AD' for lead generation campaigns where user interaction happens within the ad.
is_dynamic_creative: Enable Dynamic Creative for this ad set (required when using dynamic creatives with asset_feed_spec/dynamic_creative_spec).
access_token: Meta API access token (optional - will use cached token if not provided)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | Yes | ||
| campaign_id | Yes | ||
| name | Yes | ||
| optimization_goal | Yes | ||
| billing_event | Yes | ||
| status | No | PAUSED | |
| daily_budget | No | ||
| lifetime_budget | No | ||
| targeting | No | ||
| bid_amount | No | ||
| bid_strategy | No | ||
| start_time | No | ||
| end_time | No | ||
| dsa_beneficiary | No | ||
| promoted_object | No | ||
| destination_type | No | ||
| is_dynamic_creative | No | ||
| access_token | No |
Implementation Reference
- meta_ads_mcp/core/adsets.py:84-292 (handler)The core handler function for the 'create_adset' MCP tool. Decorated with @mcp_server.tool() for registration and @meta_api_tool for API handling. Performs validation on inputs like account_id, campaign_id, budgets, targeting, DSA beneficiary, and mobile app parameters for APP_INSTALLS. Makes POST request to Meta Ads API endpoint '{account_id}/adsets' using make_api_request. Handles various errors including permissions and compliance issues.@mcp_server.tool() @meta_api_tool async def create_adset( account_id: str, campaign_id: str, name: str, optimization_goal: str, billing_event: str, status: str = "PAUSED", daily_budget: Optional[int] = None, lifetime_budget: Optional[int] = None, targeting: Optional[Dict[str, Any]] = None, bid_amount: Optional[int] = None, bid_strategy: Optional[str] = None, start_time: Optional[str] = None, end_time: Optional[str] = None, dsa_beneficiary: Optional[str] = None, promoted_object: Optional[Dict[str, Any]] = None, destination_type: Optional[str] = None, is_dynamic_creative: Optional[bool] = None, access_token: Optional[str] = None ) -> str: """ Create a new ad set in a Meta Ads account. Args: account_id: Meta Ads account ID (format: act_XXXXXXXXX) campaign_id: Meta Ads campaign ID this ad set belongs to name: Ad set name optimization_goal: Conversion optimization goal (e.g., 'LINK_CLICKS', 'REACH', 'CONVERSIONS', 'APP_INSTALLS') billing_event: How you're charged (e.g., 'IMPRESSIONS', 'LINK_CLICKS') status: Initial ad set status (default: PAUSED) daily_budget: Daily budget in account currency (in cents) as a string lifetime_budget: Lifetime budget in account currency (in cents) as a string targeting: Targeting specifications including age, location, interests, etc. Use targeting_automation.advantage_audience=1 for automatic audience finding bid_amount: Bid amount in account currency (in cents) bid_strategy: Bid strategy (e.g., 'LOWEST_COST', 'LOWEST_COST_WITH_BID_CAP') start_time: Start time in ISO 8601 format (e.g., '2023-12-01T12:00:00-0800') end_time: End time in ISO 8601 format dsa_beneficiary: DSA beneficiary (person/organization benefiting from ads) for European compliance promoted_object: Mobile app configuration for APP_INSTALLS campaigns. Required fields: application_id, object_store_url. Optional fields: custom_event_type, pixel_id, page_id. Example: {"application_id": "123456789012345", "object_store_url": "https://apps.apple.com/app/id123456789"} destination_type: Where users are directed after clicking the ad (e.g., 'APP_STORE', 'DEEPLINK', 'APP_INSTALL', 'ON_AD'). Required for mobile app campaigns and lead generation campaigns. Use 'ON_AD' for lead generation campaigns where user interaction happens within the ad. is_dynamic_creative: Enable Dynamic Creative for this ad set (required when using dynamic creatives with asset_feed_spec/dynamic_creative_spec). access_token: Meta API access token (optional - will use cached token if not provided) """ # Check required parameters if not account_id: return json.dumps({"error": "No account ID provided"}, indent=2) if not campaign_id: return json.dumps({"error": "No campaign ID provided"}, indent=2) if not name: return json.dumps({"error": "No ad set name provided"}, indent=2) if not optimization_goal: return json.dumps({"error": "No optimization goal provided"}, indent=2) if not billing_event: return json.dumps({"error": "No billing event provided"}, indent=2) # Validate mobile app parameters for APP_INSTALLS campaigns if optimization_goal == "APP_INSTALLS": if not promoted_object: return json.dumps({ "error": "promoted_object is required for APP_INSTALLS optimization goal", "details": "Mobile app campaigns must specify which app is being promoted", "required_fields": ["application_id", "object_store_url"] }, indent=2) # Validate promoted_object structure if not isinstance(promoted_object, dict): return json.dumps({ "error": "promoted_object must be a dictionary", "example": {"application_id": "123456789012345", "object_store_url": "https://apps.apple.com/app/id123456789"} }, indent=2) # Validate required promoted_object fields if "application_id" not in promoted_object: return json.dumps({ "error": "promoted_object missing required field: application_id", "details": "application_id is the Facebook app ID for your mobile app" }, indent=2) if "object_store_url" not in promoted_object: return json.dumps({ "error": "promoted_object missing required field: object_store_url", "details": "object_store_url should be the App Store or Google Play URL for your app" }, indent=2) # Validate store URL format store_url = promoted_object["object_store_url"] valid_store_patterns = [ "apps.apple.com", # iOS App Store "play.google.com", # Google Play Store "itunes.apple.com" # Alternative iOS format ] if not any(pattern in store_url for pattern in valid_store_patterns): return json.dumps({ "error": "Invalid object_store_url format", "details": "URL must be from App Store (apps.apple.com) or Google Play (play.google.com)", "provided_url": store_url }, indent=2) # Validate destination_type if provided if destination_type: valid_destination_types = ["APP_STORE", "DEEPLINK", "APP_INSTALL", "ON_AD"] if destination_type not in valid_destination_types: return json.dumps({ "error": f"Invalid destination_type: {destination_type}", "valid_values": valid_destination_types }, indent=2) # Basic targeting is required if not provided if not targeting: targeting = { "age_min": 18, "age_max": 65, "geo_locations": {"countries": ["US"]}, "targeting_automation": {"advantage_audience": 1} } endpoint = f"{account_id}/adsets" params = { "name": name, "campaign_id": campaign_id, "status": status, "optimization_goal": optimization_goal, "billing_event": billing_event, "targeting": json.dumps(targeting) # Properly format as JSON string } # Convert budget values to strings if they aren't already if daily_budget is not None: params["daily_budget"] = str(daily_budget) if lifetime_budget is not None: params["lifetime_budget"] = str(lifetime_budget) # Add other parameters if provided if bid_amount is not None: params["bid_amount"] = str(bid_amount) if bid_strategy: params["bid_strategy"] = bid_strategy if start_time: params["start_time"] = start_time if end_time: params["end_time"] = end_time # Add DSA beneficiary if provided if dsa_beneficiary: params["dsa_beneficiary"] = dsa_beneficiary # Add mobile app parameters if provided if promoted_object: params["promoted_object"] = json.dumps(promoted_object) if destination_type: params["destination_type"] = destination_type # Enable Dynamic Creative if requested if is_dynamic_creative is not None: params["is_dynamic_creative"] = "true" if bool(is_dynamic_creative) else "false" try: data = await make_api_request(endpoint, access_token, params, method="POST") return json.dumps(data, indent=2) except Exception as e: error_msg = str(e) # Enhanced error handling for DSA beneficiary issues if "permission" in error_msg.lower() or "insufficient" in error_msg.lower(): return json.dumps({ "error": "Insufficient permissions to set DSA beneficiary. Please ensure you have business_management permissions.", "details": error_msg, "params_sent": params, "permission_required": True }, indent=2) elif "dsa_beneficiary" in error_msg.lower() and ("not supported" in error_msg.lower() or "parameter" in error_msg.lower()): return json.dumps({ "error": "DSA beneficiary parameter not supported in this API version. Please set DSA beneficiary manually in Facebook Ads Manager.", "details": error_msg, "params_sent": params, "manual_setup_required": True }, indent=2) elif "benefits from ads" in error_msg or "DSA beneficiary" in error_msg: return json.dumps({ "error": "DSA beneficiary required for European compliance. Please provide the person or organization that benefits from ads in this ad set.", "details": error_msg, "params_sent": params, "dsa_required": True }, indent=2) else: return json.dumps({ "error": "Failed to create ad set", "details": error_msg, "params_sent": params }, indent=2)