I can duplicate an ad and post it. But when I try to use a new video creative ID. It says the parameter is invalid. The video is in fact uploaded. I can also switch it out manually and set the ad live fine.
The bold part is where this takes place. It refuses to use the new creative.
I get this error:
Exception has occurred: FacebookRequestError
Message: Call was not successful
Method: POST
Path: https://graph.facebook.com/v17.0/act_1528844027360631/ads
Params: {'name': 'yarngc42pk5kms', 'creative': '{"creative_id":"575888971423418"}', 'adset_id': '6375801648255', 'status': 'ACTIVE'}
Status: 400
Response:
{
"error": {
"message": "Invalid parameter",
"type": "OAuthException",
"code": 100,
"error_subcode": 1487015,
"is_transient": false,
"error_user_title": "Ad Creative Invalid",
"error_user_msg": "The ad creative is invalid.",
"fbtrace_id": "A1J-ipZc03WREhijLmuhDBy"
}
}
File "/Users/codykrecicki/Desktop/debtads/admaker/app.py", line 146, in duplicate_ad_with_new_video
new_ad.remote_create()
File "/Users/codykrecicki/Desktop/debtads/admaker/app.py", line 170, in create_ads_with_multiple_videos
new_ad_id = self.duplicate_ad_with_new_video(existing_ad_id, video_path, ad_set_id, set_ad_live=True)
File "/Users/codykrecicki/Desktop/debtads/admaker/app.py", line 218, in <module>
ads_manager.create_ads_with_multiple_videos(existing_ad_id, done_folder, ad_set_id)
facebook_business.exceptions.FacebookRequestError:
Message: Call was not successful
Method: POST
Path: https://graph.facebook.com/v17.0/act_1528844027360631/ads
Params: {'name': 'yarngc42pk5kms', 'creative': '{"creative_id":"575888971423418"}', 'adset_id': '6375801648255', 'status': 'ACTIVE'}
Status: 400
Response:
{
"error": {
"message": "Invalid parameter",
"type": "OAuthException",
"code": 100,
"error_subcode": 1487015,
"is_transient": false,
"error_user_title": "Ad Creative Invalid",
"error_user_msg": "The ad creative is invalid.",
"fbtrace_id": "A1J-ipZc03WREhijLmuhDBy"
}
}
My complete FB class code.
class FacebookAdsManager:
def __init__(self, access_token, ad_account_id, app_id):
self.access_token = access_token
self.ad_account_id = ad_account_id
self.app_id = app_id
FacebookAdsApi.init(access_token=self.access_token)
def upload_video(self, video_path):
new_video = AdVideo(parent_id=self.ad_account_id)
new_video[AdVideo.Field.filepath] = video_path
new_video.remote_create()
return new_video['id']
def create_unique_ad_name(self):
return f"yarn{''.join(random.choices(string.ascii_lowercase + string.digits, k=10))}"
def get_ad_creative_info(self, ad_id):
try:
ad = Ad(ad_id)
ad.remote_read(fields=[Ad.Field.creative])
return ad[Ad.Field.creative]
except FacebookRequestError as e:
if e.api_error_code() == 100 and 'Ad creative invalid' in e.api_error_message():
print(f"The ad creative for Ad ID {ad_id} is invalid or missing.")
else:
print(f"Error while fetching the ad creative for Ad ID {ad_id}: {e}")
return None
def duplicate_ad_with_new_video(self, existing_ad_id, new_video_path, ad_set_id, set_ad_live=True):
# Retrieve the existing Ad creative information
existing_creative = self.get_ad_creative_info(existing_ad_id)
if existing_creative is None:
print("Skipping duplicate ad creation. The existing ad creative is invalid or missing.")
return None
new_video_id = self.upload_video(new_video_path)
print(f"New Video ID: {new_video_id}")
**existing_creative['id'] = new_video_id**
# Wait for a few seconds to ensure that the newly uploaded creative is fully available
time.sleep(5)
**new_ad = Ad(parent_id=self.ad_account_id)
new_ad_name = self.create_unique_ad_name()
new_ad[Ad.Field.name] = new_ad_name
new_ad[Ad.Field.creative] = {
'creative_id': existing_creative['id']
}**
# Set the ad set ID to which the new ad belongs
new_ad[Ad.Field.adset_id] = ad_set_id
# Set the status field to "PAUSED" (or "ACTIVE" if you prefer the new ad to be active right away)
new_ad[Ad.Field.status] = 'ACTIVE'
try:
print(f"Creating new ad with data: {new_ad.export_data()}")
new_ad.remote_create()
except FacebookRequestError as e:
print(f"Error while creating the new ad: {e.api_error_message()}")
print(f"Error code: {e.api_error_code()}")
print(f"Error subcode: {e.api_error_subcode()}")
return None
if set_ad_live:
try:
new_ad.api_update(params={'status': 'ACTIVE'})
except FacebookRequestError as e:
print(f"Error while setting the new ad to ACTIVE: {e.api_error_message()}")
print(f"Error code: {e.api_error_code()}")
print(f"Error subcode: {e.api_error_subcode()}")
return None
return new_ad['id']
def create_ads_with_multiple_videos(self, existing_ad_id, videos_folder, ad_set_id):
# Get the list of video files in the specified folder
video_files_in_folder = [os.path.join(videos_folder, f) for f in os.listdir(videos_folder) if f.endswith('.mp4')]
for video_path in video_files_in_folder:
# Duplicate the existing ad with the new video creative
new_ad_id = self.duplicate_ad_with_new_video(existing_ad_id, video_path, ad_set_id, set_ad_live=True)
print(f"New ad created with video: {video_path}")
# Fetch and print the response of the remote_create call
if new_ad_id:
try:
# Get an ad and copy it
new_ad = Ad(new_ad_id)
response = new_ad.remote_read(fields=[Ad.Field.name, Ad.Field.status, Ad.Field.creative])
print(f"Response: {response}")
# Move the video to the "done_uploaded" folder
video_filename = os.path.basename(video_path)
done_uploaded_folder = './done_uploaded'
os.makedirs(done_uploaded_folder, exist_ok=True)
new_video_path = os.path.join(done_uploaded_folder, video_filename)
shutil.move(video_path, new_video_path)
print(f"Video moved to: {new_video_path}")
except FacebookRequestError as e:
print(f"Error while fetching the ad information: {e.api_error_message()}")
It should use the new creative video ID. But it refuses. I have even hard coded a video ID in.
All the permissions are checked off when I made the access token. Please help.