def get_ad_set_data(ad_account: adaccount.AdAccount) -> {}: """Retrieves the ad set data of the ad account as a dictionary Args: ad_account: An ad account for which to retrieve the ad set data Returns: A dictionary with {ad_set_id: {'name': 1, 'campaign_id': 2, 'attributes': {}}} format """ logging.info('get ad set data for account {}'.format( ad_account['account_id'])) ad_sets = ad_account.get_ad_sets( fields=['id', 'name', 'campaign_id', 'adlabels'], params={ 'limit': 1000, 'status': ['ACTIVE', 'PAUSED', 'ARCHIVED'] }) result = {} for ad_set in ad_sets: result[ad_set['id']] = { 'name': ad_set['name'], 'campaign_id': ad_set['campaign_id'], 'attributes': parse_labels(ad_set.get('adlabels', [])) } return result
def view_ad(request): FacebookAdsApi.init(access_token=access_token, app_id=app_id, app_secret=app_secret) my_account = AdAccount('act_' + user_id) adsets = my_account.get_ad_sets() adset_id = [] for i in range(len(adsets)): adset_id.append(adsets[i]["id"]) for adset in adset_id: ad_set = AdSet(adset) fields = [ Ad.Field.name, Ad.Field.id, ] ad_iter = ad_set.get_ads(fields=fields) ad_data = [] for ad in ad_iter: result = {} result["id"] = ad[Ad.Field.id] result["name"] = ad[Ad.Field.name] ad_data.append(result) context = {'ads': ad_data} return render(request, 'fbapp/view_ad.html', context)
def view_adset(request): FacebookAdsApi.init(access_token=access_token, app_id=app_id, app_secret=app_secret) my_account = AdAccount('act_' + user_id) adsets = my_account.get_ad_sets() adset_id = [] for i in range(len(adsets)): adset_id.append(adsets[i]["id"]) adset_data = [] for id in adset_id: adset = AdSet(fbid=id) fields = [ AdSet.Field.name, AdSet.Field.effective_status, AdSet.Field.campaign_id, AdSet.Field.status, ] adset.remote_read(fields=fields) result = {} result["id"] = id result["name"] = adset[AdSet.Field.name] result["campid"] = adset[AdSet.Field.campaign_id] result["status"] = adset[AdSet.Field.status] result["data_1"] = "ACTIVE" result["data_2"] = "PAUSED" adset_data.append(result) context = {'adsets': adset_data} return render(request, 'fbapp/view_adset.html', context)
def get_request(account_id, table, params, fields): """account_id: unique id for ad account in format act_<ID> table: The table object found in the models module params: dictionary of parameters for request fields: list of fields for request --> returns requested data from Facebook Marketing API """ my_account = AdAccount(account_id) if table == 'accounts': cursor = my_account.api_get(params=params, fields=fields) return dict(cursor) if table == 'campaigns': cursor = my_account.get_campaigns(params=params, fields=fields) request = [campaign for campaign in cursor] return request if table == 'adsets': request = my_account.get_ad_sets(params=params, fields=fields) return request if table == 'ads_insights': cursor = my_account.get_insights_async(params=params, fields=fields) cursor.api_get() while cursor[AdReportRun.Field.async_status] != "Job Completed": time.sleep(1) cursor.api_get() time.sleep(1) request = cursor.get_result(params={"limit": 1000}) return request if table == 'ads_insights_age_and_gender': cursor = my_account.get_insights_async(params=params, fields=fields) cursor.api_get() while cursor[AdReportRun.Field.async_status] != "Job Completed": time.sleep(1) cursor.api_get() time.sleep(1) request = cursor.get_result(params={"limit": 1000}) return request if table == 'ads_insights_region': cursor = my_account.get_insights_async(params=params, fields=fields) cursor.api_get() while cursor[AdReportRun.Field.async_status] != "Job Completed": time.sleep(1) cursor.api_get() time.sleep(1) request = cursor.get_result(params={"limit": 1000}) return request
def getAds(my_app_id, my_app_secret, my_access_token, account_id): FacebookAdsApi.init(my_app_id, my_app_secret, my_access_token) account = AdAccount(account_id) ad_set = account.get_ad_sets() print(ad_set)
from facebook_business.adobjects.adset import AdSet my_app_id = cfg.fb_app_id my_app_secret = cfg.fb_app_secret my_access_token = cfg.fb_token auth_url = f"https://graph.facebook.com/oauth/access_token?client_id={cfg.fb_app_id}&client_secret={my_app_secret}&redirect_uri={cfg.redirect}&grant_type=client_credentials" logger.info(f'auth url: {auth_url}') FacebookAdsApi.init(my_app_id, my_app_secret, my_access_token) id = 'act_207528810141959' account = AdAccount(id) adsets = account.get_ad_sets(fields=[AdSet.Field.name]) for adset in adsets: print(adset[AdSet.Field.name]) # my_accounts = list(me.get_ad_accounts()) # print(my_accounts) # campaigns = my_account # print(campaigns)
def get_ad_sets(self, account_id, include_archived, limit): """ Retrieves and displays a list of ad sets of a given account, and analyze how likely a similar ad for Instagram can be created. Params: * `account_id` is your Facebook Ad Account id. * `include_archived` specifies whether archived ad sets should be analyzed. * `limit` is how many ad sets to analyze. This script will analyze the first `limit` ad sets as in the response, not including those which use Instagram placement already. The more this limit is, the longer it takes to run. If you run the script directly and are willing to wait for a while, you can drop the lines of code around it. For more information see the [Instagram Ads document]( https://developers.facebook.com/docs/marketing-api/guides/instagramads/) """ locale.setlocale(locale.LC_ALL, '') if include_archived: params = { 'limit': limit, AdSet.Field.configured_status: [ 'PENDING', 'ACTIVE', 'PAUSED', 'PENDING_REVIEW', 'DISAPPROVED', 'PREAPPROVED', 'PENDING_BILLING_INFO', 'CAMPAIGN_PAUSED', 'CAMPAIGN_GROUP_PAUSED', 'ARCHIVED' ], } else: params = {'limit': limit} account = AdAccount(account_id) ad_sets = account.get_ad_sets(fields=[ AdSet.Field.id, AdSet.Field.campaign_id, AdSet.Field.name, AdSet.Field.configured_status, AdSet.Field.targeting, ], params=params) cache = {} count = 0 results = [] for ad_set in ad_sets: if count >= limit: break count += 1 result = {} result['id'] = ad_set['id'] result['name'] = ad_set['name'] logger.error(ad_set) # Get targeting from ad set targeting = ad_set.get(AdSet.Field.targeting, None) logger.error(targeting) if targeting is not None: publisher_platforms = targeting.get('publisher_platforms', None) pp_str = '' if publisher_platforms is None: result['publisher_platforms'] = '<li>DEFAULT</li>' else: for pp in publisher_platforms: pp_str += ('<li>' + self.translate_placement_publisher( str(pp)) + '</li>') result['publisher_platforms'] = pp_str params = { 'currency': 'USD', 'targeting_spec': targeting, 'optimize_for': AdSet.OptimizationGoal.impressions, } if publisher_platforms is not None and "instagram" in \ publisher_platforms: count -= 1 continue reach_fb = account.get_reach_estimate(params=params)[0].get( 'users', 0) targeting['publisher_platforms'] = ["instagram"] targeting['facebook_positions'] = None params = { 'currency': 'USD', 'targeting_spec': targeting, 'optimize_for': AdSet.OptimizationGoal.impressions, } reach_ig = account.get_reach_estimate(params=params)[0].get( 'users', 0) self.add_check_result(result, self.check_audience(reach_fb, reach_ig)) result["audience"] = reach_ig * 100 / reach_fb result["ig_audience"] = locale.format("%d", reach_ig, grouping=True) # Get objective and status from Campaign campaign_id = ad_set[AdSet.Field.campaign_id] campaign = self.get_ad_campaign(cache, campaign_id) result["c_objective"] = \ campaign[Campaign.Field.objective].replace("_", " ") result["c_status"] = campaign[Campaign.Field.configured_status] check = self.check_objective(result["c_objective"]) if check['eligibility'] == 5: result['objective_supported'] = 1 elif check['eligibility'] == 1: result['objective_supported'] = 0 else: result['objective_supported'] = 2 self.add_check_result(result, check) # Get creative and check the media if campaign[Campaign.Field.objective] == 'PRODUCT_CATALOG_SALES': result['preview_url'] = \ 'Images from product catalog are not supported.' results.append(result) result['creative_ready'] = False continue creatives = ad_set.get_ad_creatives([ AdCreative.Field.object_story_id, ]) result['creative_ready'] = False if not creatives: comment = 'No creative found in this ad set.' self.add_check_result(result, { "eligibility": 3, }) result['preview_url'] = comment results.append(result) continue creative = creatives[0] story_id = creative.get(AdCreative.Field.object_story_id, 0) if story_id == 0: comment = 'No post fround in the first creative of this ad set.' self.add_check_result(result, { "eligibility": 3, }) result['preview_url'] = comment results.append(result) continue # Check whether the creative's post is IG ready try: # This Graph API call is not a part of Ads API thus no SDK post = FacebookAdsApi.get_default_api().call( 'GET', (story_id, ), params={ 'fields': 'is_instagram_eligible,child_attachments' }, ) post_ig_eligible = post.json()['is_instagram_eligible'] except FacebookRequestError: post_ig_eligible = False result['creative_ready'] = post_ig_eligible if post_ig_eligible: self.add_check_result(result, { "eligibility": 5, }) # Generate preview # As we do not know which IG account you will use, # just use a hardcoded one for preview. jasper_ig_account = "1023317097692584" ad_format = AdPreview.AdFormat.instagram_standard creative_spec = { AdCreative.Field.instagram_actor_id: jasper_ig_account, AdCreative.Field.object_story_id: story_id, } params = { 'creative': creative_spec, 'ad_format': ad_format, } preview = account.get_generate_previews(params=params) result['preview_url'] = preview[0].get_html() \ .replace('width="320"', 'width="340"', 1) else: comment = 'The creative needs to be modified for Instagram.' self.add_check_result(result, { "eligibility": 3, }) result['preview_url'] = comment results.append(result) return list( sorted(results, key=lambda result: result['eligibility'], reverse=True))
def retrieve_eligible_adsets_for_an( self, accountid, includepaused=False, ): """ This method returns all eligible ad sets that can have audience networked turned on for a given ad account id. Args: accountid: The ad account id (should be of the form act_<act_id>) for which you are running this exercise. inlcudepaused: Boolen parameter to make your method consider ad sets with paused states (PAUSED & CAMPAIGN_PAUSED). Checks only ACTIVE by default. Returns: List of ad set objects (if found satisfying the conditions) or an empty list. """ # use accountid to retrieve all active adsets account = AdAccount(accountid) adsetfields = [ AdSet.Field.id, AdSet.Field.name, AdSet.Field.campaign_id, AdSet.Field.targeting, AdSet.Field.effective_status, ] adsets = list(account.get_ad_sets(fields=adsetfields)) # Filter ad sets received by desired status and placement types. # Further filter by campaign objectives listed in the criteria below. # # Ref: https://developers.facebook.com/docs/ # marketing-api/audience-network/v2.5 desired_campaign_status = set(['ACTIVE']) # mostly useful in testing when you don't have active campaigns if includepaused is True: desired_campaign_status.update({'PAUSED', 'CAMPAIGN_PAUSED'}) desired_campaign_objectives = set([ 'MOBILE_APP_INSTALLS', 'MOBILE_APP_ENGAGEMENT', 'LINK_CLICKS', 'CONVERSIONS', 'PRODUCT_CATALOG_SALES', ]) # Hold the result set eligible_adsets = [] for adset in adsets: if adset[AdSet.Field.effective_status] in desired_campaign_status: """ 'devide_platforms', 'publisher_platforms' and 'facebook_positions' could be absent for the default of 'ALL' """ device_platforms = None if Targeting.Field.device_platforms in \ adset[AdSet.Field.targeting]: device_platforms = set(adset[AdSet.Field.targeting][ Targeting.Field.device_platforms]) publisher_platforms = None if Targeting.Field.publisher_platforms in \ adset[AdSet.Field.targeting]: publisher_platforms = set(adset[AdSet.Field.targeting][ Targeting.Field.publisher_platforms]) facebook_positions = None if Targeting.Field.facebook_positions in \ adset[AdSet.Field.targeting]: facebook_positions = set(adset[AdSet.Field.targeting][ Targeting.Field.facebook_positions]) if ((facebook_positions is None or 'feed' in facebook_positions) and (device_platforms is None or 'mobile' in device_platforms)): if (publisher_platforms is None or 'audience_network' in publisher_platforms): # audience network already enabled, so just pass continue else: campaign = Campaign(adset[AdSet.Field.campaign_id]) campaignfields = [ Campaign.Field.id, Campaign.Field.name, Campaign.Field.effective_status, Campaign.Field.objective, ] campaign = campaign.remote_read(fields=campaignfields) if (campaign[Campaign.Field.objective] in desired_campaign_objectives): eligible_adsets.append(adset) return eligible_adsets
class LibFacebook: def __init__(self, app_id, app_secret, access_token, ad_account_id): FacebookAdsApi.init(app_id, app_secret, access_token) self.account = AdAccount(ad_account_id) def create_ad_tree(self): # Campaign fields fields = ["id", "account_id", "adlabels", "bid_strategy", "boosted_object_id", "brand_lift_studies", "budget_rebalance_flag", "budget_remaining", "buying_type", "can_create_brand_lift_study", "can_use_spend_cap", "configured_status", "created_time", "daily_budget", "effective_status", "issues_info", "lifetime_budget", "name", "objective", "recommendations", "source_campaign", "source_campaign_id", "spend_cap", "start_time", "status", "stop_time", "updated_time"] # List of all campaigns campaigns = self.account.get_campaigns(fields=fields) # Ad set fields fields = ["id", "account_id", "adlabels", "adset_schedule", "attribution_spec", "bid_amount", "bid_info", "bid_strategy", "billing_event", "budget_remaining", "campaign", "campaign_id", "configured_status", "created_time", "creative_sequence", "daily_budget", "daily_min_spend_target", "daily_spend_cap", "destination_type", "effective_status", "end_time", "frequency_control_specs", "instagram_actor_id", "is_dynamic_creative", "issues_info", "lifetime_budget", "lifetime_imps", "lifetime_min_spend_target", "lifetime_spend_cap", "name", "optimization_goal", "pacing_type", "promoted_object", "recommendations", "recurring_budget_semantics", "rf_prediction_id", "source_adset", "source_adset_id", "start_time", "status", "targeting", "time_based_ad_rotation_id_blocks", "time_based_ad_rotation_intervals", "updated_time", "use_new_app_click"] # List of all ad sets ad_sets = self.account.get_ad_sets(fields=fields) # Ad fields fields = ["id", "account_id", "ad_review_feedback", "adlabels", "adset", "adset_id", "bid_amount", "bid_info", "bid_type", "campaign", "campaign_id", "configured_status", "conversion_specs", "created_time", "creative", "effective_status", "issues_info", "last_updated_by_app_id", "name", "recommendations", "source_ad", "status", "tracking_specs", "updated_time"] # List of all ads ads = self.account.get_ads(fields=fields) ad_tree = [] for i in campaigns: ad_structure_dict = {"campaign": i.export_all_data(), "adset_list": []} a = 0 for j in ad_sets: if j["campaign_id"] == i["id"]: ad_structure_dict["adset_list"].append({"ad_set": j.export_all_data(), "ad_list": []}) for k in ads: if k["adset_id"] == j["id"]: ad_structure_dict["adset_list"][a]["ad_list"].append({"ad": k.export_all_data()}) a += 1 ad_tree.append(ad_structure_dict) return ad_tree
class FbApi(object): def __init__(self, config_file=None): self.config_file = config_file self.df = pd.DataFrame() self.config = None self.account = None self.campaign = None self.app_id = None self.app_secret = None self.access_token = None self.act_id = None self.config_list = [] self.date_lists = None self.field_lists = None self.adset_dict = None self.cam_dict = None self.ad_dict = None self.pixel = None if self.config_file: self.input_config(self.config_file) def input_config(self, config_file): logging.info('Loading Facebook config file: ' + str(config_file)) self.config_file = os.path.join(config_path, config_file) self.load_config() self.check_config() FacebookAdsApi.init(self.app_id, self.app_secret, self.access_token) self.account = AdAccount(self.config['act_id']) def load_config(self): try: with open(self.config_file, 'r') as f: self.config = json.load(f) except IOError: logging.error(self.config_file + ' not found. Aborting.') sys.exit(0) self.app_id = self.config['app_id'] self.app_secret = self.config['app_secret'] self.access_token = self.config['access_token'] self.act_id = self.config['act_id'] self.config_list = [ self.app_id, self.app_secret, self.access_token, self.act_id ] def check_config(self): for item in self.config_list: if item == '': logging.warning(item + 'not in FB config file. Aborting.') sys.exit(0) def set_id_name_dict(self, fb_object): if fb_object == Campaign: fields = ['id', 'name'] self.cam_dict = list(self.account.get_campaigns(fields=fields)) elif fb_object == AdSet: fields = ['id', 'name', 'campaign_id'] self.adset_dict = list(self.account.get_ad_sets(fields=fields)) elif fb_object == Ad: fields = ['id', 'name', 'campaign_id', 'adset_id'] self.ad_dict = list(self.account.get_ads(fields=fields)) def campaign_to_id(self, campaigns): if not self.cam_dict: self.set_id_name_dict(Campaign) cids = [x['id'] for x in self.cam_dict if x['name'] in campaigns] return cids def adset_to_id(self, adsets, cids): as_and_cam = list(itertools.product(adsets, cids)) if not self.adset_dict: self.set_id_name_dict(AdSet) asids = [ tuple([x['id'], x['campaign_id']]) for x in self.adset_dict if tuple([x['name'], x['campaign_id']]) in as_and_cam ] return asids def create_campaign(self, campaign_name, objective, status, spend_cap): if not self.cam_dict: self.set_id_name_dict(Campaign) if campaign_name in ([x['name'] for x in self.cam_dict]): logging.warning(campaign_name + ' already in account. This ' + 'campaign was not uploaded.') return None self.campaign = Campaign(parent_id=self.account.get_id_assured()) self.campaign.update({ Campaign.Field.name: campaign_name, Campaign.Field.objective: objective, Campaign.Field.effective_status: status, Campaign.Field.spend_cap: int(spend_cap), Campaign.Field.special_ad_categories: 'NONE' }) self.campaign.remote_create() @staticmethod def geo_target_search(geos): all_geos = [] for geo in geos: params = { 'q': geo, 'type': 'adgeolocation', 'location_types': [Targeting.Field.country], } resp = TargetingSearch.search(params=params) all_geos.extend(resp) return all_geos @staticmethod def target_search(targets_to_search): all_targets = [] for target in targets_to_search[1]: params = { 'q': target, 'type': 'adinterest', } resp = TargetingSearch.search(params=params) if not resp: logging.warning(target + ' not found in targeting search. ' + 'It was not added to the adset.') continue if targets_to_search[0] == 'interest': resp = [resp[0]] new_tar = [dict((k, x[k]) for k in ('id', 'name')) for x in resp] all_targets.extend(new_tar) return all_targets @staticmethod def get_matching_saved_audiences(audiences): aud_list = [] for audience in audiences: audience = CustomAudience(audience) val_aud = audience.remote_read(fields=['targeting']) aud_list.append(val_aud) aud_list = aud_list[0]['targeting'] return aud_list def get_matching_custom_audiences(self, audiences): act_auds = self.account.get_custom_audiences( fields=[CustomAudience.Field.name, CustomAudience.Field.id]) audiences = [{ 'id': x['id'], 'name': x['name'] } for x in act_auds if x['id'] in audiences] return audiences def set_target(self, geos, targets, age_min, age_max, gender, device, publisher_platform, facebook_positions): targeting = {} if geos and geos != ['']: targeting[Targeting.Field.geo_locations] = { Targeting.Field.countries: geos } if age_min: targeting[Targeting.Field.age_min] = age_min if age_max: targeting[Targeting.Field.age_max] = age_max if gender: targeting[Targeting.Field.genders] = gender if device and device != ['']: targeting[Targeting.Field.device_platforms] = device if publisher_platform and publisher_platform != ['']: targeting[Targeting.Field.publisher_platforms] = publisher_platform if facebook_positions and facebook_positions != ['']: targeting[Targeting.Field.facebook_positions] = facebook_positions for target in targets: if target[0] == 'interest' or target[0] == 'interest-broad': int_targets = self.target_search(target) targeting[Targeting.Field.interests] = int_targets if target[0] == 'savedaudience': aud_target = self.get_matching_saved_audiences(target[1]) targeting.update(aud_target) if target[0] == 'customaudience': aud_target = self.get_matching_custom_audiences(target[1]) targeting[Targeting.Field.custom_audiences] = aud_target return targeting def create_adset(self, adset_name, cids, opt_goal, bud_type, bud_val, bill_evt, bid_amt, status, start_time, end_time, prom_obj, country, target, age_min, age_max, genders, device, pubs, pos): if not self.adset_dict: self.set_id_name_dict(AdSet) for cid in cids: if adset_name in ([ x['name'] for x in self.adset_dict if x['campaign_id'] == cid ]): logging.warning(adset_name + ' already in campaign. This ' + 'ad set was not uploaded.') continue targeting = self.set_target(country, target, age_min, age_max, genders, device, pubs, pos) params = { AdSet.Field.name: adset_name, AdSet.Field.campaign_id: cid, AdSet.Field.billing_event: bill_evt, AdSet.Field.status: status, AdSet.Field.targeting: targeting, AdSet.Field.start_time: start_time, AdSet.Field.end_time: end_time, } if bid_amt == '': params['bid_strategy'] = 'LOWEST_COST_WITHOUT_CAP' else: params[AdSet.Field.bid_amount] = int(bid_amt) if opt_goal in [ 'CONTENT_VIEW', 'SEARCH', 'ADD_TO_CART', 'ADD_TO_WISHLIST', 'INITIATED_CHECKOUT', 'ADD_PAYMENT_INFO', 'PURCHASE', 'LEAD', 'COMPLETE_REGISTRATION' ]: if not self.pixel: pixel = self.account.get_ads_pixels() self.pixel = pixel[0]['id'] params[AdSet.Field.promoted_object] = { 'pixel_id': self.pixel, 'custom_event_type': opt_goal, 'page_id': prom_obj } elif 'APP_INSTALLS' in opt_goal: opt_goal = opt_goal.split('|') params[AdSet.Field.promoted_object] = { 'application_id': opt_goal[1], 'object_store_url': opt_goal[2], } else: params[AdSet.Field.optimization_goal] = opt_goal params[AdSet.Field.promoted_object] = {'page_id': prom_obj} if bud_type == 'daily': params[AdSet.Field.daily_budget] = int(bud_val) elif bud_type == 'lifetime': params[AdSet.Field.lifetime_budget] = int(bud_val) self.account.create_ad_set(params=params) def upload_creative(self, creative_class, image_path): cre = creative_class(parent_id=self.account.get_id_assured()) if creative_class == AdImage: cre[AdImage.Field.filename] = image_path cre.remote_create() creative_hash = cre.get_hash() elif creative_class == AdVideo: cre[AdVideo.Field.filepath] = image_path cre.remote_create() creative_hash = cre.get_id() else: creative_hash = None return creative_hash def get_all_thumbnails(self, vid): video = AdVideo(vid) thumbnails = video.get_thumbnails() if not thumbnails: logging.warning('Could not retrieve thumbnail for vid: ' + str(vid) + '. Retrying in 120s.') time.sleep(120) thumbnails = self.get_all_thumbnails(vid) return thumbnails def get_video_thumbnail(self, vid): thumbnails = self.get_all_thumbnails(vid) thumbnail = [x for x in thumbnails if x['is_preferred'] is True] if not thumbnail: thumbnail = thumbnails[1] else: thumbnail = thumbnail[0] thumb_url = thumbnail['uri'] return thumb_url @staticmethod def request_error(e): if e._api_error_code == 2: logging.warning( 'Retrying as the call resulted in the following: ' + str(e)) else: logging.error('Retrying in 120 seconds as the Facebook API call' 'resulted in the following error: ' + str(e)) time.sleep(120) def create_ad(self, ad_name, asids, title, body, desc, cta, durl, url, prom_obj, ig_id, view_tag, ad_status, creative_hash=None, vid_id=None): if not self.ad_dict: self.set_id_name_dict(Ad) for asid in asids: if ad_name in [ x['name'] for x in self.ad_dict if x['campaign_id'] == asid[1] and x['adset_id'] == asid[0] ]: logging.warning(ad_name + ' already in campaign/adset. ' + 'This ad was not uploaded.') continue if vid_id: params = self.get_video_ad_params(ad_name, asid, title, body, desc, cta, url, prom_obj, ig_id, creative_hash, vid_id, view_tag, ad_status) elif isinstance(creative_hash, list): params = self.get_carousel_ad_params(ad_name, asid, title, body, desc, cta, durl, url, prom_obj, ig_id, creative_hash, view_tag, ad_status) else: params = self.get_link_ad_params(ad_name, asid, title, body, desc, cta, durl, url, prom_obj, ig_id, creative_hash, view_tag, ad_status) for attempt_number in range(100): try: self.account.create_ad(params=params) break except FacebookRequestError as e: self.request_error(e) def get_video_ad_params(self, ad_name, asid, title, body, desc, cta, url, prom_obj, ig_id, creative_hash, vid_id, view_tag, ad_status): data = self.get_video_ad_data(vid_id, body, title, desc, cta, url, creative_hash) story = { AdCreativeObjectStorySpec.Field.page_id: str(prom_obj), AdCreativeObjectStorySpec.Field.video_data: data } if ig_id and str(ig_id) != 'nan': story[AdCreativeObjectStorySpec.Field.instagram_actor_id] = ig_id creative = {AdCreative.Field.object_story_spec: story} params = { Ad.Field.name: ad_name, Ad.Field.status: ad_status, Ad.Field.adset_id: asid[0], Ad.Field.creative: creative } if view_tag and str(view_tag) != 'nan': params['view_tags'] = [view_tag] return params def get_link_ad_params(self, ad_name, asid, title, body, desc, cta, durl, url, prom_obj, ig_id, creative_hash, view_tag, ad_status): data = self.get_link_ad_data(body, creative_hash, durl, desc, url, title, cta) story = { AdCreativeObjectStorySpec.Field.page_id: str(prom_obj), AdCreativeObjectStorySpec.Field.link_data: data } if ig_id and str(ig_id) != 'nan': story[AdCreativeObjectStorySpec.Field.instagram_actor_id] = ig_id creative = {AdCreative.Field.object_story_spec: story} params = { Ad.Field.name: ad_name, Ad.Field.status: ad_status, Ad.Field.adset_id: asid[0], Ad.Field.creative: creative } if view_tag and str(view_tag) != 'nan': params['view_tags'] = [view_tag] return params @staticmethod def get_video_ad_data(vid_id, body, title, desc, cta, url, creative_hash): data = { AdCreativeVideoData.Field.video_id: vid_id, AdCreativeVideoData.Field.message: body, AdCreativeVideoData.Field.title: title, AdCreativeVideoData.Field.link_description: desc, AdCreativeVideoData.Field.call_to_action: { 'type': cta, 'value': { 'link': url, }, }, } if creative_hash[:4] == 'http': data[AdCreativeVideoData.Field.image_url] = creative_hash else: data[AdCreativeVideoData.Field.image_hash] = creative_hash return data @staticmethod def get_link_ad_data(body, creative_hash, durl, desc, url, title, cta): data = { AdCreativeLinkData.Field.message: body, AdCreativeLinkData.Field.image_hash: creative_hash, AdCreativeLinkData.Field.caption: durl, AdCreativeLinkData.Field.description: desc, AdCreativeLinkData.Field.link: url, AdCreativeLinkData.Field.name: title, AdCreativeLinkData.Field.call_to_action: { 'type': cta, 'value': { 'link': url, }, }, } return data @staticmethod def get_carousel_ad_data(creative_hash, desc, url, title, cta, vid_id=None): data = { AdCreativeLinkData.Field.description: desc, AdCreativeLinkData.Field.link: url, AdCreativeLinkData.Field.name: title, AdCreativeLinkData.Field.call_to_action: { 'type': cta, 'value': { 'link': url, }, }, } if creative_hash[:4] == 'http': data['picture'] = creative_hash else: data[AdCreativeVideoData.Field.image_hash] = creative_hash if vid_id: data[AdCreativeVideoData.Field.video_id] = vid_id return data @staticmethod def get_individual_carousel_param(param_list, idx): if idx < len(param_list): param = param_list[idx] else: logging.warning('{} does not have index {}. Using last available.' ''.format(param_list, idx)) param = param_list[-1] return param def get_carousel_ad_params(self, ad_name, asid, title, body, desc, cta, durl, url, prom_obj, ig_id, creative_hash, view_tag, ad_status): data = [] for idx, creative in enumerate(creative_hash): current_description = self.get_individual_carousel_param(desc, idx) current_url = self.get_individual_carousel_param(url, idx) current_title = self.get_individual_carousel_param(title, idx) if len(creative) == 1: data_ind = self.get_carousel_ad_data(creative_hash=creative[0], desc=current_description, url=current_url, title=current_title, cta=cta) else: data_ind = self.get_carousel_ad_data(creative_hash=creative[1], desc=current_description, url=current_url, title=current_title, cta=cta, vid_id=creative[0]) data.append(data_ind) link = { AdCreativeLinkData.Field.message: body, AdCreativeLinkData.Field.link: url[0], AdCreativeLinkData.Field.caption: durl, AdCreativeLinkData.Field.child_attachments: data, AdCreativeLinkData.Field.call_to_action: { 'type': cta, 'value': { 'link': url[0], }, }, } story = { AdCreativeObjectStorySpec.Field.page_id: str(prom_obj), AdCreativeObjectStorySpec.Field.link_data: link } if ig_id and str(ig_id) != 'nan': story[AdCreativeObjectStorySpec.Field.instagram_actor_id] = ig_id creative = {AdCreative.Field.object_story_spec: story} params = { Ad.Field.name: ad_name, Ad.Field.status: ad_status, Ad.Field.adset_id: asid[0], Ad.Field.creative: creative } if view_tag and str(view_tag) != 'nan': params['view_tags'] = [view_tag] return params
def get_add_sets(app_id: str, app_secret: str, account_access_token: str, account_id: str): FacebookAdsApi.init(app_id, app_secret, account_access_token) account = AdAccount(account_id) return account.get_ad_sets()