Catalog Setup

The release of Facebook Graph API, v2.12 is scheduled for January 30, 2018 and does not contain any versioned breaking changes for Facebook Marketing APIs, except for the following scenario:

If you're using Product Catalog as part of your application, you may be affected by a couple of security-related breaking changes. Technically, these are not Marketing API endpoints. However, these are used by some marketing applications, and hence can be considered breaking changes for such applications. Read further below for details.

  • Marketing API, v2.11 will continue to be the latest version and it will not enter deprecation mode on January 30, 2018.
  • Marketing API, v2.10 will continue to be in deprecated state, as it is currently, and will end of life on May 8, 2018.
  • After Graph API v2.12 is released, any calls made to Marketing APIs with the version set as 2.12, will be treated as v2.11 calls.
  • Marketing API, v2.11 and v2.12 will be deprecated and end of life at the same time, at a later date.

As of May 8, 2018, we'll limit permissions to catalogs managed under the same Business Manager account to only users who have explicitly been assigned the ADMIN or ADVERTISER role on that catalog owned by a business, as follows:

  • Only users with the catalog ADMIN role can create and edit the catalog. Business Admins only have read access. This change applies to calling POST {product-catalog-id}.
  • Only users with the catalog ADVERTISER role can't edit the catalog, but have read and write access to catalogs managed under the same Business Manager account.
  • Only users with catalog ADMIN or ADVERTISER role can read the catalog.

For more details, see Implications of Graph API 2.12 Release and Facebook Graph API, v2.12.

To set up Dynamic Ads, you need a catalog, catalog feeds and product sets.

Your catalog is a structured data file with a list of items that you would like to advertise. Each line contains all information needed to create a Dynamic Ad. Product feeds are dynamic uploads of your data to keep your product catalog up to date.

To set up a catalog, follow these steps:

See also Getting Started with Dynamic Ads and Dynamic Ads Setup via UI.

Step 1: Create a Catalog

To create a catalog for Dynamic Ads:

curl -X POST \
  -F "name=Test+Catalog" \
  -F "access_tokens={ACCESS_TOKEN}" \{business-id}/product_catalogs
const adsSdk = require('facebook-nodejs-ads-sdk');
const Business = adsSdk.Business;
const ProductCatalog = adsSdk.ProductCatalog;

let access_token = '<ACCESS_TOKEN>';
let app_secret = '<APP_SECRET>';
let app_id = '<APP_ID>';
let id = '<ID>';
const api = adsSdk.FacebookAdsApi.init(access_token);
const showDebugingInfo = true; // Setting this to true shows more debugging info.
if (showDebugingInfo) {

const fields = [
const params = {
  'name' : 'Test Catalog',
(new Business(id)).createProductCatalog(
.then((result) => {
  product_catalogs_id =;
.catch((error) => {
require __DIR__ . '/vendor/autoload.php';

use FacebookAds\Object\Business;
use FacebookAds\Object\ProductCatalog;
use FacebookAds\Api;
use FacebookAds\Logger\CurlLogger;

$access_token = '<ACCESS_TOKEN>';
$app_secret = '<APP_SECRET>';
$app_id = '<APP_ID>';
$id = '<ID>';

$api = Api::init($app_id, $app_secret, $access_token);
$api->setLogger(new CurlLogger());

$fields = array(
$params = array(
  'name' => 'Test Catalog',
echo json_encode((new Business($id))->createProductCatalog(
)->getResponse()->getContent(), JSON_PRETTY_PRINT);
from import Business
from facebookads.adobjects.productcatalog import ProductCatalog
from facebookads.api import FacebookAdsApi

access_token = '<ACCESS_TOKEN>'
app_secret = '<APP_SECRET>'
app_id = '<APP_ID>'
id = '<ID>'

fields = [
params = {
  'name': 'Test Catalog',
print Business(id).create_product_catalog(
import java.util.Arrays;

public class SAMPLE_CODE_EXAMPLE {
  public static void main (String args[]) throws APIException {

    String access_token = \"<ACCESS_TOKEN>\";
    String app_secret = \"<APP_SECRET>\";
    String app_id = \"<APP_ID>\";
    String id = \"<ID>\";
    APIContext context = new APIContext(access_token).enableDebug(true);

    new Business(id, context).createProductCatalog()
      .setName(\"Test Catalog\")
access_token = '<ACCESS_TOKEN>'
app_secret = '<APP_SECRET>'
app_id = '<APP_ID>'
id = '<ID>'

FacebookAds.configure do |config|
  config.access_token = access_token
  config.app_secret = app_secret

business = FacebookAds::Business.get(id)
    name: 'Test Catalog',

To use the Catalog Batch API, you need the appropriate Marketing API Access Level and must accept the Terms of Service by creating your first catalog through Business Manager. See Catalog Reference.

Step 2: Set Up Feed

Feed is a set of items uploaded or fetched from a business so that your product catalog is current. A product item is a single item in your online store, such as a SKU. You can have a single product feed represent all products in your catalog; or multiple product feeds with each feed represents a single country or division's products. See Feed, Reference and Item, Reference.

After you create a product catalog, use catalog id to create and schedule a Product Feed:

use FacebookAds\Object\ProductFeed;
use FacebookAds\Object\Fields\ProductFeedFields;
use FacebookAds\Object\Fields\ProductFeedScheduleFields;

$product_feed = new ProductFeed(null, <PRODUCT_CATALOG_ID>);

  ProductFeedFields::NAME => 'Test Feed',
  ProductFeedFields::SCHEDULE => array(
    ProductFeedScheduleFields::INTERVAL => 'DAILY',
    ProductFeedScheduleFields::URL =>'',
    ProductFeedScheduleFields::HOUR => 22,

from facebookads.adobjects.productfeed import ProductFeed

product_feed = ProductFeed(parent_id=<PRODUCT_CATALOG_ID>)

product_feed[] = 'Test Feed'
product_feed[ProductFeed.Field.schedule] = {
    'interval': 'DAILY',
    'url': '',
    'hour': 22,

ProductFeed productFeed = new ProductCatalog(<PRODUCT_CATALOG_ID>, context).createProductFeed()
  .setName("Test Feed")
String product_feed_id = productFeed.getId();
curl \
  -F 'name=Test Feed' \
  -F 'schedule={ 
    "interval": "DAILY", 
    "url": "http:\/\/\/sample_feed.tsv", 
    "hour": 22 
  }' \
  -F 'access_token=<ACCESS_TOKEN>' \<PRODUCT_CATALOG_ID>/product_feeds

Supported Formats

Provide the product feed in one of these formats:

Feed Format Description Sample Feed


Comma-separated value. The first row is the column header. Enclose fields containing commas in "double quotes"

Download (Right-Click and Save Link As)


Tab-separated values. The first row is the column header. Enclose fields containing commas in "double quotes"

Download (Right-Click and Save Link As)


Format typically generated by automated feed provider systems or web servers. A set of item XML nodes represents a product list and must begin with the <?xml declaration tag.

Download (Right-Click and Save Link As)


Format typically generated by automated feed provider systems or web servers. A set of item XML nodes represents a product list and must begin with the <?xml declaration tag.

Download (Right-Click and Save Link As)

Required Fields

Provide all column names in English.

Name Type Description


Max size: 100


Unique ID for item. Can be a variant for a product. If there are multiple instances of the same ID, we ignore all instances. This maps to retailer_id after the product is imported.



If item in stock. Accepted values are:

in stock - Item ships immediately.

out of stock - No plan to restock.

preorder- Available in future.

available for order - Ships in 1-2 weeks.

discontinued - Discontinued



Product condition: new, refurbished, or used


Max size: 5000


Short text describing product.



Link to item image used in the ad. Carousel format and Instagram uses a square 1:1 aspect ratio images (600x600px) while single product ad uses 1.91:1 aspect ratio image (1200x630px). Provide proper images for your use.



Link to merchant's site where someone can buy the item.


Max size: 100


Title of item.



Cost of item and currency. Currency should follow ISO 4217 currency codes such as 9.99 USD

gtin, mpn, or brand

Max size: 70


gtin - Global Trade Item Number (GTINs) can include UPC, EAN, JAN, and ISBN.

mpn - Unique manufacturer ID for product.

brand - Name of the brand.

Either gtin, mpn, or brand required.

Optional Fields, Product Deep Links

Provide deep links in Product Feed following the App Links specification. Deep link information in Product Feed takes precedence over any information Facebook collects with App Links metadata with our web crawler.

If you already have deep link information from App Links, you do not need to specify this data. Facebook uses information from App Links to display the correct deep link. To display deep links in your ads see Dynamic Ads, Ad Template.

Name Description Example


Custom scheme for iOS app as URL



App ID for App Store



Name of app to display

Electronic Example iOS


Custom scheme for iPhone app as URL



App ID for App Store



Name of app to display

Electronic Example iPhone


Custom scheme for iPhone app



App ID for App Store



Name of app to display

Electronic Example iPad


Custom scheme for Android app as URL



Fully-qualified package name for intent generation



Name of app for display

Electronic Example Android


Custom scheme for Windows Phone app as URL



App ID, as a GUID, for app store



Name of app for display

Electronic Example Windows

For iOS, only provide iPhone or iPad app information if they are different from the general iOS app.

Use product group to group all product variants. Provide product group to identify products that are almost identical but have variations such as color, material, size or pattern. Groups make it easier to advertise additional colors, styles, or patterns for a particular product. All products in a product group share the same item_group_id. In Dynamic Ads, we pick only one item out of the group based on the signal we received from the pixel or app.

These are optional fields you can include:

Name Type Max Size


Max size: 2000


You can include up to 10 additional images; provide them as comma-separated URLs.



Age group for product. Accepted values are newborn, infant, toddler, kids, and adult.


Max size: 100


Item color.



Product expiration. If the product is expired, Facebook excludes it from all product sets and does not display it in ads.



Options include: male, female, and unisex



For items that are variants of a product. Provide the same item_group_id for all items that are variants. For example, Red Polo Shirt is a variant of Polo Shirt. Facebook maps this to retailer_product_group_id once we get your feed. In Dynamic Ads, we pick only one item out of the group based on the signal we received from the pixel or app.


Max size: 250


Predefined values (string or category ID) from Google's product taxonomy. For example, Apparel & Accessories > Clothing > Dresses or 2271


Max size: 200


Material product is made of such as leather, denim, or cotton.


Max size: 100


Pattern or graphic print on a product.


Max size: 750


Retailer-defined category for product.

e.g. in TSV
Home & Garden > Kitchen & Dining > Appliances > Refrigerators

e.g. in XML <product_type>Home & Garden > Kitchen & Dining > Appliances > Refrigerators</product_type>



Discounted price if the item is on sale. Currency should be specified as the ISO 4217 currency code. Specified as 9.99 USD



Start and end date and time for the sale, separated by slash:




Blob with different prices for each country and region. Different regions are comma-separated. The format should be COUNTRY:STATE:SHIPPING_TYPE:PRICE.


US:CA:Ground:9.99 USD, US:NY:Air:15.99 USD



Shipping weight of item. We only accept these units of weight: lb, oz, g, kg. Example: 3 lbs



Size of item. For example, a shirt may be Small or XL.


Max size: 100


Optional, additional information about item.


Max size: 100


Optional, additional information about item.


Max size: 100


Optional, additional information about item.


Max size: 100


Optional, additional information about item.


Max size: 100


Optional, additional information about item.

Test your product feed through our product feed debug page. For CSV / TSV, copy the first row (column header row) and a few products; for XML, copy the XML with a few item / entry, paste the lines into the text area and validate.

Step 3: Update Options

To keep product information current, use one of the following:

  1. Scheduled Product Feed Fetches
  2. Direct Upload a Product Feed
  3. Update a Product

Scheduled Product Feed Fetches

Facebook fetches product feeds from your system on a schedule you define. There are two types of schedule you can define - update_schedule and schedule. The uploads created via update_schedule would either create new items or update existing ones with the information provided in the feed file. The uploads created via schedule would result in a complete refresh operation on your feed - we delete products not present in the file, update existing ones, and create new ones. You can use either of the schedules or both depending on your needs.

e.g: update_schedule with frequency HOURLY and a replace schedule with frequency DAILY.

We recommend setting up an update_schedule with only changed data in the feed file for faster processing of feed. This is especially better for holiday sales and faster price and availability updates. It's also recommended to mark product items as "out of stock" rather than deleting from the feed so Facebook can re-target the user with similar available products.

curl \
  -F 'name=Test Feed' \
  -F 'schedule={ 
    "interval": "DAILY", 
    "url": "http:\/\/\/sample_feed.tsv"
  }' \
  -F 'update_schedule={ 
    "interval": "HOURLY", 
    "url": "http:\/\/\/sample_feed_updates.tsv",
    "hour": 22
  }' \
  -F 'access_token=<ACCESS_TOKEN>' \<PRODUCT_CATALOG_ID>/product_feeds

The response is:

{ "id" : {PRODUCT_FEED_ID} }

See Product Feed Reference, Product Feed Schedule Reference.

Direct Upload a Product Feed

Along with scheduled feed fetches, you can manually perform one-time uploads.

This example is for feed files which are hosted on a public location.

curl \
-F "url=" \
-F "access_token={ACCESS_TOKEN}" \{API_VERSION}/{PRODUCT_FEED_ID}/uploads

This example is for uploading feed files directly from the local machine. The path to the file needs to be changed according to your use case.

curl \
-F "file=@catalog.csv;type=text/csv" \
-F "access_token={ACCESS_TOKEN}" \{API_VERSION}/{PRODUCT_FEED_ID}/uploads

Optionally, you can set update_only to true. We create new items and update existing ones but do not delete items from the feed. You only need to provide id to update existing items. This reduces time to fetch and process your file.

For example, to update only price and custom labels for 100 items in a feed, use direct upload. Provide a file with only id, price and custom_label_0 for those items and update_only set to true. We supported all listed file formats; the most common ones are TSV and CSV.

Example files:

Feed Format Use-Case Sample Feed


Update price and availability for a subset of items.

Download (Right-Click and Save Link As)


Reset sale_price and update custom_label_0 for a subset of items

Download (Right-Click and Save Link As)

See Manual Uploads, Reference.

If you get errors in your Product Feed, see Product Feed Upload Errors, Reference.

Update Individual Product

Update an individual product's data in real time. Include the updated fields in an HTTP POST:{PRODUCT_CATALOG_ID}:{base64urlencode(retailer_id)}

Where retailer_id is the product ID from your product feed. It must be base64url-encoded. See mutable product fields in the Product Catalog Products, Reference.

Do not provide product feeds with individual product updates, creation, or deletion with the API. This can disrupt any updates or deletes of items you created with the API since we do not track these with the feed.

See also:

Batch Upload for Large Catalogs

Upload very large catalogs with millions of products and quickly-changing inventory. You can create, update and delete numerous products in a single HTTP request. The API has two endpoints:

  • POST [/{product_catalog_id}/batch](#send-batch-request) - Send a batch of requests to create, update, delete items in a catalog.
  • GET [/{product_catalog_id}/check_batch_request_status](#batch-request-status) - Check status of request.

Send Product Updates

To create, update or delete products in your catalog, make an HTTP POST with the changes you want to make. You can make up to 5000 updates in one call. For each catalog, you can make up to 100 calls per hour.

use FacebookAds\Api;
use FacebookAds\Http\RequestInterface;

$requests =  array(
        'method' => 'CREATE',
        'retailer_id' => 'retailer-product-id-123',
        'data' => array(
          'availability' => 'in stock',
          'brand' => 'Niky',
          'category' => 't-shirts',
          'currency' => 'USD',
          'description' => 'This is the product description.',
          'image_url' => '',
          'name' => 'My product name',
          'price' => '100',
          'url' => '',

$data = Api::instance()->call(
  array('requests' => $requests))->getContent();
curl \
  -F 'requests=[ 
      "method": "CREATE", 
      "retailer_id": "retailer-product-id-123", 
      "data": { 
        "availability": "in stock", 
        "brand": "Niky", 
        "category": "t-shirts", 
        "currency": "USD", 
        "description": "This is the product description.", 
        "image_url": "http:\/\/\/t-shirts\/1.png", 
        "name": "My product name", 
        "price": "100", 
        "url": "http:\/\/\/t-shirts\/1.html" 
  ]' \
  -F 'access_token=<ACCESS_TOKEN>' \<CATALOG_ID>/batch

This call returns a handle that you can use to check the status of the batch request. See Get Request Status:

  "handles": ["AczwaOW7j_EuQ5peV3kGq8X9qc7cDiv_kFrrHkdKuG7LkpkkqK5939wgdoduSQ45FGK5vKdVqOaSDJEun-fvbsR1kk8Rd53AZyD1WThSemo26I"]
Parameter Type Description



JSON object containing all requests.






Product id given by a retailer.


JSON object containing fields and values for the product. When method is CREATE, this must contain all required fields for a product. When method is UPDATE it can contain any fields. Facebook updates only the fields you provide.

The values supported in the data field you can use to CREATE and UPDATE items:

  • additional_image_urls
  • availability
  • age_group
  • applinks
  • brand
  • category
  • color
  • condition
  • currency
  • custom_label_0
  • custom_label_1
  • custom_label_2
  • custom_label_3
  • custom_label_4
  • description
  • gender
  • gtin
  • image_url
  • manufacturer_part_number
  • name
  • pattern
  • price
  • product_type
  • sale_price
  • sale_price_end_date
  • sale_price_start_date
  • shipping
  • size
  • url

You can use applinks for deep link information, which functions similarly to Product Deep Links. The format is the following:

"applinks" : {
  "ios": [{
    "app_name":"Electronic Example iOS"
  "iphone": [{
     "app_name":"Electronic Example iPhone"
  "ipad": [{
     "app_name":"Electronic Example iPad"
  "android": [{
     "app_name":"Electronic Example Android",
  "windows_phone": [{
     "app_name":"Electronic Example Windows"

See Product Catalog, Creating, Reference.

Get Request Status

To get the status of a batch request, use the handle returned from the call to {product_catalog_id}/batch:

curl -G \
-d 'handle=AczwaOW7j_EuQ5peV3kGq8X9qc7cDiv_kFrrHkdKuG7LkpkkqK5939wgdoduSQ45FGK5vKdVqOaSDJEun-fvbsR1kk8Rd53AZyD1WThSemo26I'
-d 'access_token={ACCESS_TOKEN}'{API_VERSION}/{PRODUCT_CATALOG_ID}/check_batch_request_status


  "data": [
      "handle": "AczwaOW7j_EuQ5peV3kGq8X9qc7cDiv_kFrrHkdKuG7LkpkkqK5939wgdoduSQ45FGK5vKdVqOaSDJEun-fvbsR1kk8Rd53AZyD1WThSemo26Q",
      "status": "finished",
      "errors_total_count": 1,
      "errors": [
          "line": 0,
          "id": "retailer-4",
          "message": "Invalid value: Value passed at position 0 (id=retailer-199) is invalid: \"You cannot create a EntProductItem without required field Availability\""

See Product Catalog, Reference, Check Batch Status.

Product Feed Rules

Fix and prevent ongoing feed upload errors with rules. You can provide rules that Facebook applies to each feed upload. Specify your rules by the attribute (column) they should apply to, by the type of rule, and by parameters. You currently cannot use rules with Batch API. You can provide these types of rules:

  • Mapping Rule - Maps attributes (column names) in a feed file to attributes we can recognize.
  • Value Mapping Rule - Maps fields (column values) in a feed file to fields we can recognize.
  • Letter Case Rule - Change case of words in a field. For example, change all uppercase descriptions to lower case.

For example, you can fix these issues with Mapping and Value Mapping Rules:

  • Attribute typos from gavailability to availability
  • Fix unrecognized enums InStock to in stock
  • Price format from 45$ to 45.00 USD
  • Translate Condition: Neu under Condition: New

You can use Letter Case Rules to address these types of issues:

  • Change descriptions in all caps BRAND NEW WITH LEATHER DETAIL... to Brand new with leather detail...
  • Fix titles in all caps FACEBOOK T-SHIRT to Facebook T-shirt

Suggested Rules

You can get suggested rules from Facebook to fix errors in your feed. To see suggested rules for your upload session, follow next steps.

  • Retrieve upload sessions:{API_VERSION}/{PRODUCT_FEED_ID}/uploads
  • Retrieve errors for upload session:{API_VERSION}/{UPLOAD_SESSION_ID}/errors
  • Retrieve suggested rules for upload error:
curl -i -X GET 

An example response with a suggestion looks like this:

"data": [
    "attribute": "description",
    "type": "letter_case_rule",
    "params": [
        "key": "type",
        "value": "capitalize_first"

For details Suggested Rules API, Reference.


Adding Rules to Feeds

To apply rules to a feed, you need to associate the rule to the feed. Make an HTTP POST call to:{API_VERSION}/{PRODUCT_FEED_ID}/rules?attribute={ATTRIBUTE}&amp;rule_type={RULE_TYPE}&amp;params={PARAMS}

For example:

curl -i -X POST 
 -d "attribute=google_product_category" 
 -d "rule_type=mapping_rule" 
 -d "params=%7B'map_from'%3A%20'gcategory'%7D" 
 -d "access_token={ACCESS_TOKEN}" 
 // sample response
  "id": "{RULE_ID}"

You should format params as follows:

Rule Type Format Example Notes

Mapping Rule

"map_from": <string>

"map_from": "gavailability"

Value Mapping Rule

<string> : <string>

"InStock": "in stock"

For value mapping rule number of mappings is limited to 10 and length of strings to 20.

Letter Case Rule

"type": one of : "capitalize_first", "capitalize_all", "to_upper", "to_lower"

"type": "capitalize_first"

For details, see Product Feed Rules API, Reference.

Get Current Rules

To list all rules associated with a feed, make a HTTP GET call to:{API_VERSION}/{PRODUCT_FEED_ID}/rules

For details, see Product Feed Rules API, Reference.

Updating and Deleting Rules

To change a rule associated with a feed, make an HTTP POST call to update any parameters and HTTP DELETE to delete it. You can only update parameters. If you want to change attribute or rule_type, you must delete and re-create the rule.{API_VERSION}/{PRODUCT_FEED_RULE_ID}?params={PARAMS}

For details, See Product Feed Rule API, Reference

Next: Collect audience Signals and Build Product Audience

Build Product Audiences