
2Performant feed for Shopify
2Performant, the Romanian affiliate network whose platform is now branded Business League, lets publishers promote your products for a commission, and the product supply is one CSV file you host at a URL they fetch three to four times a day. Feedflock turns your Shopify catalog into exactly that file: a header row of 2Performant's own field labels so the mapping step is a no-op, prices as bare numbers, availability in their six-value vocabulary, regenerated on your schedule, as often as every hour.

Old price: only when the discount is real.
2Performant's Sale price is simply the price you charge: mandatory, a bare dot-decimal number, read in the program's currency. Old price is the pre-discount reference, and it stays empty when there is no discount: an always-filled old price invents a permanent markdown that every affiliate repeats. Feedflock maps Old price from your compare-at price, so the pair tells the truth in both directions.
Catch feed issues before 2Performant does.
Before every generation Feedflock checks that every field the channel requires is filled, and, on templates verified against the channel's own spec, that the values fit its rules. Most problems are fixed with one click, without editing products in Shopify.
Setup
Live in five steps
From a bare Shopify store to a listed offer: the whole setup fits into one coffee break.
Open an advertiser program
Register your program on 2Performant. The platform is branded Business League. The program and its commissions are what affiliates sign up to. A feed is not mandatory to launch, but affiliates running price-comparison and aggregator sites rely on it.
Install Feedflock
Add Feedflock from the Shopify App Store. It reads your products, variants, stock and images directly through the Shopify API.
Pick the 2Performant template
One row per variant, with a header row of their own field labels, identical to their sample CSV. The numeric Shopify variant ID goes out as Product ID, availability as 1/0, and Old price from your compare-at price, empty when there is no discount.
Decide what the spec leaves open
Category is your own tree. No 2Performant taxonomy is mandated. Description is plain text by default (their whitelist of simple HTML tags is one mapping away), availability can send the worded states instead of 1/0, and Brand, GTIN and up to four custom fields are ready when you need them.
Paste the feed URL
In your advertiser account: Tools → Product Feeds → New Feed, and paste the hosted URL. 2Performant fetches it 3-4 times a day (the schedule can be adjusted), and with the template's header the column mapping is just confirming each column. Already running a Google Merchant feed? That URL is accepted verbatim too.
https://feedflock.appfleece.com/f/demo-twoperformant/twoperformant.csv
The feed
What the channel receives
Title;Description;Sale price;Old price;Category;Brand;GTIN;Product URL;Images;Product ID;Availability "Linen shirt Sand M";"Breathable linen shirt with a relaxed regular fit.";259.00;;Men's shirts;Nordlin;8594000123453;https://shop.example.ro/products/linen-shirt-sand?variant=46012345678901;"https://cdn.shop.example.ro/img/linen-shirt-sand.jpg,https://cdn.shop.example.ro/img/linen-shirt-sand-back.jpg";46012345678901;1

Nordlin
Linen shirt Sand
259 lei
Feed fields
Title
Linen shirt Sand M
Description
Breathable linen shirt with a relaxed regular fit.
Sale price
259.00
Category
Men's shirts
Brand
Nordlin
GTIN
8594000123453
Product URL
https://shop.example.ro/products/linen-shirt-sand?variant=46012345678901
Product ID
46012345678901
Availability
1
The channel
The region's affiliate network
2Performant was founded in Romania and absorbed Profitshare's Romanian and Bulgarian business in 2025; the Business League leaderboard already lists RO, BG, HU, IE and IT as selling countries. One feed serves affiliates across the whole region.
Your Google feed is already accepted
In their own words: if you already created a feed for Google Merchant, you can use that same feed in their platform. Start in minutes, and switch to the native field set when you want Old price and the six-value availability.
Plain URLs, their tracking
The Product URL stays the plain product page. 2Performant builds the affiliate redirect on its side. No UTM parameters, no tracking glue in your feed, nothing to maintain when campaigns change.
The feed
- A header row of 2Performant's own field labels, identical to their sample CSV, so the column mapping in their UI is just confirming each column
- Product ID from Shopify's numeric variant ID; a gid:// URI or a text SKU would violate the spec's "must be a number"
- Sale price as a bare dot-decimal number with no thousands separator; no currency column exists, so the number is read in the program's currency
- Old price mapped from the compare-at price and left empty when the product is not on sale, because an always-filled reference price invents a permanent discount
- Availability as 1/0 by default, with the worded states (In Stock, Backorder, Out Of Stock, Preorder) one mapping away
- The spec's validations checked at generation (Title ≤ 255, numeric prices and Product ID, the availability enum, custom fields ≤ 254 characters), reported with the affected products, never silently rewritten
- One row per variant, with titles that pair product and variant so per-variant rows never collide
- Fetch tracking shows when 2Performant last downloaded the feed and alerts you if the fetches stop
Deep dive
A URL they fetch three to four times a day
- The feed lives at a
URLyou share; 2Performant fetches it 3-4 times a day and the schedule can be adjusted - A one-off
CSVfile upload (≤ 10 MB) is the fallback - The merchant's side of the contract: the file must update automatically whenever a change was made
- A Google Merchant feed is accepted verbatim, the sibling route in
Technical details
2Performant's own words: the CSV is added through a link to the file. You share a URL and they fetch it three to four times a day, with the schedule adjustable on request. The one-off file upload (their legacy guide caps it at 10 MB) is the fallback, not the norm. And the freshness contract is stated from the merchant's side: the feed must be found at a URL and updated automatically whenever a change was made. That is exactly Feedflock's hosted-URL model.
The cadence cuts both ways: price and stock changes reach affiliates within hours, but a broken URL means stale data until the next fetch succeeds. Feedflock hosts the file on a stable URL, regenerates it as often as every hour and tracks the fetches, alerting you if they stop. And if you already run a Google Merchant feed, 2Performant accepts that URL verbatim; this template exists for the merchant who wants 2Performant's own field set instead.
One CSV, their labels
- One product per line; separator comma, semicolon, tab or pipe; content delimiter double quote, single quote or backtick;
UTF-8 - The header row uses their field labels, so the mapping step in their UI becomes a no-op
- Embedded quotes are doubled, Enter is the row separator, and stray blank spaces can fail the whole upload
RSSand AtomXMLare supported too, with all tags present even when empty
Technical details
The spec's file rules, quoted: one product per line; the content delimiter is a double quote, a single quote or a backtick; the field separator a comma, semicolon, tab or pipe; UTF-8. Your feed can carry as much information as you need, mapped to their required and optional fields in their UI. That is why the template's header row uses their field labels, identical to their own sample CSV: the mapping step is just confirming each column.
The legacy blueprint adds the strictness worth knowing: embedded quotes must be doubled, Enter is the row separator, and blank spaces before rows or other small errors can make the whole upload fail. Feedflock's exporter quotes and doubles exactly as prescribed, so a quote inside a description never breaks a row, and a broken row never silently breaks the file. XML is the alternative: RSS and Atom are both supported, with all tags recommended present even when empty.
The mandatory eight
- Title (≤ 255 characters), Description (text plus a whitelist of simple
HTMLtags), Category (your own tree; none is mandated) - Sale price: a number, dot decimal, no thousands separator, and no currency column anywhere in the feed
- Product
URLstays plain (they build the redirect), Product ID must be a number, Images is one comma-joined cell - Availability: 0, 1, In Stock, Backorder, Out Of Stock, Preorder; sold-out rows stay in the feed, as 0
Technical details
Eight fields are mandatory, with validations quoted straight from the spec page. Title is capped at 255 characters; Description takes text and simple HTML from a whitelist (b, li, ul, ol, dl, dd, i, u, br); Category is a tree with no mandated taxonomy, just your shop's own path. The template's defaults are the honest ones: the title pairs product and variant so per-variant rows never collide, and the description is stripped to plain text.
Three details deserve care. Sale price is a bare number (dot decimal, no thousands separator), and no currency column exists anywhere in their field set: the number is read in the program's currency, so the feed never states one. Product ID must be a number, which is why the default is Shopify's numeric variant ID (a gid:// URI would violate the rule; a SKU works only when it is numeric). And Availability has a six-value vocabulary (0, 1, In Stock, Backorder, Out Of Stock, Preorder), with sold-out rows staying in the feed as 0 rather than disappearing.
Old price, GTIN and the custom slots
- Old price: the price before discount, same number rules, empty when there is none
- Brand and
GTINare optional; the statedGTINlength rule is self-contradictory, so it is quoted but not enforced - Other data takes
JSONorYAML; up to four custom fields, ≤ 254 characters each - No delivery fields at all: shipping is not part of the 2Performant feed
Technical details
Beyond the mandatory eight, Old price carries the pre-discount reference under the same number rules. The template maps it from your compare-at price and leaves it empty when the product is not on sale, because an always-filled old price invents a permanent discount. Brand and GTIN round out identification. One spec oddity, recorded honestly: GTIN's stated validation (greater than 8, less than 14 characters) would reject a legitimate 14-digit GTIN, so the rule is quoted in the template but deliberately not enforced.
For everything else there is Other data (JSON or YAML) and up to four custom fields of at most 254 characters each. What the field set does not contain is just as notable: no carrier, no shipping cost, no COD element. Delivery is not part of the 2Performant feed at all, and neither is a currency column. The feed describes the products; the program describes the commercial terms.
The takeaway
One URL, fetched three to four times a day, and a CSV whose header row already speaks 2Performant's own field labels: bare-number prices, a numeric Product ID, availability in their six values. Your Shopify catalog stays the single source of truth for every affiliate in the network.
Claude · ChatGPT
Or set up your 2Performant feed in chat
Connect Feedflock to Claude or ChatGPT and ask. It creates the feed as a draft, maps your categories to 2Performant's own tree and tells you what is still missing. You approve every change.
Create a 2Performant feed for my store and map my categories.
I'll create it as a draft and show you each change before I make it.
FAQ
Get on every marketplace that matters this afternoon.
Install free, connect your first feed in minutes, and let Feedflock keep it fresh and validated.