Skip to content
Dashboard

ChatGPT Ads

Use the ChatGPT Ads connector to sync ad account configuration, campaign hierarchy, product feeds, custom audiences, and daily performance insights (including segmented breakdowns by country, device, and platform) into your Athena lakehouse. This is a Blotout custom connector built on the Airbyte Connector Builder (declarative manifest).

  • A tag with Blotout Cloud set up (green checkmark in the Tags table)
  • A ChatGPT Ads API key — created in Ads Manager under account settings
  • The ad account must be active with at least one campaign

Follow the shared Create a pipeline steps until the source catalogue appears, then select ChatGPT Ads.

On the Source step, configure the connector:

FieldPurpose
Schedule TypeHow the pipeline runs — typically Scheduled
Sync FrequencyHow often Airbyte syncs (for example, Every 24 hours)
Source NameName for this pipeline — used in the Athena schema <SOURCE_NAME>_<ENV>

Every request carries Authorization: Bearer <key>.

FieldTypeRequiredDefaultDescription
api_keysecret stringYes—ChatGPT Ads API key. One key = one ad account.
start_datestringYes—Earliest date for insights (YYYY-MM-DD), read in the ad account’s timezone. Retention: 365 days for delivery, ~30 days for product reporting.
end_datestringNoTodaySet only for a bounded backfill.
lookback_daysintegerNo7Rewind before the stored cursor. Spend and attribution are not settled on the day they happen.
include_conversion_metricsbooleanNotrueAdds conversion/revenue fields to entity-level insights. Turn off if a 400 names a conversion field.
page_sizeintegerNo500List endpoints; API max 500.
insights_page_sizeintegerNo1000Insights endpoints; API max 2000.
base_urlstringNohttps://api.ads.openai.com/v1Override only for a dedicated host. Keep the /v1.
  • Full Refresh (10 dimension streams)
  • Incremental Sync — Append, cursor date (8 metric streams)
StreamEndpointPrimary KeyNotes
ad_accountGET /ad_accountidSingle row. The check stream. Carries timezone and currency_code.
campaignsGET /campaignsidBudgets in micros, times as unix integers.
ad_groupsGET /ad_groups?campaign_id=idSubstream over campaigns. campaign_id added by connector.
adsGET /ads?ad_group_id=idSubstream over ad groups. ad_group_id added by connector.
product_feedsGET /feedsfeed_idCatalogue health with product_count.
product_feed_uploadsGET /feeds/uploadsupload_idrows_accepted / rows_rejected / rows_ads_eligible + diagnostics.
custom_audiencesGET /custom_audiencesidMatch counts are range strings, not numbers.
spend_limit_windowsGET /ad_account/spend_limit_windowswindow_idBudget pacing: amount_micros vs spent_micros.
conversion_event_settingsGET /conversions/event_settingsidAttribution window — may require enablement.
conversion_pixelsGET /conversions/pixelsidMay require enablement — 404 is a provisioning state.

Metric streams (Incremental — cursor date)

Section titled “Metric streams (Incremental — cursor date)”

All eight hit GET /ad_account/insights with different aggregation_level and segments[] values.

StreamAggregationSegmentsPrimary Key
insights_account_dailyad_account—date
insights_campaign_dailycampaign—date, campaign_id
insights_ad_group_dailyad_group—date, ad_group_id
insights_ad_dailyad—date, ad_id
insights_campaign_by_countrycampaigncountrydate, campaign_id, country_name
insights_campaign_by_devicecampaigndevicedate, campaign_id, device_type
insights_campaign_by_platformcampaignplatformdate, campaign_id, platform
insights_product_dailycampaignproductdate, campaign_id, product_feed_id, item_id

Hierarchy is not in the payload — ad_groups has no campaign_id in the API response; ads has no ad_group_id. The connector partitions over parent streams and stamps the parent ID onto each record. These fields are added by the connector, not the API.

Insights project nothing unless asked — omitting fields[] returns only impressions. Every insights stream sends an explicit field list.

Money: micros vs plain — *_micros on campaigns/ad groups/spend limits are millionths of the account currency. Insights spend is already a plain number. Do not divide both by 1e6.

Ratios do not re-aggregate — ctr, cpc, cpm, cpa, post_click_cvr, order_created_roas are computed by the API over its row grain. Recompute from base measures in dbt.

  • Schema: chatgpt_ads_<client>_prod.*
  • Deduplication for insights streams:
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY date, campaign_id
ORDER BY _airbyte_extracted_at DESC
) AS rn
FROM chatgpt_ads_<client>_prod.insights_campaign_daily
) WHERE rn = 1
VersionDateDescription
1.0.02026-09Initial release with 18 streams: 10 dimension (Full Refresh) + 8 metric (Incremental Append)

Continue through the Schema and Summary steps to choose streams and confirm the connection. Save and run the first sync.

After a successful sync, Airflow creates an organization-scoped DAG for the pipeline, and dbt models feed downstream analytics.