def get_account_analyse(self, account_id, date_preset=Ad.DatePreset.lifetime, limit=300): """ retrieve account level insight for all campaigns under the ad account. """ ad_account = AdAccount(account_id) params = { 'date_preset': date_preset, 'action_attribution_windows': [ AdsInsights.ActionAttributionWindows.value_default, AdsInsights.ActionAttributionWindows.value_1d_click, AdsInsights.ActionAttributionWindows.value_7d_click ], 'level': AdsInsights.Level.account, 'limit': limit } insight = ad_account.get_insights([ AdsInsights.Field.cpc, AdsInsights.Field.cpm, AdsInsights.Field.ctr, AdsInsights.Field.spend, AdsInsights.Field.clicks, AdsInsights.Field.impressions, AdsInsights.Field.reach, AdsInsights.Field.actions, AdsInsights.Field.action_values ], params) purchase_insight = self.extract_purchase(insight[0]) results = {"insight": insight, "purchase": purchase_insight} return results
def get_acountinfo_async(ad_account_id, reqparas, retry_max_time = 6): adAccount = AdAccount("act_" + str(ad_account_id)) retry_time = 0 stats = None while retry_time < retry_max_time: retry_time +=1 try: async_job = adAccount.get_insights(params=reqparas, async=True) async_job.remote_read() while async_job[AdReportRun.Field.async_percent_completion] < 100: time.sleep(1) async_job.remote_read() time.sleep(1) from copy import deepcopy reqparas_copy = deepcopy(reqparas) if 'breakdowns' in reqparas_copy: del reqparas_copy['breakdowns'] if 'filtering' in reqparas_copy: del reqparas_copy['filtering'] if 'fields' in reqparas_copy: del reqparas_copy['fields'] stats = async_job.get_result(params=reqparas_copy) if stats is None: raise Exception("stats null") except Exception, e: print "get_stats_async error ", e print "do some sleep" time.sleep(int(20 * random.random() + 10)) continue break
def get_ads_insight(self, account_id, report_date): """ Pull insights from the Insight edge and return an array of insight report Params: * `account_id` is your Facebook AdAccount id * `report_date` is the date for the insight report For more information see the [Ads Insights doc]( https://developers.facebook.com/docs/marketing-api/insights-api) """ ad_account = AdAccount(fbid=account_id) limit = 10 fields = [ 'campaign_name', 'adset_name', 'adset_id', 'impressions', 'spend', 'reach', 'actions', 'action_values' ] params = { 'time_range': { 'since': report_date, 'until': report_date }, 'action_attribution_windows': ['28d_click'], 'breakdowns': ['impression_device', 'publisher_platform'], 'level': 'adset', 'limit': limit if limit > 0 else None } insights = ad_account.get_insights(fields, params) insights_value = self.get_insights_value(insights, report_date, limit) return insights_value
def get_account_insights(self): accounts = AdAccount(self.account_id) params = { 'date_preset': 'today', } insights = accounts.get_insights(params=params, fields=list(GENERAL_FIELD.values()) + list(TARGET_FIELD.values())) current_account = insight[0] return current_account
def _facebook_report( self, account_id: str, api: FacebookAdsApi, params: Dict[str, Any], fields: List[str], sleep_time: int = 5, ) -> List[AdsInsights]: """ Pulls data from the Facebook Ads API with given account_id :param account_id: Facebook Account ID that holds ads information https://developers.facebook.com/docs/marketing-api/reference/ads-insights/ :type account_id: str :param api: FacebookAdsApi created in the hook :type api: FacebookAdsApi :param fields: List of fields that is obtained from Facebook. Found in AdsInsights.Field class. https://developers.facebook.com/docs/marketing-api/insights/parameters/v6.0 :type fields: List[str] :param params: Parameters that determine the query for Facebook https://developers.facebook.com/docs/marketing-api/insights/parameters/v6.0 :type params: Dict[str, Any] :param sleep_time: Time to sleep when async call is happening :type sleep_time: int """ ad_account = AdAccount(account_id, api=api) _async = ad_account.get_insights(params=params, fields=fields, is_async=True) while True: request = _async.api_get() async_status = request[AdReportRun.Field.async_status] percent = request[AdReportRun.Field.async_percent_completion] self.log.info("%s %s completed, async_status: %s", percent, "%", async_status) if async_status == JobStatus.COMPLETED.value: self.log.info("Job run completed") break if async_status in [ JobStatus.SKIPPED.value, JobStatus.FAILED.value ]: message = f"{async_status}. Please retry." raise AirflowException(message) time.sleep(sleep_time) report_run_id = _async.api_get()["report_run_id"] report_object = AdReportRun(report_run_id, api=api) self.log.info("Extracting data from returned Facebook Ads Iterators") insights = report_object.get_insights() return list(insights)
def bulk_facebook_report( self, params: Dict[str, Any], fields: List[str], sleep_time: int = 5, ) -> List[AdsInsights]: """ Pulls data from the Facebook Ads API :param fields: List of fields that is obtained from Facebook. Found in AdsInsights.Field class. https://developers.facebook.com/docs/marketing-api/insights/parameters/v6.0 :type fields: List[str] :param params: Parameters that determine the query for Facebook https://developers.facebook.com/docs/marketing-api/insights/parameters/v6.0 :type fields: Dict[str, Any] :param sleep_time: Time to sleep when async call is happening :type sleep_time: int :return: Facebook Ads API response, converted to Facebook Ads Row objects :rtype: List[AdsInsights] """ api = self._get_service() ad_account = AdAccount(api.get_default_account_id(), api=api) _async = ad_account.get_insights(params=params, fields=fields, is_async=True) while True: request = _async.api_get() async_status = request[AdReportRun.Field.async_status] percent = request[AdReportRun.Field.async_percent_completion] self.log.info("%s %s completed, async_status: %s", percent, "%", async_status) if async_status == JobStatus.COMPLETED.value: self.log.info("Job run completed") break if async_status in [ JobStatus.SKIPPED.value, JobStatus.FAILED.value ]: message = "{async_status}. Please retry.".format( async_status=async_status) raise AirflowException(message) time.sleep(sleep_time) report_run_id = _async.api_get()["report_run_id"] report_object = AdReportRun(report_run_id, api=api) insights = report_object.get_insights() self.log.info("Extracting data from returned Facebook Ads Iterators") return list(insights)
def main(request): access_token = request.args.get('access_token') account_id = request.args.get('account_id') date_start = request.args.get('date_start') date_end = request.args.get('date_end') conversion_event = request.args.get('conversion_event') facebook_app_id = os.environ.get('FACEBOOK_APP_ID') facebook_app_secret = os.environ.get('FACEBOOK_APP_SECRET') print(access_token, account_id, facebook_app_id, facebook_app_secret) # Initialize Facebook App FacebookAdsApi.init(facebook_app_id, facebook_app_secret, access_token) # Make a call to the Facebook API my_account = AdAccount('act_'+account_id) fields = ['spend', 'impressions', 'inline_link_clicks', 'actions'] params = { 'level': 'account', 'time_range': {'since': date_start, 'until': date_end}, 'time_increment': 1 } insights = my_account.get_insights(fields=fields, params=params) data = [] for day in insights: format_data = {} format_data['date'] = day['date_start'] format_data['impressions'] = day['impressions'] format_data['clicks'] = day['inline_link_clicks'] format_data['spend'] = day['spend'] # Pull out conversion metric conversions = [action.get('value') for action in day['actions'] if action.get('action_type') == conversion_event] if conversions: format_data['conversions'] = conversions[0] else: format_data['conversions'] = "0" # Append to the data list data.append(format_data) return jsonify(data)
def get_insights_for_account_id(self, account_id, insight_fields, breakdowns, time_range, time_increment='all_days', level='ad', limit=100, bootstrap=False): FacebookAdsApi.init(self.app_id, self.app_secret, self.access_token) account = AdAccount(f'act_{account_id}') params = { 'breakdowns': breakdowns, 'time_range': time_range, 'date_preset': 'lifetime', 'time_increment': time_increment, 'level': level } if bootstrap: params.pop('time_range') params['date_preset'] = 'lifetime' self.log.info( f'Retrieving Insights for Facebook Ad Account {account_id}') async_job = account.get_insights(params=params, fields=insight_fields, is_async=True) while True: job = async_job.api_get() status = job[AdReportRun.Field.async_status] self.log.info( f'Status: {status}, Percent done: {str(job[AdReportRun.Field.async_percent_completion])}' ) time.sleep(1) if status == "Job Completed": self.log.info('Done!') break return [dict(e) for e in async_job.get_result(params={'limit': limit})]
from facebook_business.api import FacebookAdsApi import time import os import json this_dir = os.path.dirname(__file__) config_filename = os.path.join(this_dir, 'config.json') config_file = open(config_filename) config = json.load(config_file) config_file.close() api = FacebookAdsApi.init(access_token=config['access_token']) account_id = config['act_id'] account = AdAccount(account_id) # Both Insights and Reportstats i_async_job = account.get_insights(params={'level': 'ad'}, is_async=True) # Insights while True: job = i_async_job.api_get() print("Percent done: " + str(job[AdReportRun.Field.async_percent_completion])) time.sleep(1) if job: print("Done!") break print(i_async_job.get_result())
Ad.Field.status: status, } ad = Ad(parent_id=account_id, api=api) # ad = ad.remote_create(params=params) # print(ad) return ad ad_list = [] for i in range(0, 10): params = { # 'level': 'campaign', 'campaign_id': 23842986818330629 } i_async_job = account.get_insights(params=params, async=True) # Insights while True: job = i_async_job.remote_read() print(job) print("Percent done: " + str(job['async_percent_completion'])) time.sleep(1) if job['async_status'] == "Job Completed": print("Done!") break print(i_async_job.get_result())
def fetch(self, target_date): # init FacebookAdsApi FacebookAdsApi.init(self.config['APP_ID'], self.config['APP_SECRET'], self.config['ACCESS_TOKEN']) my_account = AdAccount('act_' + self.config['AD_ACCOUNT_ID']) fields = [ AdsInsights.Field.impressions, AdsInsights.Field.clicks, AdsInsights.Field.conversions, ] target_date_str = target_date.strftime('%Y-%m-%d') params = { 'time_range': { 'since': target_date_str, 'until': target_date_str, }, } # data fetch response = my_account.get_insights(fields=fields, params=params) # dummy response for develop response = { "data": [ { "impressions": "200", "clicks": "60", "conversions": "20", "date_start": target_date_str, "date_stop": target_date_str, }, { "impressions": "300", "clicks": "90", "conversions": "30", "date_start": target_date_str, "date_stop": target_date_str, }, ], "paging": { "cursors": { "before": "MAZDZD", "after": "MAZDZD", } } } ret = [] for row in response['data']: ret.append({ 'date': row['date_stop'], 'format': 'format', 'impression': int(row['impressions']), 'click': int(row['clicks']), 'conversion': int(row['conversions']), 'used_budget': int('10'), }) return FacebookResponse('ok', ret)
# 'date_preset': 'this_week_sun_today' } fields = [ 'campaign_id', 'campaign_name', 'impressions', 'spend', 'impressions', 'date_start', 'date_stop', 'actions' ] campaigns = my_account.get_insights( fields=fields, params=params) # print(campaigns) ts = calendar.timegm(time.gmtime()) time = time.ctime(ts) with open('shopify_sales.csv', newline='') as read_shopify_csv: shopify_reader=csv.DictReader(read_shopify_csv) shopify_reader_list=(list(shopify_reader)) campaign_list = [] for my_campaigns in campaigns: # name = my_campaigns['campaign_name'].split("@")[0].lower() # name = " ".join(my_campaigns['campaign_name'].split()[:2])
def get_campaignDFn(n): # Set the info to get connected to the API. Do NOT share this info my_app_id = 'APP_ID' my_app_secret = 'APP-SECRET' my_access_token = 'ACCESS-TOKEN' # Start the connection to the facebook API FacebookAdsApi.init(my_app_id, my_app_secret, my_access_token) # Get yesterday's date for the filename, and the csv data yesterdaybad = datetime.datetime.now() - datetime.timedelta(days=(1+n)) yesterdayslash = yesterdaybad.strftime('%Y/%m/%d') yesterdayhyphen = yesterdaybad.strftime('%Y-%m-%d') # params = {'time_range':{"since":"2019-08-25","until":"2019-08-25"},'level':'adset'} This is an example params['time_range']['since'] = yesterdayhyphen params['time_range']['until'] = yesterdayhyphen # Define the destination filename filename = 'data'+str(n)+'.csv' filelocation = filename # Open or create new file try: csvfile = open(filelocation , 'w+', newline='') except: print ("Cannot open file.") # To keep track of rows added to file rows = 0 try: # Create file writer filewriter = csv.writer(csvfile, delimiter=',') except Exception as err: print(err) # Create an addaccount object from the adaccount id to make it possible to get insights tempaccount = AdAccount("ad_account_ID") # Grab insight info for all ads in the adaccount ads = tempaccount.get_insights(params=params, fields=[AdsInsights.Field.account_id, AdsInsights.Field.account_name, AdsInsights.Field.ad_id, AdsInsights.Field.ad_name, AdsInsights.Field.adset_id, AdsInsights.Field.adset_name, AdsInsights.Field.campaign_id, AdsInsights.Field.campaign_name, AdsInsights.Field.cost_per_outbound_click, AdsInsights.Field.outbound_clicks, AdsInsights.Field.spend, AdsInsights.Field.impressions ] # add any other required fields ); # Iterate through all accounts in the business account filewriter.writerow(["date", "adsetid", "adsetname","impressions", "clicks", "CPC", "spend"]) for ad in ads: # print(ad) # Set default values in case the insight info is empty date = yesterdayslash adsetid = "" adsetname = "" impressions = "" costperoutboundclick = "" outboundclicks = "" spend = "" # Set values from insight data if ('adset_id' in ad) : adsetid = ad[AdsInsights.Field.adset_id] if ('adset_name' in ad) : adsetname = ad[AdsInsights.Field.adset_name] if 'impressions' in ad: impressions = ad[AdsInsights.Field.impressions] if ('cost_per_outbound_click' in ad) : # This is stored strangely, takes a few steps to break through the layers costperoutboundclicklist = ad[AdsInsights.Field.cost_per_outbound_click] costperoutboundclickdict = costperoutboundclicklist[0] costperoutboundclick = costperoutboundclickdict.get('value') if ('outbound_clicks' in ad) : # This is stored strangely, takes a few steps to break through the layers outboundclickslist = ad[AdsInsights.Field.outbound_clicks] outboundclicksdict = outboundclickslist[0] outboundclicks = outboundclicksdict.get('value') if ('spend' in ad) : spend = ad[AdsInsights.Field.spend] # Write all ad info to the file, and increment the number of rows that will display filewriter.writerow([date, adsetid, adsetname, impressions, outboundclicks, costperoutboundclick, spend]) rows += 1 csvfile.close() # Print report print (str(rows) + " rows added to the file " + filename)
FacebookAdsApi.init(c['fb_app_id'], c['fb_app_secret'], token) num_days = 5 my_account = AdAccount(c['fb_account']) fields = [ 'account_id', 'account_name', 'ad_id', 'adset_id', 'adset_name', 'campaign_id', 'campaign_name', 'cost_per_outbound_click', 'outbound_clicks', 'outbound_clicks_ctr', 'spend', 'relevance_score', 'actions' ] tf = '%Y-%m-%d' start = date.today() - timedelta(days=num_days) while start < date.today(): results = dd(dict) params = { 'time_range': { 'since': start.strftime(tf), 'until': (start + timedelta(days=1)).strftime(tf) }, 'level': 'ad' } ads = my_account.get_insights(params=params, fields=fields) start += timedelta(days=1)
def get_data_from_api(start_date,end_date): Campaign_ID = [] Page_ID = [] Amount_Spent = [] # Page_Name = [] campaigns_all = {"Campaign_id":[], "Page_id":[], "Amount_spent":[], } page_id = None pixel_id = None access_token = 'EAAUbBhxccoEBALbQCDsVMLzwdZBZAZBXApZA0t1Qy3GtjZALfs89EMFhH62f5Kp7FWvshYRTrur41B14vICAgTf1TOba8qx7SBPejdqR4gZBqZCGDo0l0WvsmzubUKKqHncpyqhSpUqcO7O0WJsB1PnSZAMY7t7awukDuIYwrisTYwZDZD' bussiness_account_id = '1517651558352959' app_secret = '7a3ad485c97dbf45ee83562bc0dcb570' app_id = '1437087943127681' start_time = datetime.datetime.now() FacebookAdsApi.init(app_id, app_secret, access_token) business = Business(bussiness_account_id) # Get all ad accounts on the business account my_ad_account =business.get_owned_ad_accounts(fields=[AdAccount.Field.id]) # fields = [ # 'name', # 'objective', # # 'spend', # ] # params = { # 'time_range':{'since':start_date,'until':end_date}, # # 'date_preset':'yesterday', # 'effective_status': ['ACTIVE','PAUSED'], # } # Iterate through the adaccounts for account in my_ad_account: print(len(my_ad_account)) # i = 0 # Create an addaccount object from the adaccount id to make it possible to get insights tempaccount = AdAccount(account[AdAccount.Field.id]) # campaigns_iter = tempaccount.get_campaigns(fields = fields, params = params) # CAMPAIGN_UPDATE_BATCH_LIMIT = 5 # for campaigns in generate_batches(campaigns_iter,CAMPAIGN_UPDATE_BATCH_LIMIT): # api_batch = api.new_batch() # for i, campaign in enumerate(campaigns_iter): # adset = AdAccount(campaign[Campaign.Field.id]).get_ad_sets( # fields=['id', 'name', 'promoted_object'], # params = {}) # print(adset) # api_batch.execute() # spend_val.append(campaign[Campaign.Field.id]) # print(campaign, i) # print(spend_val) # print(set(spend_val)) # Grab insight info for all ads in the adaccount account_data = tempaccount.get_insights(params={ # 'time_increment':'1', 'time_range':{'since':start_date, 'until':end_date}, 'level':'campaign', }, fields=[ AdsInsights.Field.campaign_id, AdsInsights.Field.campaign_name, AdsInsights.Field.spend, ] ) for campaign in account_data: try: #Check if you reached 75% of the limit, if yes then back-off for 5 minutes (put this chunk in your 'for ad is ads' loop, every 100-200 iterations) # if (check_limit(bussiness_account_id,access_token)>75): # print('75% Rate Limit Reached. Cooling Time 5 Minutes.') # logging.debug('75% Rate Limit Reached. Cooling Time 5 Minutes.') # time.sleep(300) #ID OF Campaign # if campaign!=[]: # print(campaign) # print(len(account_data)) campaign_id = campaign[AdsInsights.Field.campaign_id] campaign_spent_val = campaign[AdsInsights.Field.spend] # print(campaign_spent_val) my_camp = Campaign(campaign_id) print(my_camp) #Campaign Insights Object # campaign_spent_obj = my_camp.get_insights(params={}, fields=[AdsInsights.Field.spend]) # campaign_spent = campaign_spent_obj[Campaign.Field.spend] # print(campaign_spent_obj) #Campaign Spend value # campaigns_all["Amount_spent"].append(campaign_spent_val) #AdSet Object adset = AdAccount(my_camp[Campaign.Field.id]).get_ad_sets( fields=['id', 'name', 'promoted_object'], params = {}) #page and Pixel ID from Adset if 'page_id' in adset[0][AdSet.Field.promoted_object]: page_id = adset[0][AdSet.Field.promoted_object][AdPromotedObject.Field.page_id] campaigns_all["Page_id"].append(page_id) Page_ID.append(page_id) # page_req = rq.head('https://facebook.com/'+page_id) # print(page_req.headers) # # for page in Page_ID: # print(Page(page_id).api_get(fields=['name'],params={})) elif 'pixel_id' in adset[0][AdSet.Field.promoted_object]: pixel_id = adset[0][AdSet.Field.promoted_object][AdPromotedObject.Field.pixel_id] campaigns_all["Page_id"].append(pixel_id) Page_ID.append(pixel_id) else: continue # Add Values to Dictionary campaigns_all["Campaign_id"].append(campaign_id) campaigns_all["Amount_spent"].append(campaign_spent_val) Campaign_ID.append(campaign_id) Amount_Spent.append(campaign_spent_val) # print(campaigns_all) time.sleep(2) except KeyError as e: print(e) continue except Exception as e: print(e) if FacebookRequestError.api_error_code(e) == 17: print(campaigns_all) print("Limit Reached") print("Wait 5 minutes for cooldown") time.sleep(300) continue finally: end_time = datetime.datetime.now() diff = end_time - start_time print(diff) tuples_of_data = list(zip(Campaign_ID,Page_ID,Amount_Spent)) sum_amount = compare_values(tuples_of_data) print(sum_amount) # print(diff.total_seconds()) return campaigns_all,sum_amount
def facebook_output(clicks, ad_account_id, app_id, access_token, app_secret, metrics, breakdown, start_date, end_date): if clicks is not None: my_ad_account = ad_account_id my_app_id = app_id my_access_token = access_token my_app_secret = app_secret my_metrics = metrics my_breakdown = breakdown my_start_date = start_date my_end_date = end_date my_action_type = 'action_type' my_level = 'ad' my_time_increment = 1 FacebookAdsApi.init(my_app_id, my_app_secret, my_access_token, api_version='v5.0') me = User(fbid="me") new_col_list = my_metrics # print(new_col_list) act = AdAccount(my_ad_account) async_job = act.get_insights(params={ 'time_range': { 'since': my_start_date, 'until': my_end_date }, 'breakdowns': list(my_breakdown), 'action_breakdowns': my_action_type, 'level': my_level, 'time_increment': my_time_increment }, fields=list(new_col_list)) df = pd.DataFrame(async_job) dff = df[new_col_list] html.Br() return html.Div( [ dash_table.DataTable(css=[{ 'selector': '.row', 'rule': 'margin: 0; white-space: inherit; overflow: inherit; text-overflow: inherit;' }], id='table', columns=[{ "name": i, "id": i } for i in dff.columns], data=dff.to_dict("rows"), export_format="csv", style_cell={ "fontFamily": "Arial", "size": 10, 'textAlign': 'left', 'width': '{}%'.format(len( dff.columns)), 'textOverflow': 'ellipsis', 'overflow': 'hidden' }, style_table={ 'maxHeight': '200px', 'overflowY': 'scroll', 'maxWidth': '1000px', 'overflowX': 'scroll' }, style_header={ 'backgroundColor': '#ffd480', 'color': 'white', 'height': '10', 'width': '10', 'fontWeight': 'bold' }, style_data={ 'whiteSpace': 'auto', 'height': 'auto', 'width': 'auto' }, tooltip_data=[{ column: { 'value': str(value), 'type': 'markdown' } for column, value in row.items() } for row in dff.to_dict('rows')], tooltip_duration=None, persistence=True, persistence_type='memory'), ], style={ 'margin-top': 20, 'margin-left': 300, 'display': 'table-cell', 'verticalAlign': 'middle', 'width': '100%' })
} # sample parameters format # params = {'level': 'campaign', # 'date_preset': 'lifetime', # 'fields': ['account_id', # 'account_name', # 'actions', # 'ad_id', 'ad_name', # 'adset_id', # 'adset_name', # 'spend', ] # } # retrieve a JSON look-alike object foo = my_account.get_insights(fields=fields, params=params) # flatten the object; convert to list foo_list = [x for x in foo] # print(type(foo_list)) # convert the list to a data frame df = pd.DataFrame(foo_list) df = df.rename(columns={ 'campaign_name': 'trackingtemplate', 'date_start': 'date' }).drop(['date_stop', 'id'], axis=1) # write to csv df.to_csv("fb.csv", index=False)
yesterday = (datetime.datetime.now() - datetime.timedelta(1)).strftime('%Y-%m-%d') if date_ranges is not None and len(date_ranges) > 0 and (yesterday != date_ranges[0] or yesterday != date_ranges[-1]): date_ranges_post = [{'since': date_str, 'until': date_str} for date_str in date_ranges] print "set date_ranges", date_ranges_post params['time_ranges'] = date_ranges_post return params def get_by_account_id(ad_account_id, date_ranges = None, delivery_info_status = None, async= False, retry_max_time = 30): params = get_reqparas_by(date_ranges, delivery_info_status) print params if async: stats = get_acountinfo_async(ad_account_id, params) else: adAccount = AdAccount("act_" + str(ad_account_id)) stats = adAccount.get_insights(params=params) print len(stats) if stats is None: raise Exception("ad Account {} get error !! ".format(ad_account_id)) retry_time = 0 while True: # retry_time < retry_max_time: try: retry_time += 1 list_stat = list() for stat in stats: print "------- stas is ----- ", stat, "------------------" mobile_install = 0 video_view = 0 link_click = 0 uniq_link_click = 0
max_retries = 5 messages = [] for x in range(1, max_retries): try: # Get insights by date and level ad logging.info('Get insights ' + date_delta_formated) ads = account.get_insights( params={ 'time_range': { 'since': date_delta_formated, 'until': date_delta_formated }, 'level': 'ad' }, fields=[ AdsInsights.Field.campaign_name, AdsInsights.Field.adset_name, AdsInsights.Field.ad_name, AdsInsights.Field.impressions, AdsInsights.Field.outbound_clicks, AdsInsights.Field.spend ]) break except Exception as str_error: messages.append(str_error) logging.info("Waiting 60s... ") time.sleep(60) else:
class FbApi(object): def __init__(self): self.df = pd.DataFrame() self.configfile = None self.config = None self.account = None self.app_id = None self.app_secret = None self.access_token = None self.act_id = None self.campaign_filter = None self.config_list = [] self.date_lists = None self.field_lists = None self.async_requests = [] def input_config(self, config): logging.info('Loading Facebook config file: {}'.format(config)) self.configfile = os.path.join(config_path, config) 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.configfile, 'r') as f: self.config = json.load(f) except IOError: logging.error('{} not found. Aborting.'.format(self.configfile)) 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 ] if 'campaign_filter' in self.config: self.campaign_filter = self.config['campaign_filter'] def check_config(self): for item in self.config_list: if item == '': logging.warning('{} not in FB config file. ' 'Aborting.'.format(item)) sys.exit(0) @staticmethod def parse_fields(items): breakdowns = [] action_breakdowns = [] attribution_window = [] fields = def_fields time_breakdown = 1 level = AdsInsights.Level.ad for item in items: if item == 'Actions': fields.extend(fields_actions) if item == 'Age': breakdowns.extend(breakdown_age) if item == 'Gender': breakdowns.extend(breakdown_gender) if item == 'Placement': breakdowns.extend(breakdown_placement) if item == 'Publisher': breakdowns.extend(breakdown_publisher) if item == 'Country': breakdowns.extend(breakdown_country) if item == 'Impression Device': breakdowns.extend(breakdown_impdevice) if item == 'Device': breakdowns.extend(breakdown_device) if item == 'Product': breakdowns.extend(breakdown_product) if item == 'Action Device': action_breakdowns.extend(ab_device) if 'Attribution' in item: item = item.split('::') attribution_window = [ '{}d_click'.format(item[1]), '{}d_view'.format(item[2]) ] if item == 'Total': time_breakdown = 'all_days' if item == 'Adset': level = AdsInsights.Level.adset if item == 'Campaign': level = AdsInsights.Level.campaign return fields, breakdowns, action_breakdowns, attribution_window,\ time_breakdown, level @staticmethod def get_data_default_check(sd, ed, fields): if sd is None: sd = dt.datetime.today() - dt.timedelta(days=1) if ed is None: ed = dt.datetime.today() - dt.timedelta(days=1) if fields is None: fields = def_fields return sd, ed, fields @staticmethod def date_check(sd, ed): sd = sd.date() ed = ed.date() if sd > ed: logging.warning('Start date greater than end date. Start date ' 'was set to end date.') sd = ed return sd, ed def get_data(self, sd=None, ed=None, fields=None): self.df = pd.DataFrame() sd, ed, fields = self.get_data_default_check(sd, ed, fields) fields, breakdowns, action_breakdowns, attr, time_breakdown, level = \ self.parse_fields(fields) sd, ed = self.date_check(sd, ed) self.date_lists = self.set_full_date_lists(sd, ed) self.make_all_requests(fields, breakdowns, action_breakdowns, attr, time_breakdown, level) self.check_and_get_async_jobs(self.async_requests) for col in nested_col: try: self.df[col] = self.df[col].apply(lambda x: self.clean_data(x)) except KeyError: continue for col in nested_dict_col: if col in self.df.columns: self.nested_dicts_to_cols(col) self.df = self.rename_cols() return self.df def make_all_requests(self, fields, breakdowns, action_breakdowns, attr, time_breakdown, level): self.field_lists = [fields] if time_breakdown == 'all_days': sd = self.date_lists[0][0] ed = self.date_lists[-1][0] self.request_for_fields(sd, ed, self.date_lists, fields, breakdowns, action_breakdowns, attr, time_breakdown, level) else: for date_list in self.date_lists: sd = date_list[0] ed = date_list[-1] self.request_for_fields(sd, ed, date_list, fields, breakdowns, action_breakdowns, attr, time_breakdown, level) def request_for_fields(self, sd, ed, date_list, fields, breakdowns, action_breakdowns, attr, time_breakdown, level): self.field_lists = [fields] for field_list in self.field_lists: self.make_request(sd, ed, date_list, field_list, breakdowns, action_breakdowns, attr, ad_status_enbaled, time_breakdown, level) self.make_request(sd, ed, date_list, field_list, breakdowns, action_breakdowns, attr, ad_status_disabled, time_breakdown, level) def make_request(self, sd, ed, date_list, field_list, breakdowns, action_breakdowns, attribution_window, ad_status, time_breakdown=1, level=AdsInsights.Level.ad, times_requested=1): logging.info('Making FB request for {} to {}'.format(sd, ed)) params = { 'level': level, 'breakdowns': breakdowns, 'time_range': { 'since': str(sd), 'until': str(ed), }, 'time_increment': time_breakdown, 'filtering': [{ 'field': 'ad.effective_status', 'operator': 'IN', 'value': ad_status }] } if action_breakdowns: params['action_breakdowns'] = action_breakdowns if attribution_window: params['action_attribution_windows'] = attribution_window if self.campaign_filter: params['filtering'].append({ 'field': 'campaign.name', 'operator': 'CONTAIN', 'value': self.campaign_filter }) try: insights = self.account.get_insights(fields=field_list, params=params, is_async=True) except FacebookRequestError as e: self.request_error(e, date_list, field_list) return True init_dict = { 'sd': sd, 'ed': ed, 'date_list': date_list, 'field_list': field_list, 'breakdowns': breakdowns, 'action_breakdowns': action_breakdowns, 'attribution_window': attribution_window, 'ad_status': ad_status, 'time_breakdown': time_breakdown, 'level': level, 'insights': insights, 'times_requested': times_requested } fb_request = FacebookRequest(init_dict=init_dict) self.async_requests.append(fb_request) def get_report(self, ar): try: report = ar.api_get() except FacebookRequestError as e: self.request_error(e) report = self.get_report(ar) return report def reset_report_request(self, fb_request): self.make_request(fb_request.sd, fb_request.ed, fb_request.date_list, fb_request.field_list, fb_request.breakdowns, fb_request.action_breakdowns, fb_request.attribution_window, fb_request.ad_status, fb_request.time_breakdown, fb_request.level, fb_request.times_requested + 1) def check_and_get_async_jobs(self, async_jobs): self.async_requests = [] for fb_request in async_jobs: try: job = fb_request.insights except AttributeError as e: logging.warning( 'A FB async_job does not contain insights and will ' 'be requested again. This is request #{} Error: {}'. format(fb_request.times_requested, e)) self.reset_report_request(fb_request) continue ar = AdReportRun(job['id']) report = self.get_report(ar) percent = report['async_percent_completion'] need_reset = fb_request.check_last_percent(percent) if need_reset: logging.warning( 'FB async_job #{} has been stuck for {} attempts and will ' 'be requested again. This is request #{}'.format( job['id'], fb_request.times_requested * 10, fb_request.times_requested)) self.reset_report_request(fb_request) continue logging.info('FB async_job #{} percent done ' '{}%'.format(job['id'], percent)) if percent == 100 and (report['async_status'] == 'Job Completed'): try: complete_job = list(ar.get_result()) except FacebookRequestError as e: self.request_error(e) self.async_requests.append(job) complete_job = None except FacebookBadObjectError as e: logging.warning('Facebook Bad Object Error: {}'.format(e)) self.async_requests.append(job) complete_job = None if complete_job: self.df = self.df.append(complete_job, ignore_index=True) fb_request.complete = True else: self.async_requests.append(fb_request) if self.async_requests: time.sleep(30) self.check_and_get_async_jobs(self.async_requests) def get_all_async_jobs(self, async_jobs): for async_job in async_jobs: percent = self.get_async_job_percent(async_job) while percent < 100 and type(percent) is int: percent = self.get_async_job_percent(async_job) complete_job = list(async_job.get_result()) if complete_job: self.df = self.df.append(complete_job, ignore_index=True) @staticmethod def get_async_job_percent(async_job): job = async_job.api_get() percent = job['async_percent_completion'] logging.info('FB async_job #{}' ' percent done:' '{}%'.format(async_job['id'], percent)) time.sleep(30) return percent def request_error(self, e, date_list=None, field_list=None): if e._api_error_code == 190: logging.error('Facebook Access Token invalid. Aborting.') sys.exit(0) elif e._api_error_code == 2 or e._api_error_code == 100: logging.warning('An unexpected error occurred. ' 'Retrying request later. {}'.format(e)) return True elif e._api_error_code == 17: logging.warning('Facebook rate limit reached. Pausing for ' '300 seconds.') time.sleep(300) self.date_lists.append(date_list) return True elif e._api_error_code == 1 and date_list is not None: if date_list[0] == date_list[-1]: logging.warning('Already daily. Reducing requested fields.' 'Error as follows: {}'.format(e)) metrics = [x for x in field_list if x not in def_params] fh, bh = self.split_list(metrics) if fh and bh: self.field_lists.append(def_params + fh) self.field_lists.append(def_params + bh) else: self.field_lists.append(field_list) return True logging.warning('Too much data queried. Reducing time scale') fh, bh = self.split_list(date_list) self.date_lists.append(fh) self.date_lists.append(bh) return True elif e._api_error_code == 1: logging.warning('Unknown FB error has occurred. Retrying.') return True else: logging.error('Aborting as the Facebook API call resulted ' 'in the following error: {}'.format(e)) if e._api_error_code: logging.error('Api error subcode: {}'.format( e._api_error_code)) sys.exit(0) @staticmethod def split_list(x): first_half = x[:len(x) / 2] back_half = x[len(x) / 2:] return first_half, back_half @staticmethod def clean_data(x): if str(x) == str('nan'): return 0 x = str(x).strip('[]') return ast.literal_eval(x)['value'] @staticmethod def convert_dictionary(x): if str(x) == str('nan'): return 0 x = str(x).strip('[]') return ast.literal_eval(x) def rename_cols(self): self.df = self.df.rename(columns=col_name_dic) return self.df @staticmethod def set_full_date_lists(sd, ed): dates = [] while sd <= ed: dates.append([sd]) sd = sd + dt.timedelta(days=1) return dates def nested_dicts_to_cols(self, nd_col): self.df[nd_col] = ( self.df[nd_col].apply(lambda x: self.convert_dictionary(x))) dict_df = self.df[nd_col].apply(pd.Series).fillna(0) column_list = dict_df.columns.values.tolist() column_list = [ l for l in column_list if l not in ['action_type', 'value'] ] clean_df = pd.DataFrame() if 'action_type' in dict_df.columns: column_list += ['action_type'] for col in column_list: dirty_df = dict_df[col].apply(pd.Series).fillna(0) if 'action_type' in dirty_df.columns: dirty_df = utl.data_to_type(dirty_df, str_col=['action_type']) clean_df = self.clean_nested_df(dirty_df, clean_df) self.df = pd.concat([clean_df, self.df], axis=1) # type: pd.DataFrame self.df = self.df.drop(nested_dict_col, axis=1) # type: pd.DataFrame @staticmethod def clean_nested_df(dirty_df, clean_df): values = [x for x in dirty_df.columns if x != 'action_type'] dirty_df = utl.data_to_type(dirty_df, float_col=values) dirty_df = pd.pivot_table(dirty_df, columns='action_type', values=values, index=dirty_df.index, aggfunc='sum', fill_value=0) if type(dirty_df.columns) == pd.MultiIndex: dirty_df.columns = [ ' - '.join([str(y) for y in x]) if x[0] != 'value' else x[1] for x in dirty_df.columns ] for col in [x for x in [0.0, 'action_type'] if x in dirty_df.columns]: dirty_df = dirty_df.drop(col, axis=1) dirty_df = dirty_df.apply(pd.to_numeric) clean_df = pd.concat([clean_df, dirty_df], axis=1) clean_df = clean_df.groupby(clean_df.columns, axis=1).sum() # type: pd.DataFrame return clean_df
def get_facebook_data(event, context): pubsub_message = base64.b64decode(event['data']).decode('utf-8') bigquery_client = bigquery.Client() if 'date' in event['attributes']: yesterday = event['attributes']['date'].strftime('%Y-%m-%d') else: yesterday = date.today() - timedelta(1) if pubsub_message == 'get_currency': table_id = event['attributes']['table_id'] dataset_id = event['attributes']['dataset_id'] project_id = event['attributes']['project_id'] api_key = event['attributes']['api_key'] from_currency = event['attributes']['from_currency'] to_currency = event['attributes']['to_currency'] source = from_currency + to_currency cur_source = [] params = { 'access_key': api_key, 'currencies': to_currency, 'source': from_currency, 'date': yesterday.strftime("%Y-%m-%d") } url = 'http://api.currencylayer.com/historical' try: r = requests.get(url, params=params) except requests.exceptions.RequestException as e: logger.error('request to currencylayer error: {}').format(e) return e if r.json()["success"] is True: exist_dataset_table(bigquery_client, table_id, dataset_id, project_id, schema_exchange_rate) cur_source.append({ 'date': yesterday.strftime("%Y-%m-%d"), 'currencies': source, 'rate': r.json()['quotes'][source] }) insert_rows_bq(bigquery_client, table_id, dataset_id, project_id, cur_source) else: logger.error('request to currencylayer error: {}').format( r.json()['error']['info']) return 'ok' elif pubsub_message == 'get_facebook': table_id = event['attributes']['table_id'] dataset_id = event['attributes']['dataset_id'] project_id = event['attributes']['project_id'] app_id = event['attributes']['app_id'] app_secret = event['attributes']['app_secret'] access_token = event['attributes']['access_token'] account_id = event['attributes']['account_id'] try: FacebookAdsApi.init(app_id, app_secret, access_token) account = AdAccount('act_' + str(account_id)) insights = account.get_insights( fields=[ AdsInsights.Field.account_id, AdsInsights.Field.campaign_id, AdsInsights.Field.campaign_name, AdsInsights.Field.adset_name, AdsInsights.Field.adset_id, AdsInsights.Field.ad_name, AdsInsights.Field.ad_id, AdsInsights.Field.spend, AdsInsights.Field.impressions, AdsInsights.Field.clicks, AdsInsights.Field.actions, AdsInsights.Field.conversions ], params={ 'level': 'ad', 'time_range': { 'since': yesterday.strftime("%Y-%m-%d"), 'until': yesterday.strftime("%Y-%m-%d") }, 'time_increment': 1 }) except Exception as e: logger.info(e) print(e) raise fb_source = [] for index, item in enumerate(insights): actions = [] conversions = [] if 'actions' in item: for i, value in enumerate(item['actions']): actions.append({ 'action_type': value['action_type'], 'value': value['value'] }) if 'conversions' in item: for i, value in enumerate(item['conversions']): conversions.append({ 'action_type': value['action_type'], 'value': value['value'] }) fb_source.append({ 'date': item['date_start'], 'ad_id': item['ad_id'], 'ad_name': item['ad_name'], 'adset_id': item['adset_id'], 'adset_name': item['adset_name'], 'campaign_id': item['campaign_id'], 'campaign_name': item['campaign_name'], 'clicks': item['clicks'], 'impressions': item['impressions'], 'spend': item['spend'], 'conversions': conversions, 'actions': actions }) if exist_dataset_table(bigquery_client, table_id, dataset_id, project_id, schema_facebook_stat, clustering_fields_facebook) == 'ok': insert_rows_bq(bigquery_client, table_id, dataset_id, project_id, fb_source) return 'ok'
def run_query_on_fb_account_obj(self, params, ad_object_id): account = AdAccount("act_" + ad_object_id) for el in account.get_insights(params=params): yield el
def get_account_ad_performance_for_single_day( ad_account: adaccount.AdAccount, single_date: datetime) -> adsinsights.AdsInsights: """Downloads the ad performance for an ad account for a given day https://developers.facebook.com/docs/marketing-api/insights Args: ad_account: An ad account to download. single_date: A single date as a datetime object Returns: A list containing dictionaries with the ad performance from the report """ fields = [ 'date_start', 'ad_id', 'impressions', 'actions', 'spend', 'action_values' ] params = { 'action_attribution_windows': config.action_attribution_windows(), # https://developers.facebook.com/docs/marketing-api/insights/action-breakdowns 'action_breakdowns': ['action_type'], # https://developers.facebook.com/docs/marketing-api/insights/breakdowns 'breakdowns': ['impression_device'], 'level': 'ad', 'limit': 1000, 'time_range': { 'since': single_date.strftime('%Y-%m-%d'), 'until': single_date.strftime('%Y-%m-%d') }, # By default only ACTIVE campaigns get considered. 'filtering': [{ 'field': 'ad.effective_status', 'operator': 'IN', 'value': [ 'ACTIVE', 'PAUSED', 'PENDING_REVIEW', 'DISAPPROVED', 'PREAPPROVED', 'PENDING_BILLING_INFO', 'CAMPAIGN_PAUSED', 'ARCHIVED', 'ADSET_PAUSED' ] }] } # https://developers.facebook.com/docs/marketing-api/insights/best-practices # https://developers.facebook.com/docs/marketing-api/asyncrequests/ async_job = ad_account.get_insights(fields=fields, params=params, is_async=True) async_job.remote_read() while async_job[ AdReportRun.Field.async_percent_completion] < 100 or async_job[ AdReportRun.Field.async_status] != 'Job Completed': time.sleep(1) async_job.remote_read() time.sleep(1) ad_insights = async_job.get_result() return ad_insights
'time_range': { 'since': start, 'until': end }, 'level': 'ad', 'breakdowns': ['publisher_platform', 'platform_position', 'device_platform'] } fields = [ 'ad_name', 'adset_name', 'campaign_name', 'impressions', 'clicks', 'video_thruplay_watched_actions', 'video_continuous_2_sec_watched_actions', 'video_p25_watched_actions', 'video_p50_watched_actions', 'estimated_ad_recall_rate', 'video_p75_watched_actions', 'video_p95_watched_actions', 'video_p100_watched_actions', 'website_purchase_roas', 'spend', 'inline_link_clicks', 'unique_inline_link_clicks', 'video_play_actions', 'actions' ] async_job = act.get_insights(params=params, fields=fields, is_async=True) #Insights df = pd.DataFrame() async_job.api_get() while async_job[ AdReportRun.Field.async_status] != 'Job Completed' or async_job[ AdReportRun.Field.async_percent_completion] < 100: time.sleep(1) async_job.api_get() df = pd.DataFrame(async_job.get_result()) df.head()
def main(arg1): #initiate SQL Engine params = urllib.parse.quote_plus( "DRIVER={SQL Server};SERVER=XXXXXX;DATABASE=XXXXXX;UID=XXXXXX;PWD=XXXXXX" ) engine = sqlalchemy.create_engine("mssql+pyodbc:///?odbc_connect=%s" % params) #Set long term FB access token and request parameters and fields. Refer to https://developers.facebook.com/docs/marketing-api/insights/parameters for custom requirements. access_token = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' params = { 'level': 'campaign', 'time_range': { 'since': '2019-01-05', 'until': '2019-09-19' }, 'action_breakdowns': ['action_type'], 'breakdowns': ['publisher_platform'] } fields = [ 'impressions', 'clicks', 'actions', 'campaign_name', 'spend', 'video_10_sec_watched_actions' ] #initiate Facebook session FacebookAdsApi.init(access_token=access_token) #Takes Facebook Ad Account ID passed as an argument from multi.py. Runs the reporting job asynchronously. account = AdAccount('act_' + str(arg1)) i_async_job = account.get_insights(fields=fields, params=params, is_async=True) #Waiting for the job to complete while True: job = i_async_job.api_get() print("Percent done: " + str(job[AdReportRun.Field.async_percent_completion])) time.sleep(1) if job[AdReportRun.Field.async_status] == 'Job Completed': print("Done!") break #Fetching resulting Job ID reportid = json.loads( str(i_async_job).replace('\n', '').replace('<AdReportRun> ', '')) report_id = reportid['report_run_id'] #Fetching the response in csv format after the job has completed response = requests.get( 'https://www.facebook.com/ads/ads_insights/export_report/?report_run_id=' + report_id + '&name=myreport&format=csv&locale=en_GB&access_token=' + access_token) #Loading the result in a pandas data frame response = StringIO(response.text) df = pd.read_csv(response, encoding='utf8') #Uncomment to retrieve data as a flat file. ##print(df) ##f = open(report_id + '.csv','w', encoding="utf-8") ##f.write(response.text) ## ##f.close() #Replacing NAs with 0s and importing the dataframe to a database table df = df.fillna(0) df.to_sql('Enter you table name', schema='Enter your schema name', con=engine, if_exists='replace', index=False)
'until': yesturday }, 'time_increment': 1, } fields = [ AdsInsights.Field.date_start, AdsInsights.Field.spend, AdsInsights.Field.actions, ] #++++++++++++++++++++++++++++++++++++++++ my_account = AdAccount('act_<ACCOUNT ID>') my_file_name = 'my_file_name.csv' # extract data into json insights_cursor = my_account.get_insights(fields=fields, params=params) #+++++++++++++++++++++++++++++++++++++++++ # CLEANING #+++++++++++++++++++++++++++++++++++++++++ # column names must match eg: AdsInsights.Field.spend = spend columns = ['date_start', 'spend', 'actions'] # iterable (insights_cursor) will not work in older version of pandas df = pd.DataFrame(insights_cursor, columns=columns) df['spend'] = pd.to_numeric(df['spend']) def find(lst, key, value): """ lst: a list of dictionaries
class FacebookExecutor: """ Facebook FacebookExecutor. Arguments: """ def __init__(self): self.client = None self.access_token = None self.account = None self.account_id = None self.pixel_id = None self.set_api_config() def set_api_config(self): """ Loads access_token from FACEBOOK_APPLICATION_CREDENTIALS. """ try: with open(os.environ["FACEBOOK_APPLICATION_CREDENTIALS"]) as facebook_cred: data = json.load(facebook_cred) self.access_token = data["access_token"] except KeyError: raise KeyError("FACEBOOK_APPLICATION_CREDENTIALS env variable needed") self.set_client() def set_client(self): """ Sets self.client using the access token. """ self.client = FacebookAdsApi.init(access_token=self.access_token) def set_account(self, account_id): """ Sets account object """ self.account_id = account_id self.account = AdAccount('act_{}'.format(self.account_id)) logging.info("Initiated AdAccount object for account %s", self.account_id) def set_pixel_id(self, pixel_id): """ Sets the Pixel ID """ self.pixel_id = pixel_id logging.info("Set the pixel_id as %s", self.pixel_id) def get_campaign_insights(self, account_id, fields, start_date, end_date): """ Sets insights from the Facebook Insight API. Parameters: account_id: ID associated to the Facebook Account start_date: The start date end_date: The end date fields: list of field to be fetched start_date/end_date: defines the time range to get insights for (YYYY-mm-dd). """ self.set_account(account_id) out = [] params = { 'effective_status': ['ACTIVE'], 'level': 'campaign', 'time_range': { 'since': start_date, 'until': end_date } } logging.debug("Downloading insights for account %s", self.account_id) logging.debug("fields: %s", fields) logging.debug("params: %s", params) campaign_insights = self.account.get_insights( params=params, fields=fields ) for insight in campaign_insights: out.append(dict(insight)) return out def get_active_campaigns(self): return self.account.get_campaigns( fields=['account_id', 'name', 'daily_budget', 'lifetime_budget'], params={ 'effective_status': ["ACTIVE"], 'is_completed': False } ) def get_active_campaign_budgets(self, account_id): """ Fetches active campaign metadata from the Facebook API. Returns a dataframe with the following fields: - account_id - campaign_id - campaign_name - budget_type (daily_budget or lifetime_budget) - budget amount in account currency """ self.set_account(account_id) campaigns = self.get_active_campaigns() out = transform_campaign_budget(campaigns) return out def update_daily_budget(self, account_id, campaign_id, new_budget): """ Update the budget on the facebook API """ self.set_account(account_id) campaigns = self.get_active_campaigns() for campaign in campaigns: if campaign.get_id() == campaign_id: from pygyver.etl.toolkit import configure_logging configure_logging() logging.info( "Loading new budget for campaign %s", campaign_id ) logging.info( "Current daily_budget for campaign %s: %s", campaign_id, campaign['daily_budget'] ) campaign.api_update( params={'daily_budget': round(new_budget*100)} ) logging.info( "New daily_budget for campaign %s: %s", campaign_id, new_budget ) return campaigns def push_conversions_api_events(self, events, test_event_code=None): """ Pushes a list of Events to the Facebook Conversions API. :param events: A list of Facebook Events to push to the conversions API :type events: list of Event :param test_event_code: A test_event_code from Facebook Events Manager to mark these as test events :type test_event_code: str Returns: A dictionary with the parsed response from the Facebook API rtype: dict[str, str] """ if len(events) > 1000: logging.error("The maximum number of events that Facebook accepts in a single API call is 1,000. " "Please use the split_events_to_batches() function to split the events into batches") raise ValueError event_request = EventRequest( events=events, pixel_id=self.pixel_id, ) # Add the test_event_code if one is given if test_event_code: event_request.test_event_code = test_event_code api_response = {} try: event_response = event_request.execute() logging.info('%s events pushed to Facebook Conversions API', event_response.events_received) api_response['status'] = 'API Success' api_response['fb_trace_id'] = event_response.fbtrace_id api_response['messages'] = '\n'.join(event_response.messages) api_response['total_events'] = event_response.events_received except FacebookRequestError as e: logging.error('There was a Facebook Conversions API error:\n\t%s', e) api_response['status'] = 'API Error' api_response['fb_trace_id'] = e.body()['error']['fbtrace_id'] error_message = e.body()['error']['message'] error_message = ': '.join([error_message, e.body()['error']['error_user_msg']]) api_response['messages'] = error_message api_response['total_events'] = None return api_response