def createAds(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) fields = [] params = { 'name': 'Ad for Instagram Profile', 'optimization_goal': 'IMPRESSIONS', 'billing_event': 'IMPRESSIONS', 'bid_amount': '500', 'image_url': dict1['image_path'], 'promoted_object': { 'page_id': dict1['page_id'] }, 'daily_budget': '10050', 'campaign_id': dict1['campaign_id'], 'status': 'PAUSED', 'special_ad_categories': 'None', # 'lifetime_budget': '200000', 'start_time': '2020-03-12T23:41:41-0800', 'end_time': '2020-12-19T23:41:41-0800', 'targeting': { 'age_min': 20, 'age_max': 24, 'genders': [1], 'geo_locations': { 'countries': ['US'], 'regions': [{ 'key': '4081' }], 'cities': [{ 'key': '777934', 'radius': 10, 'distance_unit': 'mile' }] } }, } ad_set = AdAccount(account.create_ad_set( fields=fields, params=params, )) print('ad_set', ad_set)
from facebook_business.adobjects.adaccount import AdAccount from facebook_business.api import FacebookAdsApi access_token = "EAAHsrmgrz0YBAA9W2ffy3UsB0UgAzkdPaZANA7VYMNHVKZCD80y4CVSGEB33ZCfn367SNB4ogJdLmwwbZAkcyZCpqyubToEUp3QnsZA7Av9rLfhrVFnQqgO9uL6EJQPbTDZA58oqBFjZB2oqVSsECKQP7KnQzlZAdJ1QU4yJVgePz4ZCfK7gvHw5Ay" account_id = 'act_414637205659315' api = FacebookAdsApi.init(access_token=access_token) adset_account = AdAccount(fbid=account_id, api=api) adset = adset_account.create_ad_set(params=params)
def create_adset(_name, _campaign, _optimization_goal = 'LINK_CLICKS', _billing_event = 'LINK_CLICKS', _ad_account= ad_account_id): from facebook_business.adobjects.adset import AdSet ad_account = AdAccount(fbid=_ad_account) params = { AdSet.Field.name: _name, AdSet.Field.optimization_goal: _optimization_goal, #AdSet.OptimizationGoal.offsite_conversions, #.post_engagement, reach enum {NONE, APP_INSTALLS, BRAND_AWARENESS, AD_RECALL_LIFT, CLICKS, ENGAGED_USERS, EVENT_RESPONSES, IMPRESSIONS, LEAD_GENERATION, LINK_CLICKS, OFFER_CLAIMS, OFFSITE_CONVERSIONS, PAGE_ENGAGEMENT, PAGE_LIKES, POST_ENGAGEMENT, REACH, SOCIAL_IMPRESSIONS, VIDEO_VIEWS, APP_DOWNLOADS, LANDING_PAGE_VIEWS, VALUE, REPLIES} AdSet.Field.billing_event: _billing_event, #.post_engagement, impressions # AdSet.Field.promoted_object: {#'page_id': c.rw_page_id, # 'pixel_id': c.rw_pixel_id, # 'custom_event_type': 'ADD_TO_CART' #PURCHASE, ADD_TO_CART, CONTENT_VIEW # }, # AdSet.Field.start_time: _start_time, # AdSet.Field.end_time: _end_time, # AdSet.Field.bid_amount: 150, #AdSet.Field.is_autobid: True, AdSet.Field.bid_strategy: 'LOWEST_COST_WITHOUT_CAP', AdSet.Field.daily_budget: 5000, # AdSet.Field.lifetime_spend_cap: 50000, AdSet.Field.campaign_id: _campaign, #AdSet.Field.frequency_control_specs: [{"event": "IMPRESSIONS", "interval_days":3, "max_frequency":1}], AdSet.Field.targeting: { 'geo_locations': { 'countries': ['US'] }, "excluded_geo_locations": { "regions": [ {"key": "3844", "name": "Alaska", "country": "US"}, {"key": "3854", "name": "Hawaii", "country": "US"}, {"key": "3869", "name": "Montana", "country": "US"}, {"key": "3870", "name": "Nebraska", "country": "US"}, {"key": "3871", "name": "Nevada", "country": "US"}, {"key": "3874", "name": "New Mexico", "country": "US"}, {"key": "3877", "name": "North Dakota", "country": "US"}, {"key": "3884", "name": "South Dakota", "country": "US"}, {"key": "3893", "name": "Wyoming", "country": "US"} ], }, "flexible_spec": [ {"interests": [ {"id": "1089448267745618", "name": "Joanna Gaines"}, {"id": "1507682269559205", "name": "The Holderness Family"}, {"id": "6002839660079", "name": "Cosmetics"}, {"id": "6002991239659", "name": "Motherhood"}, {"id": "6003134986700", "name": "Baking"}, {"id": "6003161577378", "name": "Groupon"}, {"id": "6003232518610", "name": "Parenting"}, {"id": "6003271034848", "name": "Working Mother"}, {"id": "6003332406177", "name": "Organization"}, {"id": "6003372919544", "name": "The Pioneer Woman - Ree Drummond"}, {"id": "6003385609165", "name": "Recipes"}, {"id": "6003470511564", "name": "Do it yourself (DIY)"}, {"id": "6003476182657", "name": "Family"}, {"id": "6003664179678", "name": "LivingSocial"}, {"id": "6009268249149", "name": "RetailMeNot"} ], "behaviors": [ {"id": "6017521096783", "name": "Gmail users"} ] } ], 'age_min':28, 'age_max': 65, 'publisher_platforms': ['facebook', 'instagram'], # 'audience_network', 'messenger' 'excluded_custom_audiences': ['23842970865070345'], 'custom_audiences': ['23842968835770345','23842968837020345'], 'user_os':['Android_ver_4.0_and_above'], 'excluded_user_device':['iPhone','iPad', 'iPod'], # 'wireless_carrier':['Wifi'], # 'page_types': ['desktopfeed'], 'facebook_positions': ['feed'], #right_hand_column, instant_article, instream_video, suggested_video, marketplace 'instagram_positions': ['stream'], #story 'excluded_publisher_categories': ['debated_social_issues','mature_audiences','tragedy_and_conflict'], # 'device_platforms': ['mobile', 'desktop'], }, AdSet.Field.status: AdSet.Status.active, ###Change to active } adset = ad_account.create_ad_set(params=params) return adset
'geo_locations': { 'countries': ['US'] } }, 'daily_budget': '1000', 'billing_event': 'IMPRESSIONS', 'bid_amount': '20', 'campaign_id': campaign_id, 'optimization_goal': 'PAGE_LIKES', 'promoted_object': { 'page_id': page_id }, 'name': 'My AdSet', } ad_set = my_account.create_ad_set( fields=fields, params=params, ) print('ad_set', ad_set) ad_set_id = ad_set.get_id() print('ad_set_id:', ad_set_id, '\n') # fields = [ # ] # params = { # 'body': 'Like My Page', # 'image_url': 'https://scontent-icn1-1.xx.fbcdn.net/v/t1.0-1/p32x32/13010641_580724558761933_1572200345389822918_n.jpg?_nc_cat=108&_nc_ht=scontent-icn1-1.xx&oh=05a6349127fbb53ecf18aa72292a06e5&oe=5D570D6C', # 'name': 'My Creative', # 'object_id': page_id, # 'title': 'My Page Like Ad', # }
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 create_ad_set(app_id: str, app_secret: str, account_access_token: str, account_id: str, fields, params): FacebookAdsApi.init(app_id, app_secret, account_access_token) account = AdAccount(account_id) return account.create_ad_set(fields=fields, params=params)