如何使用Graph API SDK v.19筛选含指定指标的Facebook广告
问题描述
我需要通过Facebook Graph API SDK v19,从广告账户中获取包含统计指标且spend≥0的广告,同时排除指定日期无指标数据的广告,但遇到两个困境:
- 过滤条件设为
spend≥0且reach≥1时,没有reach指标但spend=0且有其他行为数据的广告会被过滤掉 - 过滤条件设为
spend≥0且reach≥0时,会返回账户内所有广告(超5000条),包括完全无指标数据的广告
已尝试的Graph Explorer查询URL:
act_384943998894065/ads?fields=id,name, effective_status,created_time,insights.time_range({'since':'2024-06-19','until':'2024-06-19'}){ad_id,reach,spend,objective,actions,cost_per_action_type}&filtering=[{"field":"spend","operator":"GREATER_THAN_OR_EQUAL","value":0},{"field":"reach","operator":"GREATER_THAN_OR_EQUAL","value":0}]&time_range={'since':'2024-06-19','until':'2024-06-19'}
返回结果示例:
{ "id": "120208793679360133", "name": "CE1705202404", "effective_status": "ACTIVE", "created_time": "2024-05-17T14:59:20-0500" }, { "id": "120208458805660133", "name": "CE202404301910", "effective_status": "ACTIVE", "created_time": "2024-05-09T12:23:30-0500", "insights": { "data": [ { "ad_id": "120208458805660133", "spend": "0", "objective": "OUTCOME_ENGAGEMENT", "actions": [ { "action_type": "onsite_conversion.messaging_welcome_message_view", "value": "1" } ], "cost_per_action_type": [ { "action_type": "onsite_conversion.messaging_welcome_message_view", "value": "0" } ], "date_start": "2024-06-19", "date_stop": "2024-06-19" } ], "paging": { "cursors": { "before": "MAZDZD", "after": "MAZDZD" } } } }
当前PHP代码:
public function getAdsByAccountId($date) { try { $date_range = "{'since':'$date','until':'$date'}"; $time_range = "&time_range=$date_range"; $fields = [ "id", "campaign_id", "adset_id", "adset{promoted_object}", "creative{id,image_url,video_id,object_story_spec}", "name", "created_time", "status", "effective_status", "configured_status", "campaign{id,account_id, name, objective, effective_status, status, configured_status, created_time}", "insights.time_range($date_range){ad_id,reach,spend,objective,actions,cost_per_action_type}", ]; $string_fields = $this->buildFields($fields); $filtering = "&filtering=[{'field':'spend','operator':'GREATER_THAN_OR_EQUAL','value':0},{'field':'reach','operator':'GREATER_THAN_OR_EQUAL','value':1}]"; $limit = "&limit=200"; $url = "/" . $this->BUSINESS_ACCOUNT_ID . "/ads" . $string_fields . $filtering . $time_range . $limit; $response = $this->FB_SDK->get($url, $this->ACCESS_TOKEN); $response = json_decode($response->getBody()); $ads = $response->data; $data = $this->getAdsFromNextPages($response, $ads); $ads = $data->ads; $response = $data->response; return (object) [ "ads" => $ads, "response" => $response, ]; } catch (\Facebook\Exceptions\FacebookResponseException $e) { Log::error('FacebookAdsService::getAdsByAccountId Graph returned an error: ' . $e->getMessage()); throw $e; } catch (\Facebook\Exceptions\FacebookSDKException $e) { Log::error('FacebookAdsService::getAdsByAccountId Facebook SDK returned an error: ' . $e->getMessage()); throw $e; } }
解决方案
核心思路是直接从ads_insights端点查询数据,该端点默认仅返回带有统计指标的广告,同时配合简单过滤条件筛选spend≥0的条目,避免Graph API过滤逻辑的局限性。
修改后的PHP代码
public function getAdsByAccountId($date) { try { $date_range = json_encode(['since' => $date, 'until' => $date]); // 定义需要的字段:包含广告基础信息+统计指标 $fields = [ "ad_id", "ad_name", "ad_effective_status", "ad_created_time", "campaign_id", "campaign_name", "campaign_objective", "adset_id", "adset{promoted_object}", "creative{id,image_url,video_id}", "reach", "spend", "objective", "actions", "cost_per_action_type" ]; $string_fields = $this->buildFields($fields); // 构造查询参数 $params = http_build_query([ 'level' => 'ad', // 按广告维度返回数据 'time_range' => $date_range, 'limit' => 200, // 仅保留spend≥0的条目 'filtering' => json_encode([ ['field' => 'spend', 'operator' => 'GREATER_THAN_OR_EQUAL', 'value' => 0] ]) ]); // 直接请求ads_insights端点 $url = "/" . $this->BUSINESS_ACCOUNT_ID . "/ads_insights?" . $string_fields . "&" . $params; $response = $this->FB_SDK->get($url, $this->ACCESS_TOKEN); $response = json_decode($response->getBody()); $adsInsights = $response->data; // 处理分页获取全量数据 $data = $this->getAdsFromNextPages($response, $adsInsights); $adsInsights = $data->ads; $response = $data->response; // 将insights数据映射为原需求的广告结构 $ads = array_map(function($insight) use ($date) { return (object)[ 'id' => $insight->ad_id, 'name' => $insight->ad_name, 'effective_status' => $insight->ad_effective_status, 'created_time' => $insight->ad_created_time, 'campaign_id' => $insight->campaign_id, 'campaign' => (object)[ 'id' => $insight->campaign_id, 'name' => $insight->campaign_name, 'objective' => $insight->campaign_objective ], 'adset_id' => $insight->adset_id, 'adset' => $insight->adset, 'creative' => $insight->creative, 'insights' => (object)[ 'data' => [(object)[ 'ad_id' => $insight->ad_id, 'reach' => $insight->reach ?? null, 'spend' => $insight->spend, 'objective' => $insight->objective, 'actions' => $insight->actions ?? [], 'cost_per_action_type' => $insight->cost_per_action_type ?? [], 'date_start' => $date, 'date_stop' => $date ]] ] ]; }, $adsInsights); return (object) [ "ads" => $ads, "response" => $response, ]; } catch (\Facebook\Exceptions\FacebookResponseException $e) { Log::error('FacebookAdsService::getAdsByAccountId Graph returned an error: ' . $e->getMessage()); throw $e; } catch (\Facebook\Exceptions\FacebookSDKException $e) { Log::error('FacebookAdsService::getAdsByAccountId Facebook SDK returned an error: ' . $e->getMessage()); throw $e; } }
关键说明
- 改用
ads_insights端点:该端点默认只返回带有统计数据的广告,自动排除无指标的广告,无需额外过滤。 - 简化过滤规则:仅保留
spend≥0的条件,既包含有花费的广告,也包含spend=0但有其他行为数据的广告(比如示例中带欢迎消息浏览行为的广告)。 - 数据结构兼容:通过
array_map将ads_insights返回的字段映射为原需求的广告结构,确保返回格式与之前一致。
内容的提问来源于stack exchange,提问作者RONY FERNANDEZ
相关产品推荐
相关产品推荐

