Facebook广告投放数据API对接流程

说明:仅供学习使用,请勿用于非法用途,若有侵权,请联系博主删除

作者:zhu6201976

一、需求背景

App在Facebook、Google等巨头进行广告投放,想要拿到实时广告投放效果数据,如曝光、点击、花费、触达等核心指标并进行分析,可对接官方API实现。因对接过程十分复杂,此处以Facebook为例,进行简单记录。

二、对接流程

1.文档地址

https://developers.facebook.com/docs/marketing-api/insights

2. access_token获取

a. 创建App https://developers.facebook.com/apps

b. 添加产品

  • 点击进入某个App --> Add products to your app --> Marketing API --> Set up

  • 点击左下角Marketing API --> Tools --> 勾选token权限 --> Get Token 即可生成一个长效token,有效期2个月,过期后需要重新生成 步骤相同

c. 查看access_token有效期(可选)

复制保存步骤2生成的token,查看有效期。

地址:https://developers.facebook.com/tools/debug/accesstoken

如图所示,通过此种方式,可以获取到一个有效期2个月的长效access_token。

三、示例代码

获取到长效access_token后,我们可以开始请求广告数据了。

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.api_url = 'https://graph.facebook.com'
        self.api_version = 'v19.0'

1. 获取所有广告账号adaccount

    def start_requests(self):
        page = 1
        url = f'{self.api_url}/{self.api_version}/me/adaccounts?'
        params = {
            'fields': 'id,name',
            'access_token': self.access_token
        }
        url = f'{url}{urlencode(params)}'
        yield scrapy.Request(url, meta={'page': page}, priority=1, callback=self.parse_adaccounts)

通过该API,可以获取到所有广告账号,分页返回,每页25条。fields字段控制返回的字段,此处为account_id、account_name。

后续翻页控制代码:

resp_str = resp.body.decode('utf-8', 'ignore')
resp_dict = json.loads(resp_str)
next_url = resp_dict.get('paging', {}).get('next')
if next_url:
    page += 1
    yield scrapy.Request(next_url, meta={'page': page}, priority=1, callback=self.parse_adaccounts)

2. 获取广告账号广告量

为什么要获取广告账号广告量?因为如果某个广告账号下根本没有投放广告,则无需后续请求,提高效率,减少请求次数。

    def get_adaccount_ads_volume_req(self, ad_account_id, ad_account_name):
        """
        构造账号广告量查询请求
        https://developers.facebook.com/docs/marketing-api/insights-api/ads-volume
        :param ad_account_id:
        :return:
        """
        url = f'{self.api_url}/{self.api_version}/{ad_account_id}/ads_volume?'
        params = {
            'access_token': self.access_token
        }
        url = f'{url}{urlencode(params)}'
        return scrapy.Request(url,
                              meta={'ad_account_id': ad_account_id,
                                    'ad_account_name': ad_account_name},
                              priority=2,
                              callback=self.parse_adaccount_ads_volume)

解析账号广告量响应代码:

        resp_str = resp.body.decode('utf-8', 'ignore')
        resp_dict = json.loads(resp_str)
        # self.logger.info(f'{method_name} {ad_account_id} {resp_dict}')
        ads_volume = resp_dict.get('data', [])
        self.logger.info(f'{method_name} {ad_account_id} 提取到 {len(ads_volume)} ads_volume')
        for volume in ads_volume:
            ads_running_or_in_review_count = volume.get('ads_running_or_in_review_count', 0)
            if ads_running_or_in_review_count > 0:
                yield self.get_campaigns_req(ad_account_id, ad_account_name, page=1)

3. 获取广告账号所有campaign

    def get_campaigns_req(self, ad_account_id, ad_account_name, page):
        """
        构造启动campaigns请求
        :param ad_account_id:
        :param ad_account_name:
        :param page:
        :return:
        """
        url = f'{self.api_url}/{self.api_version}/{ad_account_id}/campaigns?'
        params = {
            'effective_status': "['ACTIVE', 'PAUSED']",
            'fields': 'id,name',
            'access_token': self.access_token,
        }
        url = f'{url}{urlencode(params)}'
        return scrapy.Request(url,
                              meta={'ad_account_id': ad_account_id,
                                    'ad_account_name': ad_account_name,
                                    'page': page},
                              priority=2,
                              callback=self.parse_get_campaigns)

4. 对campaign聚合获取所有广告

该步骤非常重要,我们无需通过完整路径:adaccount --> campaign --> adset --> ads 获取到广告数据,可以利用API的level进行聚合,直接在campaign层级获取到所有广告投放数据。如下所示:

    def ad_insights_req(self, ad_account_id, ad_account_name, ad_campaign_id, ad_campaign_name, d_str, page):
        url = f'{self.api_url}/{self.api_version}/{ad_campaign_id}/insights?'
        params = {
            'level': 'ad',
            'fields': 'adset_id,adset_name,ad_id,ad_name,impressions,clicks,unique_clicks,spend,reach,cpc,cpm,cpp,ctr,' +
                      'date_start,date_stop,actions,action_values',
            # 'date_preset': 'today',  # today,yesterday,last_7d,last_30d,...
            'time_range': '{"since":' + f'"{d_str}"' + "," + '"until":' + f'"{d_str}"' + "}",
            'access_token': self.access_token,
        }
        url = f'{url}{urlencode(params)}'
        return scrapy.Request(url,
                              meta={'ad_account_id': ad_account_id,
                                    'ad_account_name': ad_account_name,
                                    'ad_campaign_id': ad_campaign_id,
                                    'ad_campaign_name': ad_campaign_name,
                                    'd_str': d_str,
                                    'page': page},
                              priority=3,
                              callback=self.parse_ad_insights)

 5. 解析广告数据

        for ad in ads:
            ad_insights_item = FbAdInsightsItem()
            ad_insights_item['ad_account_id'] = ad_account_id
            ad_insights_item['ad_account_name'] = ad_account_name
            ad_insights_item['ad_campaign_id'] = ad_campaign_id
            ad_insights_item['ad_campaign_name'] = ad_campaign_name
            ad_insights_item['ad_set_id'] = ad.get('adset_id', '')
            ad_insights_item['ad_set_name'] = ad.get('adset_name', '')
            ad_insights_item['ad_id'] = ad.get('ad_id', '')
            ad_insights_item['ad_name'] = ad.get('ad_name', '')
            ad_insights_item['impressions'] = ad.get('impressions', '')
            ad_insights_item['clicks'] = ad.get('clicks', '')
            ad_insights_item['unique_clicks'] = ad.get('unique_clicks', '')
            ad_insights_item['spend'] = ad.get('spend', '')
            ad_insights_item['reach'] = ad.get('reach', '')
            ad_insights_item['cpc'] = ad.get('cpc', '')
            ad_insights_item['cpm'] = ad.get('cpm', '')
            ad_insights_item['cpp'] = ad.get('cpp', '')
            ad_insights_item['ctr'] = ad.get('ctr', '')
            ad_insights_item['date_start'] = ad.get('date_start', '')
            ad_insights_item['date_stop'] = ad.get('date_stop', '')

一键三连,有需要的请私聊获取详细源码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/542820.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mybatis(5)参数处理+语句查询

参数处理&#xff0b;语句查询 1、简单单个参数2、Map参数3、实体类参数4、多参数5、Param注解6、语句查询6.1 返回一个实体类对象6.2 返回多个实体类对象 List<>6.3 返回一个Map对象6.4 返回多个Map对象 List<Map>6.5 返回一个大Map6.6 结果映射6.6.1 使用resultM…

流氓软件清理绝杀全家桶

下载地址&#xff1a;流氓软件清理绝杀全家桶.zip 网上仍有不少软件中携带流氓软件&#xff0c;甚至某些所谓的大厂出品的工具中也会有一些捆绑&#xff01; 对于玩机经验不太丰富的小白来说&#xff0c;也许一不小心&#xff0c;桌面就会被某些流氓软件搞得乌烟瘴气&#xf…

【每日刷题】技巧合集-LC136、LC169

1. LC136.只出现一次的数字 题目链接 解法一&#xff1a; 先给数字排序&#xff0c;如果num[i]与nums[i-1]或nums[i1]都不一致&#xff0c;则返回nums[i]。 class Solution {public int singleNumber(int[] nums) {if (nums.length 1){return nums[0];}Arrays.sort(nums);fo…

RabbitMQ消息模型之Work消息模型

Work消息模型 * work模型&#xff1a; * 多个消费者消费同一个队列中的消息&#xff0c;每个消费者获取到的消息唯一&#xff0c;且只能消费一次 * 作用&#xff1a;提高消息的消费速度&#xff0c;避免消息的堆积 * 默认采用轮询的方式分发消息 * 如果某…

多张固定宽度元素,随着屏幕尺寸变化自动换行

背景&#xff1a;多张固定宽度元素&#xff0c;随着屏幕尺寸变化自动换行实现&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevic…

加速Python循环的12种方法,最高可以提速900倍

在本文中&#xff0c;我将介绍一些简单的方法&#xff0c;可以将Python for循环的速度提高1.3到900倍。 Python内建的一个常用功能是timeit模块。下面几节中我们将使用它来度量循环的当前性能和改进后的性能。 对于每种方法&#xff0c;我们通过运行测试来建立基线&#xff0…

如何监控容器或K8s中的OpenSearch

概述 当前 OpenSearch 使用的越来越多, 但是 OpenSearch 生态还不尽完善. 针对如下情况: 监控容器化或运行在 K8s 中的 OpenSearch 我查了下, 官方还没有提供完备的方案. 这里如何监控 K8s 中的 OpenSearch, 包括安装 exporter 插件、采集、展示全环节。 OpenSearch 简介…

RTL设计指导原则

RTL设计指导原则 一、面积与速度互换原则 1. 电路设计中的面积与速度 面积&#xff1a;设计所消耗的目标器件的硬件资源数量或者ASIC芯片的面积。 FPGA&#xff1a;所消耗的触发器(FF&#xff09;和查找表&#xff08;LUT)数量来衡量; ASIC&#xff1a;设计的面积、门数等衡…

【免安装的MATLAB--MATLAB online】

目录&#xff1a; 前言账号的注册图片处理的示例准备图片脚本函数 总结 前言 在计算机、数学等相关专业中&#xff0c;或多或少都会与MATLAB产生藕断丝连的联系&#xff0c;如果你需要使用MATLAB&#xff0c;但是又不想要安装到自己的电脑上&#xff08;它实在是太大了啊&#…

华为海思数字芯片设计笔试第四套

声明 下面的题目作答都是自己认为正确的答案&#xff0c;并非官方答案&#xff0c;如果有不同的意见&#xff0c;可以评论区交流。 这些题目也是笔者从各个地方收集的&#xff0c;感觉有些题目答案并不正确&#xff0c;所以在个别题目会给出自己的见解&#xff0c;欢迎大家讨论…

L1-041 寻找250

对方不想和你说话&#xff0c;并向你扔了一串数…… 而你必须从这一串数字中找到“250”这个高大上的感人数字。 输入格式&#xff1a; 输入在一行中给出不知道多少个绝对值不超过1000的整数&#xff0c;其中保证至少存在一个“250”。 输出格式&#xff1a; 在一行中输出第一次…

【架构-8】Lambda和Kappa架构

Lambda架构&#xff1f; Lambda架构&#xff08;三层架构&#xff09;&#xff1a; &#xff08;1&#xff09;将数据处理分为实时和离线两部分。离线部分通过批量计算处理数据&#xff0c;实时部分则通过增加追加方式将数据合并到批处理中。 &#xff08;2&#xff09;批处理…

js canvas实现裁剪图片并下载

简历上给自己挖的坑&#xff0c;面试被拷打&#xff0c;早就该填了T.T 参考&#xff1a;【js canvas实现图片裁剪】 https://www.bilibili.com/video/BV1QK411d7n1/?share_sourcecopy_web&vd_sourcebf743b20b76eab11028ba2fb05f056b4 效果 思路 组成&#xff1a; 上传文…

基于Springcloud可视化项目:智慧工地可视化大数据云平台源码

目录 技术架构 智慧工地系统在实际推行过程中遇到的问题 智慧工地接纳程度较低 基础设施条件有待完善 智慧工地整体生态尚未完善 智慧工地平台各功能模块 施工过程工信程息信管息理管模理块 人员管理模块 生产管理模块 技术管理模块 质量管理模块 安全管理模块 绿…

记录一个Kafka客户端Offset Explore连不上的问题

我昨天把集群重装了一下&#xff0c;再连这个工具就连不上了&#xff08;你先把zk和kafka在集群启起来&#xff09;&#xff0c;报错截图如下&#xff1a; 英文翻译过来大概就是说遍历zk指定路径不存在&#xff0c;我还以为zk的问题&#xff0c;回去又把zk的文档翻了一遍&#…

多线程代码案例之阻塞队列

目录 1.生产者消费者模型 2.使用标准库中的阻塞队列 3.模拟实现阻塞队列 在介绍阻塞队列之前&#xff0c;会先介绍一些前置知识&#xff0c;像队列&#xff1a;有普通队列、优先级队列、阻塞队列、和消息队列。前面两个是线程不安全的&#xff0c;而后面两个是线程安全的。本…

FFmpeg: 自实现ijkplayer播放器--03UI界面设计

文章目录 UI设计流程图UI设计界面点击播放功能实现 UI设计流程图 UI设计界面 主界面 控制条 播放列表 画面显示 标题栏 设置界面 提示框 点击播放功能实现 槽函数实现&#xff1a; connect(ui->ctrlBarWind, &CtrlBar::SigPlayOrPause, this, &Main…

软件杯 深度学习卷积神经网络垃圾分类系统 - 深度学习 神经网络 图像识别 垃圾分类 算法 小程序

文章目录 0 简介1 背景意义2 数据集3 数据探索4 数据增广(数据集补充)5 垃圾图像分类5.1 迁移学习5.1.1 什么是迁移学习&#xff1f;5.1.2 为什么要迁移学习&#xff1f; 5.2 模型选择5.3 训练环境5.3.1 硬件配置5.3.2 软件配置 5.4 训练过程5.5 模型分类效果(PC端) 6 构建垃圾…

InnoDB中高度为3的B+树最多可以存多少数据?

参考&#xff1a; &#x1f525;我说MySQL每张表最好不超过2000万数据&#xff0c;面试官让我回去等通知&#xff1f; - 掘金 考虑到磁盘IO是非常高昂的操作&#xff0c;计算机操作系统做了预读的优化&#xff0c;当一次IO时&#xff0c;不光把当前磁盘地址的数据&#xff0c;…

QtCreater 使用

QtCreater 创建项目 1.刚进入 QtCreater 的界面是这样的一个界面 ① 创建一个新的文件&#xff0c;那么我们就选择左上角的 “文件” ② 点击新建文件&#xff0c;或者也可以直接使用快捷键 CtrlN 此时就会弹出对话框&#xff0c;让我们选择想要创建的文件&#xff1a; Appli…