Class: FacebookCampaignSyncWorker

Inherits:
Object
  • Object
show all
Includes:
Sidekiq::Job
Defined in:
app/workers/facebook_campaign_sync_worker.rb

Overview

Sidekiq worker: syncs Facebook/Meta Ads campaigns into the sources
table once a day.

Direct parallel to GoogleAdsCampaignSyncWorker,
OpenaiAdsCampaignSyncWorker, and PinterestCampaignSyncWorker: every
active or paused campaign on the Facebook ad account gets a 1:1
Source record under the "Facebook Ads" sub-parent (seeded by
20260515110902_seed_facebook_ads_and_organic_sub_sources.rb).

Source visibility is spend-driven: a campaign that has spent within
the last SPEND_LOOKBACK_DAYS is mirrored as :active; one dark
longer — or whose campaign was archived/deleted on Facebook — becomes
:archived rather than being destroyed, so historical attribution on
old visits / orders survives. Facebook leaves old boosted-post
campaigns at status ACTIVE forever, so spend recency, not status, is
the signal for what's actually running.

Scheduled at 01:45 America/Chicago daily — 45 minutes after Google
(01:00), 30 after OpenAI (01:15), and 15 after Pinterest (01:30) so
the four API ceilings don't compete for the same window.

See Also:

Constant Summary collapse

ACTIVE_STATUSES =

Facebook campaign status values that should appear as active Source
records. "ARCHIVED" / "DELETED" map to local Source#visibility = :archived. Pinterest and Facebook both use uppercase status values
(vs OpenAI's lowercase).

%w[ACTIVE PAUSED].freeze
SPEND_LOOKBACK_DAYS =

A campaign Source is mirrored as :active only when its campaign has
spent within this many days; longer-dark campaigns become :archived.

180

Instance Method Summary collapse

Instance Method Details

#performObject



41
42
43
44
45
46
47
48
49
50
51
# File 'app/workers/facebook_campaign_sync_worker.rb', line 41

def perform
  unless marketing_api_credentials_present?
    logger.warn('FacebookCampaignSyncWorker: skipping — Facebook Marketing API credentials not ' \
                'configured (facebook.advertiser_access_token / facebook.ad_account_id)')
    return
  end

  Source.with_advisory_lock('facebook_campaign_sync', timeout_seconds: 10) do
    sync_campaigns
  end
end