Class: Marketing::AdSpend::MicrosoftAdapter

Inherits:
Object
  • Object
show all
Defined in:
app/services/marketing/ad_spend/microsoft_adapter.rb

Overview

Daily campaign spend from Microsoft (Bing) Ads via the v13 Reporting API.

MicrosoftAds::ReportingClient is shared with the assistant's report tool,
whose POLL_TIMEOUT is tuned to a chat turn. A single-day campaign report is
small and lands well inside it; a timeout or failure surfaces as an empty
result plus a logged warning rather than a raise, so one slow provider never
fails the whole nightly sync.

Constant Summary collapse

PROVIDER =

Provider key recorded on ad spend rows produced by this adapter.

'microsoft_ads'
COLUMNS =

CampaignId is absent from the client's DEFAULT_COLUMNS but is required to
map rows back to their Source.

%w[CampaignId CampaignName Spend Impressions Clicks Conversions].freeze

Class Method Summary collapse

Class Method Details

.call(date) ⇒ Array<Hash>

Returns { external_id:, spend:, clicks:, impressions:, conversions: }.

Parameters:

  • date (Date)

Returns:

  • (Array<Hash>)

    { external_id:, spend:, clicks:, impressions:, conversions: }



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'app/services/marketing/ad_spend/microsoft_adapter.rb', line 19

def self.call(date)
  result = MicrosoftAds::ReportingClient.new(**credentials).run_report(
    type: 'campaign', start_date: date, end_date: date,
    columns: COLUMNS, aggregation: 'Daily'
  )

  unless result[:status] == :ok
    Rails.logger.warn("[Marketing::AdSpend::MicrosoftAdapter] #{result[:status]}: #{result[:error]}")
    return []
  end

  Array(result[:rows]).map do |row|
    {
      external_id: row['CampaignId'].to_s,
      spend: row['Spend'].to_f,
      clicks: row['Clicks'].to_i,
      impressions: row['Impressions'].to_i,
      conversions: row['Conversions'].to_f
    }
  end
end

.credentialsHash{Symbol => String}

Same config shape the assistant's report tool uses, built here so the
nightly sync doesn't depend on an Assistant class.

Returns:

  • (Hash{Symbol => String})


45
46
47
48
49
50
51
52
# File 'app/services/marketing/ad_spend/microsoft_adapter.rb', line 45

def self.credentials
  {
    developer_token: Heatwave::Configuration.fetch(:microsoft_ads, :developer_token),
    access_token: MicrosoftAds::OauthService.new.access_token!,
    customer_id: Heatwave::Configuration.fetch(:microsoft_ads, :customer_id),
    account_id: Heatwave::Configuration.fetch(:microsoft_ads, :account_id)
  }
end