Skip to main content
Glama

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
NameRequiredDescriptionDefault
account_idYes
campaign_idYes
nameYes
optimization_goalYes
billing_eventYes
statusNoPAUSED
daily_budgetNo
lifetime_budgetNo
targetingNo
bid_amountNo
bid_strategyNo
start_timeNo
end_timeNo
dsa_beneficiaryNo
promoted_objectNo
destination_typeNo
is_dynamic_creativeNo
access_tokenNo

Implementation Reference

  • 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)

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/pipeboard-co/meta-ads-mcp'

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