Skip to main content
Glama

update_ad_creative

Modify existing Meta ad creative content and settings, including copy, headlines, descriptions, and call-to-action elements.

Instructions

Update an existing ad creative with new content or settings.

Args:
    creative_id: Meta Ads creative ID to update
    access_token: Meta API access token (optional - will use cached token if not provided)
    name: New creative name
    message: New ad copy/text
    headline: Single headline for simple ads (cannot be used with headlines)
    headlines: New list of headlines for dynamic creative testing (cannot be used with headline)
    description: Single description for simple ads (cannot be used with descriptions)
    descriptions: New list of descriptions for dynamic creative testing (cannot be used with description)
    dynamic_creative_spec: New dynamic creative optimization settings
    call_to_action_type: New call to action button type
    lead_gen_form_id: Lead generation form ID for lead generation campaigns. Required when using
                     lead generation CTAs like 'SIGN_UP', 'GET_OFFER', 'SUBSCRIBE', etc.

Returns:
    JSON response with updated creative details

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
creative_idYes
access_tokenNo
nameNo
messageNo
headlineNo
headlinesNo
descriptionNo
descriptionsNo
dynamic_creative_specNo
call_to_action_typeNo
lead_gen_form_idNo

Implementation Reference

  • The primary handler implementation for the update_ad_creative MCP tool. It performs validation on inputs like headlines and descriptions, constructs the appropriate object_story_spec or asset_feed_spec for dynamic creatives, and makes a POST request to the Meta Ads API to update the creative. Includes decorators for MCP registration (@mcp_server.tool()) and API handling (@meta_api_tool).
    @mcp_server.tool()
    @meta_api_tool
    async def update_ad_creative(
        creative_id: str,
        access_token: Optional[str] = None,
        name: Optional[str] = None,
        message: Optional[str] = None,
        headline: Optional[str] = None,
        headlines: Optional[List[str]] = None,
        description: Optional[str] = None,
        descriptions: Optional[List[str]] = None,
        dynamic_creative_spec: Optional[Dict[str, Any]] = None,
        call_to_action_type: Optional[str] = None,
        lead_gen_form_id: Optional[str] = None
    ) -> str:
        """
        Update an existing ad creative with new content or settings.
        
        Args:
            creative_id: Meta Ads creative ID to update
            access_token: Meta API access token (optional - will use cached token if not provided)
            name: New creative name
            message: New ad copy/text
            headline: Single headline for simple ads (cannot be used with headlines)
            headlines: New list of headlines for dynamic creative testing (cannot be used with headline)
            description: Single description for simple ads (cannot be used with descriptions)
            descriptions: New list of descriptions for dynamic creative testing (cannot be used with description)
            dynamic_creative_spec: New dynamic creative optimization settings
            call_to_action_type: New call to action button type
            lead_gen_form_id: Lead generation form ID for lead generation campaigns. Required when using
                             lead generation CTAs like 'SIGN_UP', 'GET_OFFER', 'SUBSCRIBE', etc.
        
        Returns:
            JSON response with updated creative details
        """
        # Check required parameters
        if not creative_id:
            return json.dumps({"error": "No creative ID provided"}, indent=2)
        
        # Validate headline/description parameters - cannot mix simple and complex
        if headline and headlines:
            return json.dumps({"error": "Cannot specify both 'headline' and 'headlines'. Use 'headline' for single headline or 'headlines' for multiple."}, indent=2)
        
        if description and descriptions:
            return json.dumps({"error": "Cannot specify both 'description' and 'descriptions'. Use 'description' for single description or 'descriptions' for multiple."}, indent=2)
        
        # Validate dynamic creative parameters (plural forms only)
        if headlines:
            if len(headlines) > 5:
                return json.dumps({"error": "Maximum 5 headlines allowed for dynamic creatives"}, indent=2)
            for i, h in enumerate(headlines):
                if len(h) > 40:
                    return json.dumps({"error": f"Headline {i+1} exceeds 40 character limit"}, indent=2)
        
        if descriptions:
            if len(descriptions) > 5:
                return json.dumps({"error": "Maximum 5 descriptions allowed for dynamic creatives"}, indent=2)
            for i, d in enumerate(descriptions):
                if len(d) > 125:
                    return json.dumps({"error": f"Description {i+1} exceeds 125 character limit"}, indent=2)
        
        # Prepare the update data
        update_data = {}
        
        if name:
            update_data["name"] = name
        
        # Choose between asset_feed_spec (dynamic creative) or object_story_spec (traditional)
        # ONLY use asset_feed_spec when user explicitly provides plural parameters (headlines/descriptions)
        if headlines or descriptions or dynamic_creative_spec:
            # Handle dynamic creative assets via asset_feed_spec
            asset_feed_spec = {}
            
            # Add required ad_formats field for dynamic creatives
            asset_feed_spec["ad_formats"] = ["SINGLE_IMAGE"]
            
            # Handle headlines - Meta API uses "titles" not "headlines" in asset_feed_spec
            if headlines:
                asset_feed_spec["titles"] = [{"text": headline_text} for headline_text in headlines]
                
            # Handle descriptions  
            if descriptions:
                asset_feed_spec["descriptions"] = [{"text": description_text} for description_text in descriptions]
            
            # Add message as bodies - Meta API uses "bodies" not "primary_texts" in asset_feed_spec
            if message:
                asset_feed_spec["bodies"] = [{"text": message}]
            
            # Add call_to_action_types if provided
            if call_to_action_type:
                asset_feed_spec["call_to_action_types"] = [call_to_action_type]
            
            update_data["asset_feed_spec"] = asset_feed_spec
        else:
            # Use traditional object_story_spec with link_data for simple creatives
            if message or headline or description or call_to_action_type or lead_gen_form_id:
                update_data["object_story_spec"] = {"link_data": {}}
                
                if message:
                    update_data["object_story_spec"]["link_data"]["message"] = message
                
                # Add headline (singular) to link_data
                if headline:
                    update_data["object_story_spec"]["link_data"]["name"] = headline
                
                # Add description (singular) to link_data
                if description:
                    update_data["object_story_spec"]["link_data"]["description"] = description
                
                # Add call_to_action to link_data for simple creatives
                if call_to_action_type or lead_gen_form_id:
                    cta_data = {}
                    if call_to_action_type:
                        cta_data["type"] = call_to_action_type
                    
                    # Add lead form ID to value object if provided (required for lead generation campaigns)
                    if lead_gen_form_id:
                        cta_data["value"] = {"lead_gen_form_id": lead_gen_form_id}
                    
                    if cta_data:
                        update_data["object_story_spec"]["link_data"]["call_to_action"] = cta_data
        
        # Add dynamic creative spec if provided
        if dynamic_creative_spec:
            update_data["dynamic_creative_spec"] = dynamic_creative_spec
        
        # Prepare the API endpoint for updating the creative
        endpoint = f"{creative_id}"
        
        try:
            # Make API request to update the creative
            data = await make_api_request(endpoint, access_token, update_data, method="POST")
            
            # If successful, get more details about the updated creative
            if "id" in data:
                creative_endpoint = f"{creative_id}"
                creative_params = {
                    "fields": "id,name,status,thumbnail_url,image_url,image_hash,object_story_spec,url_tags,link_url,dynamic_creative_spec"
                }
                
                creative_details = await make_api_request(creative_endpoint, access_token, creative_params)
                return json.dumps({
                    "success": True,
                    "creative_id": creative_id,
                    "details": creative_details
                }, indent=2)
            
            return json.dumps(data, indent=2)
        
        except Exception as e:
            return json.dumps({
                "error": "Failed to update ad creative",
                "details": str(e),
                "update_data_sent": update_data
            }, 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