ChatGPT Ads Insights API: non-goal conversion reporting

Tarun Kapoor, founder of Context Hints, seated at a wooden desk with a soft city light behind him.Tarun Kapoor Updated 1 October 2026 22 min read

Non-goal conversion reporting is a ChatGPT Ads Insights API capability that returns attributed conversion events beyond a campaign's selected goal — for example, attributed purchases for a campaign optimising toward leads or checkouts — without changing its conversion goal or optimisation settings. You call POST https://api.ads.openai.com/v1/conversions/insights with include: ["attributed_events"]. This guide explains every request parameter OpenAI has published, what the response contains, how attribution windows and time basis change the numbers, how to handle the 2,000-row 413 limit, and the reporting use cases that make it worth wiring up — with working curl examples.

The short version

  • What it does: reports attributed conversion events other than a campaign's goal — e.g. purchases on a campaign optimising for leads — with no change to goal or optimisation.
  • Endpoint: POST /v1/conversions/insights on api.ads.openai.com, Bearer token auth, include: ["attributed_events"].
  • Knobs: attribution_window_days 7 / 14 / 30 (default 30), view_through_attribution_window_days 0 / 1 (default 1), attribution_time_basis ad_event_time (default) or conversion_time.
  • Caveat: conversion_time basis has limited coverage of non-goal events. Use the default for non-goal work.
  • Limits: HTTP 413 if a report exceeds 2,000 summary rows, 2,000 event rows, or 2,000 breakdown entries for one event. Split by campaign or date and retry.
  • Why it matters: you can optimise where the signal is dense and still report where the money is — purchases, revenue and ROAS.
A tall blue glass column topped by a bright disk beside a row of five smaller, paler glass disks on a clear rail - one optimised goal plus other outcomes made visible.
One goal drives optimisation; non-goal reporting makes the other attributed outcomes visible beside it.

What is non-goal conversion reporting in ChatGPT Ads?

Non-goal conversion reporting lets you retrieve attributed conversion events that are not the campaign's selected conversion goal. If a campaign optimises toward a lead or checkout event, you can still see attributed purchases — counts and values — through the public Insights API. The campaign's goal and optimisation settings do not change.

Before this, a ChatGPT Ads campaign's conversion reporting centred on its own goal. That forced an uncomfortable choice. Optimise for purchases and you might starve the algorithm of signal in a young, low-volume channel. Optimise for an upstream event with more volume and you lose sight of the thing the business actually cares about. Advertisers ended up stitching purchase data back in from their own analytics, with all the attribution mismatches that implies.

Non-goal reporting closes that gap inside OpenAI's own attribution. The same attribution engine that credits your goal event also credits your other recognised events, and you can pull those numbers per campaign, per day, with the windows you choose. For the underlying tracking this depends on, see ChatGPT Ads conversion tracking.

Scope of this guide Everything about the endpoint, parameters, fields and limits comes from OpenAI's Ads API reporting documentation and its “What's new in Ads Manager” note for the week of 25 September 2026. Advice on when and how to use it is my own operator practice and is labelled as such. The example response values are illustrative.

Why would you optimise for one event and report on another?

Because the best optimisation signal and the best business metric are often different events. Upstream events such as leads or checkouts happen more often, so bidding learns faster. Purchases and revenue are what finance cares about. Non-goal reporting lets you bid on the dense signal and still judge the campaign on the valuable one.

This is standard practice on mature platforms, and it matters more on a young one. Volume on ChatGPT is still modest for most advertisers; a campaign that needs a steady flow of conversions to learn may simply not see enough purchases in its early weeks. The conversion campaigns guide covers how oCPC learns; here is how the reporting side now fits:

BusinessOptimise toward (goal)Report via non-goal eventsWhat you learn
Ecommerce, young accountcheckout_startedorder_created count and valueTrue ROAS without starving learning
Lead gen with online saleslead_createdPurchases or subscriptionsWhich campaigns produce buyers, not just leads
Subscription app / SaaSTrial or signup eventsubscription_createdPaid conversion rate by campaign
Retailer with feed campaignsUpstream commerce eventPurchases per campaignWhich product groups earn their spend
Any advertiser with custom eventsPrimary goalCustom events (by exact name)Secondary actions like demo bookings or high-value page views

The event names above are the standard events used elsewhere in our tracking guides; your own recognised events are whatever you have configured. The point is the pattern, not the specific names.

How does the /v1/conversions/insights endpoint work?

Send an authenticated POST to https://api.ads.openai.com/v1/conversions/insights with a JSON body naming the aggregation level, time granularity, time ranges, entity IDs and attribution settings, and set include to ["attributed_events"]. The response returns summary conversion fields plus an attributed_events array, one item per entity and event.

Authentication uses a Bearer token in the Authorization header, conventionally held in an environment variable such as OPENAI_ADS_API_KEY. Never hard-code the key in scripts or commit it to version control. Here is the minimal request that returns all recognised attributed events for one campaign across one week:

curl -X POST https://api.ads.openai.com/v1/conversions/insights \
  -H "Authorization: Bearer ${OPENAI_ADS_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "aggregation_level": "campaign",
    "time_granularity": "none",
    "time_ranges": [
      "{\"type\":\"unix_range\",\"start\":\"1788235200\",\"end\":\"1788840000\"}"
    ],
    "entity_ids": ["cmpn_123"],
    "attribution_time_basis": "ad_event_time",
    "attribution_window_days": 30,
    "view_through_attribution_window_days": 1,
    "include": ["attributed_events"]
  }'

Two details catch people out. First, each time_ranges item is a JSON-encoded string describing a unix_range, not a nested object — note the escaped quotes. Second, start and end are Unix timestamps in seconds, supplied as strings. In the example, 1788235200 to 1788840000 is a seven-day span.

What do the request parameters do?

The body controls four things: what you are grouping by (aggregation level and entity IDs), over what time (time ranges and granularity), how attribution is counted (windows and time basis), and what extra detail comes back (include and event names). The table lists every parameter OpenAI documents for this endpoint.

ParameterAccepted valuesDefaultWhat it controls
aggregation_level"campaign" (as documented in the example)—The entity level rows are grouped by
time_granularity"daily" or "none"—One row per day, or one row for the whole range
time_rangesArray of JSON strings, each a unix_range with start and end—Reporting period(s)
entity_idsArray of IDs, e.g. ["cmpn_123"]—Which campaigns to report on
attribution_time_basis"ad_event_time" or "conversion_time"ad_event_timeWhether conversions are dated to the ad interaction or the conversion
attribution_window_days7, 14, 3030How long after an ad interaction a conversion can be credited
view_through_attribution_window_days0 or 11View-through window; 0 excludes view-through attribution
include["attributed_events"]—Adds the per-event breakdown, including non-goal events
event_namesExact standard or custom event namesAll recognised eventsFilters the breakdown to specific events

Which events count as “recognised”?

event_names filters by exact name, and only recognised events are reported. OpenAI defines recognised events as those configured in your conversion event settings, or those that appear in your published received-event history. In practice: if an event is firing correctly and visible in your event history, or you have set it up in conversion event settings, you can report on it. If a name is misspelt or the event never arrived, you will get nothing back for it — check spelling and casing before assuming the campaign drove zero. The event quality guide covers how to confirm events are arriving cleanly.

How do attribution windows change the numbers?

A longer click window credits conversions that happen longer after the ad interaction, so 30-day numbers are always equal to or higher than 7-day numbers for the same period. Setting the view-through window to 0 removes conversions credited to ad views without clicks. Pick windows that match your buying cycle and keep them fixed across reports.

SettingUse whenTrade-off
30-day click, 1-day view (default)Considered purchases, B2B, high-ticket itemsNumbers mature slowly; recent days look low until the window closes
14-day clickMid-consideration retailA middle ground; less lag than 30 days
7-day clickImpulse or low-ticket purchases; fast decision cyclesUndercounts slower buyers
View-through 0Conservative reporting, finance-facing ROAS, comparing against click-only analyticsDrops any credit for ads seen but not clicked
View-through 1Understanding full ad influenceIncludes conversions some stakeholders will question

My rule: report the default (30-day click, 1-day view) as the headline because it matches Ads Manager's defaults, and keep a click-only (view-through 0) series alongside it for finance. When the two diverge a lot, that tells you how much of the story relies on view-through credit. Whatever you choose, never change windows mid-series — it creates a step change that looks like performance but is just accounting.

The summary fields split the goal total into click_through_conversions and view_through_conversions, and each attributed event item carries the same split. That makes it simple to produce both views from one request with view_through_attribution_window_days: 1: add both for the full number, use only the click-through figure for the conservative one.

What is attribution_time_basis, and which should you use?

attribution_time_basis decides which date a conversion is reported on. The default, ad_event_time, dates it to the ad interaction that earned the credit; conversion_time dates it to when the conversion happened. OpenAI notes that conversion_time has limited coverage of non-goal events, so use the default for non-goal reporting.

The difference matters most for daily reporting. Under ad_event_time, a purchase made on Friday from an ad clicked on Monday shows up on Monday, which ties conversions to the spend that caused them — the right view for judging campaign efficiency. Under conversion_time, it shows up on Friday, which is closer to how your ecommerce platform or finance system records revenue.

A related consequence of ad_event_time: recent days keep growing as late conversions are credited back to them. Yesterday's ROAS is not final. Either report on periods old enough for your window to have closed, or label recent periods as provisional. We cover this reporting-lag trap in measuring ChatGPT Ads ROI.

What does the response contain?

The response carries summary fields for the goal — conversions, click_through_conversions and view_through_conversions — and, with include set, an attributed_events array. Each item names the entity, event name and kind, attributed count, click and view split, and value amount, value count and currency, plus a breakdown by conversion event setting.

The shape below is illustrative: field names are OpenAI's, the values and simplified nesting are mine. Check the reference documentation for the exact structure your integration receives.

{
  "account_currency": "USD",
  "order_created_attributed_sales": 18420.50,
  "order_created_attributed_sales_currency": "USD",
  "conversions": 212,
  "click_through_conversions": 188,
  "view_through_conversions": 24,
  "attributed_events": [
    {
      "entity_id": "cmpn_123",
      "event_name": "order_created",
      "event_kind": "standard",
      "attributed_event_count": 141,
      "click_through_conversions": 129,
      "view_through_conversions": 12,
      "attributed_event_value_amount": 18420.50,
      "attributed_event_value_count": 139,
      "attributed_event_value_currency": "USD",
      "conversion_event_setting_breakdowns": [ ... ]
    }
  ]
}
FieldMeaning
conversionsGoal conversions, counting clicks and views within the chosen windows
click_through_conversions / view_through_conversionsThe goal total split by interaction type
account_currencyThe ad account's currency
order_created_attributed_sales (+ _currency)Attributed sales value for the order-created event
attributed_events[].entity_idThe campaign the event is attributed to
event_name / event_kindThe event's exact name and whether it is standard or custom
attributed_event_countNumber of attributed occurrences of that event
click_through_conversions / view_through_conversions (per event)The event's count split by interaction type
attributed_event_value_amountTotal attributed value for the event
attributed_event_value_countHow many of those events carried a value
attributed_event_value_currencyCurrency of the value
conversion_event_setting_breakdownsThe event broken down by conversion event setting

Read the value count, not just the value

attributed_event_value_count is the quiet hero of the response. If a campaign shows 141 attributed purchases but a value count of 90, then 51 purchases arrived without a value — and your revenue figure is understated by roughly a third. Always compare count and value count before trusting a ROAS number. A gap usually means some purchase events are sent without an amount, often from one checkout path or one integration. Fixing it is a tracking job, covered in conversion tracking and advanced matching.

Done for you: conversion tracking implementation

Non-goal reporting is only as good as the events behind it. Our tracking setup service installs the pixel and Conversions API, makes sure purchase events carry values, and wires the Insights API into your reporting — from $3,999.

How do you filter to one event, such as purchases?

Add event_names with the exact event name. This request pulls daily attributed purchases for two campaigns over a week, on a 7-day click window with view-through excluded — a conservative, finance-friendly view:

curl -X POST https://api.ads.openai.com/v1/conversions/insights \
  -H "Authorization: Bearer ${OPENAI_ADS_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "aggregation_level": "campaign",
    "time_granularity": "daily",
    "time_ranges": [
      "{\"type\":\"unix_range\",\"start\":\"1788235200\",\"end\":\"1788840000\"}"
    ],
    "entity_ids": ["cmpn_123", "cmpn_456"],
    "attribution_window_days": 7,
    "view_through_attribution_window_days": 0,
    "include": ["attributed_events"],
    "event_names": ["order_created"]
  }'

Filtering keeps responses small, which matters for the row limits below, and makes downstream processing simpler: every item in attributed_events is the event you asked for. When you need several events, list them all in one request rather than calling once per event, and split by campaign or date instead if the response grows too large.

What are the 413 limits, and how do you avoid them?

The endpoint returns HTTP 413 when a report would exceed 2,000 summary rows, 2,000 event rows, or 2,000 conversion-event-setting breakdown entries for a single event. The fix is to split the request — fewer campaigns per call, shorter date ranges, time_granularity: "none" instead of daily, or an event_names filter — and combine the results yourself.

Rows multiply quickly. Daily granularity across 90 days for 30 campaigns is 2,700 summary rows before a single event is counted, which already crosses the limit. Rough arithmetic before calling saves a lot of retry logic:

DriverEffect on row countHow to reduce
Number of campaignsMultiplies every row typeBatch campaigns into groups
Daily vs. none granularityDaily multiplies by the number of daysUse none for period totals
Date range lengthMultiplies daily rowsRequest in weekly or monthly chunks
Number of eventsMultiplies event rowsFilter with event_names
Conversion event settings per eventDrives breakdown entriesSplit by campaign so each event's breakdown stays small

A simple, robust pattern is to catch 413 and bisect — halve the campaign list, or if you are down to one campaign, halve the date range — then retry each half. This Python sketch does exactly that:

import json, os, requests

URL = "https://api.ads.openai.com/v1/conversions/insights"
HEADERS = {"Authorization": f"Bearer {os.environ['OPENAI_ADS_API_KEY']}"}

def unix_range(start, end):
    # time_ranges items are JSON-encoded strings, not objects
    return json.dumps({"type": "unix_range", "start": str(start), "end": str(end)})

def fetch(campaign_ids, start, end, events=None, window=30, vta=1):
    body = {
        "aggregation_level": "campaign",
        "time_granularity": "daily",
        "time_ranges": [unix_range(start, end)],
        "entity_ids": campaign_ids,
        "attribution_window_days": window,
        "view_through_attribution_window_days": vta,
        "include": ["attributed_events"],
    }
    if events:
        body["event_names"] = events
    r = requests.post(URL, headers=HEADERS, json=body, timeout=60)
    if r.status_code == 413:
        # too many rows: split the work and try again
        if len(campaign_ids) > 1:
            mid = len(campaign_ids) // 2
            return fetch(campaign_ids[:mid], start, end, events, window, vta) + \
                   fetch(campaign_ids[mid:], start, end, events, window, vta)
        mid = (start + end) // 2
        return fetch(campaign_ids, start, mid, events, window, vta) + \
               fetch(campaign_ids, mid, end, events, window, vta)
    r.raise_for_status()
    return [r.json()]

Use daily boundaries when splitting date ranges in production so that daily rows do not straddle two requests. The sketch is deliberately minimal — add retries for transient errors and logging before putting it on a schedule.

How do you calculate true ROAS with non-goal events?

Pull spend per campaign from the Insights endpoints, pull attributed purchase value per campaign from /v1/conversions/insights with the same date range, windows and time basis, and divide value by spend. Check that value count matches purchase count, keep currencies consistent, and report recent days as provisional until the attribution window has closed.

  1. Get spend. Use GET /v1/campaigns/{id}/insights or GET /v1/ad_account/insights with fields including spend, impressions, clicks. These endpoints use time_ranges as date ranges with since, until and timezone.
  2. Get attributed purchases. Call /v1/conversions/insights with event_names set to your purchase event and include: ["attributed_events"].
  3. Align the periods. The two endpoints express time differently — Unix ranges on one, dated ranges with a timezone on the other. Convert carefully using the ad account's time zone so both cover the same days.
  4. Join on campaign ID and compute attributed_event_value_amount / spend.
  5. Sanity-check value coverage by comparing attributed_event_value_count with attributed_event_count.
  6. Check currency. Compare attributed_event_value_currency with account_currency before dividing.
  7. Mark provisional periods that are still inside the attribution window.

For campaigns whose goal is already purchases, the standard Insights fields order_created_attributed_sales and order_created_roas give you this directly. Non-goal reporting is what lets you compute the same figure for campaigns optimising toward something else — which, in young accounts, is often most of them.

A worked example

A retailer runs two campaigns. Campaign A optimises for purchases; Campaign B optimises for checkouts because purchase volume was too thin for it to learn. Before non-goal reporting, B's dashboard showed cost per checkout only, and the team argued about whether those checkouts turned into orders. Now one request returns B's attributed purchases and their value. If B spends 4,000 in a month and non-goal reporting shows 9,600 in attributed purchase value, B is running at 2.4x on the same attribution basis as A — a like-for-like comparison without touching either campaign's settings. (Illustrative numbers.)

What is the fastest way to get a first non-goal report?

Pick one campaign that optimises toward an upstream event, find its campaign ID in Ads Manager, and run the minimal curl request above for the last full week with default windows. Read the attributed_events array: if your purchase event appears with a count and value, you have your first non-goal ROAS figure.

  1. Create or locate an API key for the Ads API and store it as OPENAI_ADS_API_KEY in your shell or secrets manager.
  2. Choose a campaign with at least a few weeks of delivery, so there is something to attribute.
  3. Pick a closed period. A week that ended more than 30 days ago gives final numbers on the default window; a recent week is fine for a first look, but label it provisional.
  4. Convert the dates to Unix seconds in the ad account's time zone.
  5. Run the request without event_names first, so you can see every recognised event the campaign is credited with.
  6. Note the exact event names returned, then add event_names for the ones you will report on regularly.
  7. Pull spend for the same period from the campaign insights endpoint and compute ROAS.

What are the best use cases for non-goal reporting?

Five use cases pay back fastest: true ROAS on upstream-optimised campaigns, lead-to-sale quality by campaign, deciding when to switch a campaign's goal, reporting custom secondary actions, and giving finance a conservative click-only view. Each uses the same endpoint with different filters and windows.

1. True ROAS on upstream-optimised campaigns

Covered above. It is the most common reason to wire this up and the one most stakeholders will ask for first.

2. Lead quality by campaign

Lead-gen advertisers with any downstream online conversion — a purchase, a paid subscription, a booked call recorded as a custom event — can now see which campaigns produce leads that go on to convert. Two campaigns with the same cost per lead can differ enormously in cost per customer. That difference used to require CRM joins; for events that reach OpenAI's attribution, it now comes back from the API.

3. Deciding when to switch goals

A campaign optimised for checkouts that now shows steady attributed purchases may be ready to move its goal to purchases. Non-goal reporting gives you the purchase volume history to make that call on evidence rather than guesswork. Changing the goal is a campaign setting change with its own learning implications; reading the numbers first costs nothing.

4. Custom secondary actions

If you send custom events — say, a pricing-page view or a demo request — you can report them by exact name alongside the goal. That is useful for B2B advertisers whose real conversion happens offline weeks later; mid-funnel custom events show which campaigns are moving people forward. See our small business guide for lighter-weight versions of this setup.

5. A finance-safe view

Set view_through_attribution_window_days to 0 and a short click window for a conservative report. It will never match your analytics exactly, but it removes the most common objection — “you're counting people who never clicked” — and gives finance a floor to plan against.

How does this relate to the other Insights endpoints?

The Insights API also has GET endpoints for the ad account, campaigns, ad groups and ads, which return delivery and performance fields such as impressions, clicks, spend, CTR, conversions, attributed sales and ROAS, with segments by country, device, platform and product. The conversions insights endpoint adds the non-goal event breakdown those do not provide.

Entity insights (GET)Conversions insights (POST)
Endpoints/v1/ad_account/insights, /v1/campaigns/{id}/insights, /v1/ad_groups/{id}/insights, /v1/ads/{id}/insights/v1/conversions/insights
Best forSpend, delivery, CTR, goal conversions, segmentsAttributed events beyond the goal; per-event counts and values
Time rangesDate ranges with since, until, timezoneJSON-string unix_range with start, end
Segmentscountry, device, platform, productCampaign-level aggregation (as documented)
Notable fieldsimpressions, clicks, spend, ctr, conversions, order_created_attributed_sales, order_created_roas, product.feed_id, product.item_id, product.titleattributed_events with count, click/view split, value amount, value count, currency, setting breakdowns
Other parametersaggregation_level, time_granularity, fields[], segments[], filters[], sort[]Attribution windows, time basis, include, event_names

Two details worth knowing from the same documentation. ctr is returned as a ratio — 0.04 means 4% — so do not multiply by 100 twice in your dashboard. And delivery data is retained for 365 days at non-hourly granularity, so if you want longer history, store the results yourself on a schedule. For product-level analysis of feed campaigns, pair the product segment with bulk-built feed campaigns and the carousel reporting described in the product feed guide.

How should you build a reporting pipeline around it?

Run a scheduled job that pulls entity insights for spend and conversions insights for attributed events, stores raw responses, and rebuilds the last 30 days on every run so late-attributed conversions are captured. Join on campaign ID and date, keep window settings fixed, and label periods still inside the attribution window as provisional.

  1. Schedule daily. Once a day is enough for most advertisers.
  2. Re-pull a rolling window. Under ad_event_time, past days change as conversions arrive. Re-request at least the length of your click window each run and overwrite.
  3. Store raw JSON before transforming. If you change logic later, you can reprocess without re-requesting.
  4. Normalise to one table: date, campaign ID, spend, goal conversions, and one column per non-goal event count and value.
  5. Record the settings (windows, time basis) in the table or its metadata so nobody mixes series.
  6. Archive beyond 365 days if you need longer history than the API retains.
  7. Feed it into your BI tool or a measurement partner. Our measurement partners guide covers the third-party options.

Non-goal reports are only as good as the pixel and Conversions API events underneath them. Our ChatGPT Ads tracking setup installs and validates both, and a ChatGPT Ads audit uses this report to judge each campaign on the purchases it actually drove.

Why won't the numbers match Google Analytics or Shopify?

Because they measure different things. OpenAI attributes conversions to ChatGPT ad interactions using its own windows, including view-through; your analytics platform uses its own attribution model, often last-click, and may never see the ChatGPT click at all if parameters are stripped. Expect a gap, explain it, and track its trend rather than chasing an exact match.

What mistakes should you avoid?

For the bigger picture on what ChatGPT Ads measurement can and cannot tell you, start with how ChatGPT ads work and our news log for each new reporting capability as it ships.

Frequently asked questions

What is non-goal conversion reporting in ChatGPT Ads?

A capability of the public Insights API that returns attributed conversion events beyond a campaign's selected goal — for example, purchases on a campaign optimising for leads — without changing the conversion goal or optimisation settings.

Which endpoint returns non-goal conversions?

POST https://api.ads.openai.com/v1/conversions/insights, authenticated with a Bearer token, with include set to ["attributed_events"].

Does non-goal reporting change how my campaign optimises?

No. OpenAI states you can retrieve these events without changing the campaign's conversion goal or optimisation settings. It is reporting only.

What attribution windows can I use?

attribution_window_days accepts 7, 14 or 30 (default 30). view_through_attribution_window_days accepts 0 or 1 (default 1); 0 excludes view-through attribution.

What is attribution_time_basis?

It sets the date conversions are reported on: ad_event_time (default) dates them to the ad interaction, conversion_time to when the conversion happened. conversion_time has limited coverage of non-goal events.

How do I report only purchases?

Add event_names with the exact name of your purchase event. Only recognised events — configured in conversion event settings or present in your published received-event history — are returned.

Can I report custom events?

Yes. event_names accepts standard or custom event names by exact match, and each item in attributed_events includes an event_kind field.

Why am I getting HTTP 413?

The report exceeds 2,000 summary rows, 2,000 event rows, or 2,000 conversion-event-setting breakdown entries for one event. Split the request by campaign or date, use time_granularity: "none", or filter events.

What format do time_ranges use?

Each item is a JSON-encoded string describing a unix_range with string start and end Unix timestamps in seconds. Note it is a string containing JSON, not a nested object.

How do I calculate ROAS for a campaign optimising for checkouts?

Pull spend from the entity insights endpoints and attributed purchase value from /v1/conversions/insights for the same period and settings, then divide value by spend. Check value count and currency first.

What does attributed_event_value_count mean?

How many of the attributed events carried a value. If it is lower than attributed_event_count, some events arrived without values and revenue is understated.

Why don't the numbers match my analytics?

Different attribution models, windows, view-through credit and time basis. Compare against a click-only series and track the gap's trend rather than expecting an exact match.

How long is ChatGPT Ads reporting data retained?

OpenAI's reporting docs state delivery data is retained for 365 days at non-hourly granularity. Store results yourself if you need longer history.

Do I need the API, or is this in the Ads Manager interface?

OpenAI announced non-goal conversion reporting through the public Insights API. Plan on using the API for it.

Sources and further reading

Want purchases and ROAS on every campaign?

30 minutes with Tarun. We will review your event setup and sketch the Insights API reporting that gets true ROAS onto every campaign, whatever it optimises for.

Book a discovery call
Tarun Kapoor, founder of Context Hints, seated at a wooden desk with a soft city light behind him.
Tarun Kapoor
Founder & CEO, Context Hints

Twelve years of media buying across GroupM, WPP, Ogilvy & Mather, and Neil Patel Digital. Has personally owned media for Nestlé, Sage, Qualcomm, Aetna, Weight Watchers, Chubb and Novotel.