# Google Merchant to OpenAI Ads CSV converter (`kondasviktor/openai-ads-feed-converter`) Actor

Convert Google Merchant XML/CSV/TSV/JSON into OpenAI Ads CSV with row validation and a US/CA/MX market gate. Independent tool, not OpenAI for teams.

- **URL**: https://apify.com/kondasviktor/openai-ads-feed-converter.md
- **Developed by:** [Viktor Kondas](https://apify.com/kondasviktor) (community)
- **Categories:** E-commerce, AI, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.50 / 1,000 processed product rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## OpenAI Ads Feed Converter — Merchant → Canonical CSV

Convert **Google Merchant** XML / CSV / TSV / JSON catalogs into **OpenAI Ads** canonical CSV (`openai-ads-2026-09-09`) with row-level validation.

**Independent tool — not affiliated with OpenAI.** Does not invent prices, brands, GTINs, images, or availability dates. Does not upload to Ads Manager / SFTP in v1 (download the CSV and connect in Ads Manager).

**Store:** [apify.com/kondasviktor/openai-ads-feed-converter](https://apify.com/kondasviktor/openai-ads-feed-converter)

### When to use

- Agencies converting many Merchant feeds for ChatGPT / OpenAI product ads
- Non-Shopify merchants with a public Google Merchant XML/CSV
- Catching invalid rows before Ads Manager rejects the catalog

### Pricing (PPE)

| Event | When | Price |
| --- | --- | --- |
| Actor start | Platform default | Platform default |
| `processed-product` | Each parsed product/variant row (valid or invalid) | **$0.0005** |

Prefer **PPE only** (not + usage). Paid Apify plans (Bronze / Silver / Gold) can get lower PPE rates — see the Pricing table on the Actor page.

### Input

| Field | Notes |
| --- | --- |
| `feedUrl` | Public Merchant feed URL (or use `feedText`) |
| `feedText` | Inline sample for small tests |
| `sellerName` | Required — maps to `seller_name` |
| `targetCountries` | Default `["US"]`. Verified: US/CA/MX. Others → `not_yet_verified` |
| `formatHint` | `auto` / `xml` / `csv` / `tsv` / `json` |
| `excludeInvalidRows` | Default true — invalids only in `invalid-products.csv` |
| `maxProducts` | Cap (QA prefill: 50) |

### Output

- **Dataset:** run `summary` + up to 50 `invalid_sample` rows
- **Key-value store:**
  - `openai-products.csv` — canonical OpenAI Ads CSV
  - `invalid-products.csv` — failed rows + error columns
  - `validation-report.json` — totals / sample issues
  - `mapping-summary.json` — format + **market gate**

### Market honesty

Official product-feed markets verified in this pin: **US, CA, MX**. Hungary (`HU` / `HUF`) and other codes are marked **`not_yet_verified`** — never claimed ready.

### Examples

See the Actor **Examples** tab for Merchant XML/CSV/TSV/JSON and invalid-row samples.

### FAQ

**Does this upload to OpenAI Ads Manager?**\
No. v1 downloads canonical CSV (`openai-products.csv`). You connect the file in Ads Manager / SFTP yourself.

**What formats are supported?**\
Google Merchant **XML** (RSS/Atom + `g:`), **CSV**, **TSV**, and **JSON** (including Shopify `products.json`). Homepages and sitemaps are rejected.

**Which countries are verified?**\
Product-feed markets in this schema pin: **US, CA, MX**. Other codes are marked `not_yet_verified` — never claimed ready.

**What happens to invalid rows?**\
With `excludeInvalidRows` (default), they are omitted from `openai-products.csv` and listed in `invalid-products.csv` with validation errors.

**ChatGPT ads product feed CSV — is this the right tool?**\
Yes, if you already have a Merchant-style catalog and need OpenAI Ads canonical CSV. Pair with the [Readiness Checker](https://apify.com/kondasviktor/openai-ads-readiness-checker) for AdsBot / HTTPS first.

### Related

- [OpenAI Ads Readiness Checker](https://apify.com/kondasviktor/openai-ads-readiness-checker) — AdsBot / HTTPS / landing checks before you upload
- [Product Catalog Scraper](https://apify.com/kondasviktor/product-catalog-scraper) — Build a catalog file when you do not already have a Merchant feed
- [Website Change Monitor](https://apify.com/kondasviktor/website-change-monitor) — Watch product URLs after the feed goes live

[All Actors](https://apify.com/kondasviktor)

### Legal

Respect each site's terms. You are responsible for feed rights and Ads Manager compliance. Not an official OpenAI validator.

# Actor input Schema

## `feedUrl` (type: `string`):

Public Google Merchant XML/CSV/TSV/JSON URL. Prefer HTTPS. Leave empty and use feedText for small inline samples (Store QA uses feedText).

## `feedText` (type: `string`):

Paste a small feed sample when you do not have a public URL. Ignored if feedUrl is set. Prefill is a 2-item Merchant XML for Store daily QA.

## `sellerName` (type: `string`):

Seller supplying the offer (OpenAI seller\_name). Required.

## `targetCountries` (type: `array`):

ISO 3166-1 alpha-2 codes. Verified product-feed markets: US, CA, MX. Others are marked not\_yet\_verified (never claimed ready).

## `formatHint` (type: `string`):

auto detects from content-type / body. Force when detection is ambiguous.

## `isAdsEligible` (type: `boolean`):

Default Ads eligibility when the source row does not set is\_ads\_eligible.

## `excludeInvalidRows` (type: `boolean`):

When true (default), only valid rows go into openai-products.csv. Invalids always appear in invalid-products.csv.

## `maxProducts` (type: `integer`):

Cap parsed products (Store QA prefill stays low so tests finish under 5 minutes).

## `schemaVersion` (type: `string`):

OpenAI Ads schema adapter version.

## `requestTimeoutSecs` (type: `integer`):

HTTP timeout when downloading feedUrl.

## Actor input object example

```json
{
  "feedText": "<?xml version=\"1.0\"?><rss xmlns:g=\"http://base.google.com/ns/1.0\"><channel><item><g:id>SMOKE-1</g:id><g:title>Smoke Test Shoe</g:title><g:description>A comfortable smoke-test shoe.</g:description><g:link>https://example.com/products/smoke-shoe</g:link><g:image_link>https://example.com/images/smoke-shoe.jpg</g:image_link><g:brand>ExampleBrand</g:brand><g:price>49.99 USD</g:price><g:availability>in_stock</g:availability></item><item><g:id>SMOKE-BAD</g:id><g:title>Broken</g:title><g:description>Missing link</g:description><g:image_link>https://example.com/x.jpg</g:image_link><g:brand>ExampleBrand</g:brand><g:price>1.00 USD</g:price><g:availability>in_stock</g:availability></item></channel></rss>",
  "sellerName": "Example Store",
  "targetCountries": [
    "US"
  ],
  "formatHint": "auto",
  "isAdsEligible": true,
  "excludeInvalidRows": true,
  "maxProducts": 50,
  "schemaVersion": "openai-ads-2026-09-09",
  "requestTimeoutSecs": 60
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `openaiProductsCsv` (type: `string`):

No description

## `invalidProductsCsv` (type: `string`):

No description

## `validationReport` (type: `string`):

No description

## `mappingSummary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "feedText": "<?xml version=\"1.0\"?><rss xmlns:g=\"http://base.google.com/ns/1.0\"><channel><item><g:id>SMOKE-1</g:id><g:title>Smoke Test Shoe</g:title><g:description>A comfortable smoke-test shoe.</g:description><g:link>https://example.com/products/smoke-shoe</g:link><g:image_link>https://example.com/images/smoke-shoe.jpg</g:image_link><g:brand>ExampleBrand</g:brand><g:price>49.99 USD</g:price><g:availability>in_stock</g:availability></item><item><g:id>SMOKE-BAD</g:id><g:title>Broken</g:title><g:description>Missing link</g:description><g:image_link>https://example.com/x.jpg</g:image_link><g:brand>ExampleBrand</g:brand><g:price>1.00 USD</g:price><g:availability>in_stock</g:availability></item></channel></rss>",
    "sellerName": "Example Store",
    "targetCountries": [
        "US"
    ],
    "formatHint": "auto",
    "isAdsEligible": true,
    "excludeInvalidRows": true,
    "maxProducts": 50,
    "schemaVersion": "openai-ads-2026-09-09"
};

// Run the Actor and wait for it to finish
const run = await client.actor("kondasviktor/openai-ads-feed-converter").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "feedText": "<?xml version=\"1.0\"?><rss xmlns:g=\"http://base.google.com/ns/1.0\"><channel><item><g:id>SMOKE-1</g:id><g:title>Smoke Test Shoe</g:title><g:description>A comfortable smoke-test shoe.</g:description><g:link>https://example.com/products/smoke-shoe</g:link><g:image_link>https://example.com/images/smoke-shoe.jpg</g:image_link><g:brand>ExampleBrand</g:brand><g:price>49.99 USD</g:price><g:availability>in_stock</g:availability></item><item><g:id>SMOKE-BAD</g:id><g:title>Broken</g:title><g:description>Missing link</g:description><g:image_link>https://example.com/x.jpg</g:image_link><g:brand>ExampleBrand</g:brand><g:price>1.00 USD</g:price><g:availability>in_stock</g:availability></item></channel></rss>",
    "sellerName": "Example Store",
    "targetCountries": ["US"],
    "formatHint": "auto",
    "isAdsEligible": True,
    "excludeInvalidRows": True,
    "maxProducts": 50,
    "schemaVersion": "openai-ads-2026-09-09",
}

# Run the Actor and wait for it to finish
run = client.actor("kondasviktor/openai-ads-feed-converter").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "feedText": "<?xml version=\\"1.0\\"?><rss xmlns:g=\\"http://base.google.com/ns/1.0\\"><channel><item><g:id>SMOKE-1</g:id><g:title>Smoke Test Shoe</g:title><g:description>A comfortable smoke-test shoe.</g:description><g:link>https://example.com/products/smoke-shoe</g:link><g:image_link>https://example.com/images/smoke-shoe.jpg</g:image_link><g:brand>ExampleBrand</g:brand><g:price>49.99 USD</g:price><g:availability>in_stock</g:availability></item><item><g:id>SMOKE-BAD</g:id><g:title>Broken</g:title><g:description>Missing link</g:description><g:image_link>https://example.com/x.jpg</g:image_link><g:brand>ExampleBrand</g:brand><g:price>1.00 USD</g:price><g:availability>in_stock</g:availability></item></channel></rss>",
  "sellerName": "Example Store",
  "targetCountries": [
    "US"
  ],
  "formatHint": "auto",
  "isAdsEligible": true,
  "excludeInvalidRows": true,
  "maxProducts": 50,
  "schemaVersion": "openai-ads-2026-09-09"
}' |
apify call kondasviktor/openai-ads-feed-converter --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kondasviktor/openai-ads-feed-converter"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/QZFi169pYzZI6ExZM/builds/3Qwwk0aLoq4XhIrii/openapi.json
