Skip to content

Commit 00d0925

Browse files
committed
feat: add creative_features_spec parameter to create_ad_creative
Introduce creative_features_spec to allow for Advantage+ Creative feature opt-ins/opt-outs. This new parameter enables control over individual creative enhancements such as image touchups and text optimizations. Additionally, handle string input for creative_features_spec by parsing it into a dictionary format.
1 parent b10c54b commit 00d0925

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

meta_ads_mcp/core/ads.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,8 @@ async def create_ad_creative(
943943
lead_gen_form_id: Optional[str] = None,
944944
instagram_actor_id: Optional[str] = None,
945945
ad_formats: Optional[List[str]] = None,
946-
asset_customization_rules: Optional[List[Dict[str, Any]]] = None
946+
asset_customization_rules: Optional[List[Dict[str, Any]]] = None,
947+
creative_features_spec: Optional[Dict[str, Any]] = None
947948
) -> str:
948949
"""
949950
Create a new ad creative using an uploaded image hash or video ID.
@@ -989,6 +990,13 @@ async def create_ad_creative(
989990
["AUTOMATIC_FORMAT"] (Flexible format). For video creatives, defaults to
990991
["SINGLE_VIDEO"]. Otherwise defaults to ["SINGLE_IMAGE"].
991992
asset_customization_rules: List of placement-specific asset overrides for asset_feed_spec.
993+
creative_features_spec: Advantage+ Creative feature opt-ins/opt-outs. Controls individual
994+
creative enhancements like image_touchups, text_optimizations, inline_comment,
995+
add_text_overlay, music, 3d_animation, etc. Each feature is a dict with
996+
"enroll_status" set to "OPT_IN" or "OPT_OUT".
997+
Example: {"image_touchups": {"enroll_status": "OPT_IN"},
998+
"inline_comment": {"enroll_status": "OPT_IN"}}
999+
Sent to Meta as degrees_of_freedom_spec.creative_features_spec.
9921000
Lets you assign different images or videos to specific placement groups
9931001
(e.g., feed vs. stories). Only valid with image_hashes or plural asset params.
9941002
Each rule uses a user-friendly format that is automatically translated to
@@ -1024,6 +1032,14 @@ async def create_ad_creative(
10241032
except (json.JSONDecodeError, TypeError):
10251033
pass
10261034

1035+
if isinstance(creative_features_spec, str):
1036+
try:
1037+
_parsed = json.loads(creative_features_spec)
1038+
if isinstance(_parsed, dict):
1039+
creative_features_spec = _parsed
1040+
except (json.JSONDecodeError, TypeError):
1041+
pass
1042+
10271043
for _param_name, _param_val in [
10281044
('image_hashes', image_hashes),
10291045
('messages', messages),
@@ -1365,6 +1381,13 @@ async def create_ad_creative(
13651381
if dynamic_creative_spec:
13661382
creative_data["dynamic_creative_spec"] = dynamic_creative_spec
13671383

1384+
# Add Advantage+ Creative feature opt-ins if provided.
1385+
# Only sent when the user explicitly passes creative_features_spec.
1386+
if creative_features_spec:
1387+
creative_data["degrees_of_freedom_spec"] = {
1388+
"creative_features_spec": creative_features_spec
1389+
}
1390+
13681391
# instagram_actor_id → instagram_user_id migration (Jan 2026).
13691392
# Meta deprecated instagram_actor_id; the replacement is instagram_user_id
13701393
# inside object_story_spec (sibling of page_id and video_data/link_data).

0 commit comments

Comments
 (0)