Class: Facebook::AdvertiserApiClient
- Inherits:
-
BaseService
- Object
- BaseService
- Facebook::AdvertiserApiClient
- Defined in:
- app/services/facebook/advertiser_api_client.rb
Overview
Service object: advertiser API client.
Constant Summary collapse
- API_VERSION =
Marketing Graph API version. Meta versions the URL path; bump this
in lockstep when migrating to a newer API version (versions stay
supported for ~24 months, then auto-upgrade with possible breaking
changes — keep an eye on the changelog). 'v25.0'- BASE_URL =
URL for base.
"https://graph.facebook.com/#{API_VERSION}".freeze
- PAGE_LIMIT =
Page size for the campaigns list endpoint. Facebook caps
limitat
100 for campaign listings; well above the realistic active-campaign
count for one ad account. 100- CAMPAIGN_FIELDS =
Fields to request on each campaign — keeps the payload focused and
avoids Meta's "Please reduce the amount of data you're asking for"
errors when a large account has many campaigns. %w[ id name status effective_status objective daily_budget lifetime_budget created_time updated_time ].freeze
Instance Attribute Summary
Attributes inherited from BaseService
Instance Method Summary collapse
-
#campaigns_with_spend_since(ad_account_id:, token:, since:) ⇒ Set<String>
Campaign ids that recorded any spend on or after
since. -
#list_campaigns(ad_account_id:, token:) ⇒ Array<Hash>
List all campaigns on the ad account.
Methods inherited from BaseService
#initialize, #log_debug, #log_error, #log_info, #log_warning, #logger, #process, #tagged_logger
Constructor Details
This class inherits a constructor from BaseService
Instance Method Details
#campaigns_with_spend_since(ad_account_id:, token:, since:) ⇒ Set<String>
Campaign ids that recorded any spend on or after since. Drives
FacebookCampaignSyncWorker Source visibility — a campaign that
hasn't spent within the window is mirrored as an archived Source.
Walks the same cursor pagination as #list_campaigns. The insights
endpoint only returns rows for campaigns with delivery in the range,
so campaigns that never spent simply don't appear.
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'app/services/facebook/advertiser_api_client.rb', line 110 def campaigns_with_spend_since(ad_account_id:, token:, since:) spenders = Set.new cursor = nil loop do response = connection(token).get("act_#{ad_account_id}/insights") do |req| req.params['level'] = 'campaign' req.params['fields'] = 'campaign_id,spend' req.params['time_range'] = { since: since.iso8601, until: Date.current.iso8601 }.to_json req.params['limit'] = PAGE_LIMIT req.params['after'] = cursor if cursor end unless response.status == 200 body = safe_parse(response.body) err = body.dig('error', 'message') || body['message'] || "HTTP #{response.status}" raise "Facebook::AdvertiserApiClient: campaign insights failed (HTTP #{response.status}): #{err}" end body = safe_parse(response.body) Array(body['data']).each do |row| spenders << row['campaign_id'].to_s if row['spend'].to_f.positive? end next_cursor = body.dig('paging', 'cursors', 'after') break if next_cursor.blank? || body.dig('paging', 'next').blank? break if next_cursor == cursor # defensive — same cursor twice would loop forever cursor = next_cursor end spenders end |
#list_campaigns(ad_account_id:, token:) ⇒ Array<Hash>
List all campaigns on the ad account. Walks Meta's paging.cursors.after
cursor pagination until paging.next stops being present and returns
the concatenated list.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'app/services/facebook/advertiser_api_client.rb', line 66 def list_campaigns(ad_account_id:, token:) campaigns = [] cursor = nil loop do response = connection(token).get("act_#{ad_account_id}/campaigns") do |req| req.params['limit'] = PAGE_LIMIT req.params['fields'] = CAMPAIGN_FIELDS.join(',') req.params['after'] = cursor if cursor end unless response.status == 200 body = safe_parse(response.body) err = body.dig('error', 'message') || body['message'] || "HTTP #{response.status}" raise "Facebook::AdvertiserApiClient: list_campaigns failed (HTTP #{response.status}): #{err}" end body = safe_parse(response.body) page = Array(body['data']) campaigns.concat(page) next_cursor = body.dig('paging', 'cursors', 'after') break if next_cursor.blank? || body.dig('paging', 'next').blank? break if next_cursor == cursor # defensive — same cursor twice would loop forever cursor = next_cursor end campaigns end |