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
Exemple #2
0
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
Exemple #3
0
    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
Exemple #4
0
 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
Exemple #5
0
    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)
Exemple #6
0
    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)
Exemple #7
0
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})]
Exemple #9
0
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())
Exemple #10
0
        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())
Exemple #11
0
    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])
Exemple #13
0
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)
Exemple #14
0
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)
Exemple #15
0
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
Exemple #16
0
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%'
            })
Exemple #17
0
}
# 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)
Exemple #18
0
    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:
Exemple #20
0
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'
Exemple #22
0
 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
Exemple #23
0
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
Exemple #27
0
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