The Microsoft Ads conversion upload service is already deployed and ready. This guide covers the steps to enable it.
MicrosoftAdsConversionUploadService - uploads conversions via Microsoft Ads APIPushConversionToMicrosoftAdsJob - queues uploads when conversions have msclkid| Goal Name | Type | Revenue | Value |
|---|---|---|---|
| Lead | Offline conversion | Each conversion action has the same value | $7.00 |
| Quote | Offline conversion | Each conversion action has the same value | $20.00 |
| Purchase | Offline conversion | Conversion action value may vary | (dynamic) |
Quarry Rentals Microsoft AdsAccounts in any organizational directory and personal Microsoft accountshttps://admin.quarryrents.com/oauth/microsoft/callback (or http://localhost:3000/oauth/microsoft/callback for testing)Run this in Rails console to start OAuth flow:
# Generate authorization URL
client_id = "YOUR_CLIENT_ID"
redirect_uri = "https://admin.quarryrents.com/oauth/microsoft/callback"
scope = "https://ads.microsoft.com/msads.manage offline_access"
auth_url = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?" +
"client_id=#{client_id}&" +
"response_type=code&" +
"redirect_uri=#{CGI.escape(redirect_uri)}&" +
"scope=#{CGI.escape(scope)}"
puts auth_url
code parameterrequire 'net/http'
require 'uri'
require 'json'
code = "THE_CODE_FROM_REDIRECT"
client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"
redirect_uri = "https://admin.quarryrents.com/oauth/microsoft/callback"
uri = URI("https://login.microsoftonline.com/common/oauth2/v2.0/token")
response = Net::HTTP.post_form(uri, {
client_id: client_id,
client_secret: client_secret,
code: code,
redirect_uri: redirect_uri,
grant_type: "authorization_code",
scope: "https://ads.microsoft.com/msads.manage offline_access"
})
tokens = JSON.parse(response.body)
puts "Refresh Token: #{tokens['refresh_token']}"
Add to .kamal/secrets:
# Microsoft Ads API
export MICROSOFT_ADS_CLIENT_ID="your-azure-app-client-id"
export MICROSOFT_ADS_CLIENT_SECRET="your-azure-app-client-secret"
export MICROSOFT_ADS_REFRESH_TOKEN="your-refresh-token"
export MICROSOFT_ADS_DEVELOPER_TOKEN="your-developer-token"
export MICROSOFT_ADS_ACCOUNT_ID="your-account-id"
export MICROSOFT_ADS_CUSTOMER_ID="your-customer-id"
export MICROSOFT_ADS_LEAD_GOAL_NAME="Lead"
export MICROSOFT_ADS_QUOTE_GOAL_NAME="Quote"
export MICROSOFT_ADS_PURCHASE_GOAL_NAME="Purchase"
source .kamal/secrets && kamal deploy
After deploying, test with a conversion that has an msclkid:
# In Rails console
conversion = Conversion.find_by(msclkid: "some_msclkid")
conversion.reset_microsoft_ads_for_retry!
PushConversionToMicrosoftAdsJob.perform_now(conversion.id)
Check the logs for success/failure messages.
The service gracefully skips if any required env var is missing. Check all env vars are set.
Refresh tokens are long-lived but can expire. Re-run the OAuth flow in Step 5 if needed.
Check conversion.microsoft_ads_error for error details. Common issues:
The system has been capturing msclkid from landing URLs. To push historical conversions:
# Find conversions with msclkid that haven't been pushed
Conversion.where.not(msclkid: [nil, ""]).where(microsoft_ads_status: "skipped").find_each do |c|
c.reset_microsoft_ads_for_retry!
PushConversionToMicrosoftAdsJob.perform_later(c.id)
end
app/services/microsoft_ads_conversion_upload_service.rbapp/jobs/push_conversion_to_microsoft_ads_job.rbapp/models/conversion.rb (Microsoft Ads methods)config/deploy.yml (env var declarations)