This page is intended as a ‘Quick Start’ guide and overview of how CitrusAd can be integrated with your system. This will help to explain the initial integration steps and how to achieve them.
If you are used to an advertising strategy which uses content injection based off a simple tag on your website, our integration will seem quite foreign - however each of the steps to go live are not complex. The integration will be more involved than simply adding a tag to a page, but the results will be exponentially more valuable to both the retailer and the supplier; as well as being more scalable in the long term.
Create Catalog
Upload Product Data to CitrusAdd
Request Product Ads when loading a page
Display selected ads when loading a page
Create Banner Ad Content Standard
Request and Display Banner ads when loading page
Send impressions and clicks to CitrusAd for reporting
Send order data to CitrusAD for reporting
The first step to integrating CitrusAd is to create a catalog that you can upload your products to. This can be done with a simple one-time API call.
If you are wishing to segment your catalogs into different stores, territories, or countries, you may need to create multiple catalogs.
More information can be found here:
An example request for creating a catalog can be seen below:
POST $BASE_URL/v1/catalogs?teamId=44d25f70-b520-40de-8329-0781a9ebcdc8 HTTP/1.1accept: application/jsoncontent-type: application/jsonAuthorization: Basic 4ww25f70-b52s-40de-8f29-07b139b5cdc8{"catalogs": [{"teamId": "4ww25f70-b52s-40de-8f29-07b139b5cdc8","name": "Retailer A Catalog"}]}
curl -iX POST "$BASE_URL/v1/catalogs?teamId=44d25f70-b520-40de-8329-0781a9ebcdc8" \-H "accept: application/json" \-H "content-type: application/json" \-H "Authorization: 4ww25f70-b52s-40de-8f29-07b139b5cdc8" \-d \'{"catalogs": [{"teamId": "4ww25f70-b52s-40de-8f29-07b139b5cdc8","name": "Retailer Catalog"}]}'
To return product ads, CitrusAd needs to know what products are in stock. Regular product syncing enables CitrusAd to maintain track of all products in an integrator's catalog. Each product's prices and product codes, as well as stock levels and category information are needed to ensure ads remain relevant.
There are two different ways you can upload your catalog to us. Which way you choose is dependant on the existing capabilities and architecture of your system. CitrusAd recommend syncing data via file. It is easier to troubleshoot and resolve issues. You can view the pros and cons of each way on the Syncing Data page:
POST $BASE_URL/v1/catalog-products?teamId=e8158f9b-bbb9-49fb-93fe-3ad481ca8450 HTTP/1.1accept: application/jsoncontent-type: application/jsonAuthorization: Basic 4ww25f70-b52s-40de-8f29-07b139b5cdc8{"catalogProducts": [{"teamId": "e8158f9b-bbb9-49fb-93fe-3ad481ca8450","catalogId": "628dbe95-2ec9-4e07-881d-3e9f92ab2e0b","gtin": "23556578965543","inventory": 50,"price": "19.99","categoryHierarchy": ["Health&Beauty", "Cosmetics", "Foundation&Powders", "Foundation"],"groups": ["Cosmetics", "Foundations", "Covergirl", "Natural", "Lasting", "Dry Skin", "Beige"],"tags": ["Natural", "Lasting", "Dry Skin", "Beige"],"filters": ["imageurl:https://your.image.host.com/image.jpg","name:Covergirl Clean 120 Creamy Natural Liquid Foundation30mL","Brand:Covergirl","Category:11753","category:Health&Beauty","category:Grocery","Special_Flag:0"],"profit": "1.50"}]}
curl -iX POST "$BASE_URL/v1/catalog-products?teamId=e8158f9b-bbb9-49fb-93fe-3ad481ca8450" \-H "accept: application/json" \-H "content-type: application/json" \-H "Authorization: Basic 4ww25f70-b52s-40de-8f29-07b139b5cdc8" \-d \'{"catalogProducts": [{"teamId": "e8158f9b-bbb9-49fb-93fe-3ad481ca8450","catalogId": "628dbe95-2ec9-4e07-881d-3e9f92ab2e0b","gtin": "23556578965543","inventory": 50,"price": "19.99","categoryHierarchy": ["Health&Beauty", "Cosmetics", "Foundation&Powders", "Foundation"],"groups": ["Cosmetics", "Foundations", "Covergirl", "Natural", "Lasting", "Dry Skin", "Beige"],"tags": ["Natural", "Lasting", "Dry Skin", "Beige"],"filters": ["imageurl:https://your.image.host.com/image.jpg","name:Covergirl Clean 120 Creamy Natural Liquid Foundation30mL","Brand:Covergirl","Category:11753","category:Health&Beauty","category:Grocery","Special_Flag:0"],"profit": "1.50"}]}'
This option allows you to sync up your catalog to us via an API call. This means that your back end is pushing each product to us individually to store (although you can do these in batches and don’t actually have to upload each product one at a time).
If you are looking to upload via API, see:
The other option for uploading your catalog is to create a catalog file that we can download off your servers. For file catalogs, we support TSV (Tab Separated Values) and XML file formats. Once you have created the catalog file and given us access to download the file, we will store it on our servers and be able to reference it for ad generation.
product_code | inventory | category_hierachy | filter:category | filter:brand_name |
80591101 | 20 | ["department:spirits", "productName:Green Fairy Absinth Gift Pack 500mL", "varietal:absinthe", "webcountryoforigin:czech-republic"] | absinthe | green-fairy |
Example XML Document Snippet:
<rss><item><id>80591011</id><title>Melissa & Doug Dinosaur Stamp Set, 4yrs+</title><description>Imagine a rugged landscape littered with volcanoes, and full of dinosaurs roaming around</description><image_link>https://www.retailer.com/productImages/image1.jpg</image_link><price>£9.99</price><product_type>Food Cupboard</product_type><availability>10</availability></item><item><id>87086011</id><title>Waitrose Splits Strawberry Ice Lollies</title><description>Strawberry splits; Suitable for vegetarians. Strawberry splits vanilla flavoured ice cream with a fruity strawberry ice coating. Our fundamental belief is that few things in life are more important than the food you buy. Good quality is essential.</description><image_link>https://www.retailer.com/productImages/image2.jpg</image_link><price>£1.25</price><product_type>Frozen Ice Cream Ice Cream Lollies</product_type><availability>20</availability><brand>Waitrose</brand></item><rss>
If you are looking to upload via API, see:
There are many different places in which you can be requesting ads, including category pages, search term results pages, the homepage, specials pages etc. Below we will use a simple ‘search term result’ page context. Context is an important part of ad generation as it gives us valuable information about the customer and the page they are on.
This is an example request for an ad on a search term results page:
POST $BASE_URL/v1/ads/generate?teamId=44d25f70-b520-40de-8329-0781a9ebcdc8 HTTP/1.1accept: application/jsoncontent-type: application/jsonAuthorization: Basic 4ww25f70-b52s-40de-8f29-07b139b5cdc8{"customerId": "wertg5432a","sessionId": "ec9-4e07-881d-3e9","pageType": "Search","catalogId": "628dbe95-2ec9-4e07-881d-3e9f92ab2e0b","searchTerm": "Wine","productFilters": [["category:RedWine", "category:Shiraz"]],"maxNumberOfAds": 3}
curl -iX POST "$BASE_URL/v1/ads/generate?teamId=44d25f70-b520-40de-8329-0781a9ebcdc8" \-H "accept: application/json" \-H "content-type: application/json" \-H "Authorization: Basic 4ww25f70-b52s-40de-8f29-07b139b5cdc8" \-d \'{"customerId": "wertg5432a","sessionId": "ec9-4e07-881d-3e9","pageType": "Search","catalogId": "628dbe95-2ec9-4e07-881d-3e9f92ab2e0b","searchTerm": "Wine","productFilters": [["category:RedWine", "category:Shiraz"]],"maxNumberOfAds": 3}'
As you can see from the above request, only basic information is required for us to serve ads; although the more information you can give us in the context, the more targeted our relevancy algorithm can be in returning ads.
This is an example returned object from an ad request:
HTTP/2 200{"ads": [{"id": "display_ZFwfo0Mi2AhFBxUBHpXnICvV2j8zNTcxNzExUA==","gtin": "3571711P","discount": {"amount": 0,"minPrice": 0,"maxPerCustomer": 0},"expiry": "2019-12-10T01:51:07.936105529Z"},{"id": "display_VpFfnPOnaG4MZh43ckQjufmGAzwzNTcxOTkyUA==","gtin": "3571992P","discount": {"amount": 0,"minPrice": 0,"maxPerCustomer": 0},"expiry": "2019-12-10T01:51:07.936111787Z"},{"id": "display_vRHRnkTXbbssVwiem8jDrmOp2FM2Mzg3NTkyUA==","gtin": "6387592P","discount": {"amount": 0,"minPrice": 0,"maxPerCustomer": 0},"expiry": "2019-12-10T01:51:07.936117921Z"},],"banners": [],"products": []}
{"ads": [{"id": "display_ZFwfo0Mi2AhFBxUBHpXnICvV2j8zNTcxNzExUA==","gtin": "3571711P","discount": {"amount": 0,"minPrice": 0,"maxPerCustomer": 0},"expiry": "2019-12-10T01:51:07.936105529Z"},{"id": "display_VpFfnPOnaG4MZh43ckQjufmGAzwzNTcxOTkyUA==","gtin": "3571992P","discount": {"amount": 0,"minPrice": 0,"maxPerCustomer": 0},"expiry": "2019-12-10T01:51:07.936111787Z"},{"id": "display_vRHRnkTXbbssVwiem8jDrmOp2FM2Mzg3NTkyUA==","gtin": "6387592P","discount": {"amount": 0,"minPrice": 0,"maxPerCustomer": 0},"expiry": "2019-12-10T01:51:07.936117921Z"},],"banners": [],"products": []}
The discount
and products
fields are legacy and can be ignored
In the above response you can see that there is an ‘AdID” that we use for tracking, a ‘gtin’ which is the product code that you use in your catalog, and an expiry.
For more information, see:
As CitrusAd are only sending product information to your back end, you will have to merge our product ad IDs with the organic search results, and then display all of the content on the page. In general we recommend displaying the products that are returned from CitrusAd in priority over the organic search results - as this is what advertisers are used to and expect. Depending on how many ads are requested and how many are returned by CitrusAd, you might be displaying no sponsored products, or any number up to an entire page worth of sponsored listings. Generally on a page that has been targeted by advertisers; there will be some middle-ground where you request say ‘4’ ads and these are placed into the top row of the results based on the order that they are returned from Citrus. Here are some example product pages with sponsored ads displayed from CitrusAd:
For banner ads, you will need to specify to CitrusAd what spaces you have available for advertisers to target. Whether this is a header banner on a category page, or a double tile type banner on a product list page, we need to have dimensions and locations of all the banner slots that you wish to open up to advertisers. The way that we do this is by working with retailers to create a ‘Content Standard’. The Content Standard documents all the specific locations and sizes where banners can be displayed on your site and will be given to the suppliers so that they can create campaigns that target one or more of these locations on your site.
More information about Content Standards can be found here:
Similar to Product Ads, when you request a Banner Ad we require you to send a ‘context’ which will tell us what page the customer is on, what banner slots are available, what filters have been applied and any customer information (if available).
An example of a Banner Ad request can be seen below:
POST $BASE_URL/v1/ads/generate?teamId=44d25f70-b520-40de-8329-0781a9ebcdc8 HTTP/1.1accept: application/jsoncontent-type: application/jsonAuthorization: Basic 4ww25f70-b52s-40de-8f29-07b139b5cdc8{"customerId": "wertg5432a","sessionId": "ec9-4e07-881d-3e9","catalogId": "628dbe95-2ec9-4e07-881d-3e9f92ab2e0b","searchTerm": "Laptop","productFilters": [["Computers&Laptops"]],"pageType": "CATEGORY","maxNumberOfAds": 0,"contentStandardId": "contentStandardId1","bannerSlotIds": ["Category_Banner"]}
curl -iX POST "$BASE_URL/v1/ads/generate?teamId=44d25f70-b520-40de-8329-0781a9ebcdc8" \-H "accept: application/json" \-H "content-type: application/json" \-H "Authorization: Basic 4ww25f70-b52s-40de-8f29-07b139b5cdc8" \-d \'x{"customerId": "wertg5432a","sessionId": "ec9-4e07-881d-3e9","catalogId": "628dbe95-2ec9-4e07-881d-3e9f92ab2e0b","searchTerm": "Laptop","productFilters": [["Computers&Laptops"]],"categoryHierarchy": ["Search", "Technology", "Computers&Laptops"],"pageType": "CATEGORY","maxNumberOfAds": 0,"contentStandardId": "contentStandardId1","bannerSlotIds": ["Category_Banner"]}'
In the shown case, the important information is the PageType, the ContentStandardId, and the BannerSlotIds. These give us the basic context of what page the customer is on and what size banner to return for this request. An example response for that request can be seen below:
HTTP/2 200{"ads": [ ],"banners": [{"id": "display_GPZmwLMUH9n0_zfZTfn8UcmAShRlZmx","slotId": "Category_Banner","imageUrl": "https://assets.example.com/q/mdNYanp7zYVG6h4zYlSduXfadhNUctYG_9gsNlPHQ9t=","linkUrl": "https://www.retailer.com/p/product-471697300-652936600","altText": "An image of a brand xxx laptop with price $990 and shop now button.","expiry": "2002-10-02T15:00:00.05Z"}]}
{"ads": [ ],"banners": [{"id": "display_GPZmwLMUH9n0_zfZTfn8UcmAShRlZmx","slotId": "Category_Banner","imageUrl": "https://assets.example.com/q/mdNYanp7zYVG6h4zYlSduXfadhNUctYG_9gsNlPHQ9t=","linkUrl": "https://www.retailer.com/p/product-471697300-652936600","altText": "An image of a brand xxx laptop with price $990 and shop now button.","expiry": "2002-10-02T15:00:00.05Z"}]}
As you can see from the response, we only return an imgUrl and a linkUrl. This means that on your site you will need to insert that image into the page with the link attached. We also provide alternate text in the case that you are not be able to render the banner image. That completes a basic integration for a Banner Ad.
In more complex scenarios you can request multiple banners to display on a single page (header, product tile banner, footer) but the structure of the calls and responses will not change.
More information can be found here:
What happens if no banner ads are returned? This is a case that should definitely be considered, if a Banner Ad is not returned there should be an elegant fallback on the page which doesn’t leave a large blank space. Below is an example of a graceful fallback for a situation where no banner ads are returned or displayed.
An example of a Banner Ad correctly displayed:
An example of the Banner Ad not displayed:
One of the most critical parts of the integration is making sure that all impressions and clicks are recorded on your pages so that we can collate these into metrics for all parties. To do this we have created a simple to implement JavaScript Library that you install on your pages. Once that is complete, all clicks and impressions can be sent to CitrusAd for reporting purposes.
More information can be found at:
With regards to the reporting of sales, you will need to save our Ad ID against a product in your cart and send us that information in the ‘order sync’. The ‘order sync’ is a list of all of your orders that you send to us, some products will have Ad IDs, and some will not. We will attribute sales to orders which have Ad IDs for conversion and ROAS reporting; and we will be able to use the other order data to improve our relevancy algorithms for future targeting.
The order sync can be done either via API or File Upload similar to the Catalog Upload.
Below is an example API upload:
POST $BASE_URL/v1/orders?teamId=e8158f9b-bbb9-49fb-93fe-3ad481ca8450 HTTP/1.1accept: application/jsoncontent-type: application/jsonAuthorization: 4ww25f70-b52s-40de-8f29-07b139b5cdc8{"orders": [{"customerId": "wertg5432a","sessionId": "ec9-4e07-881d-3e9","id": "64965-5dvrt-5eds3-3wefw","teamId": "e8158f9b-bbb9-49fb-93fe-3ad481ca8450","customerId": "b1445104-1c4a-4c4c-a0a9-6cbc12482c56","orderDate": "2018-04-30T01:14:99.832ZD","orderItems": [{"gtin": "88560901388694","quantity": "5","RegularUnitPrice": "9.99","totalOrderItemPriceAfterDiscounts": "49.95""adId": "1985988a-6f9f-4ce8-8d4a-0a4b559206ca",}]"adIds": ["display_8d6bd7aa780d2278cf743d95cbdcfb7d262c5ba0575446cba91b628720975ob","display_8d6bd7aa780d2278cf745t45tb4h5bgfu4ba0575446cba91b628720975ob","display_8d6bd7aa780d2278cf743d95cbdcfb7d262c5ba0575446cba91b628720975ob","display_8d6bd7aa780d2278cf743d95cbdcfb7d262c5b4564h654hb6h45b645ob"]}]}
curl -iX POST "$BASE_URL/v1/orders?teamId=e8158f9b-bbb9-49fb-93fe-3ad481ca845" \-H "accept: application/json" \-H "content-type: application/json" \-H "Authorization: 4ww25f70-b52s-40de-8f29-07b139b5cdc8" \'{"orders": [{"id": "64965-5dvrt-5eds3-3wefw","teamId": "e8158f9b-bbb9-49fb-93fe-3ad481ca8450","customerId": "b1445104-1c4a-4c4c-a0a9-6cbc12482c56","orderDate": "2018-04-30T01:14:99.832ZD","orderItems": [{"gtin": "88560901388694","quantity": "5","RegularUnitPrice": "9.99","totalOrderItemPriceAfterDiscounts": "49.95""adId": "1985988a-6f9f-4ce8-8d4a-0a4b559206ca",}]"adIds": ["display_8d6bd7aa780d2278cf743d95cbdcfb7d262c5ba0575446cba91b628720975ob","display_8d6bd7aa780d2278cf745t45tb4h5bgfu4ba0575446cba91b628720975ob","display_8d6bd7aa780d2278cf743d95cbdcfb7d262c5ba0575446cba91b628720975ob","display_8d6bd7aa780d2278cf743d95cbdcfb7d262c5b4564h654hb6h45b645ob"]}]}'
For more information visit:
Below is an example snippet of an order sync file:
order_id | customer_id | quantity | product_code | price_with_discounts | ad_id | ad_ids | order_date |
1343321 | 5721 | 1 | DM_357480 | 469 | banner_Z2YcoG5Pqe1uTCsz3Lk5WE3sBmExNjI4NjAxNDA | | 2019-03-15 |
6845353 | 4234 | 4 | 4153234 | 191.8 | display_4fy5MPixTU-cKAWimSlHsLkfrUZCV1NfNzM1NTM= | | 2019-03-15T17:06:17+00:06 |
6845353 | 4234 | 1 | BWS_73553 | 6 | display_IDI0Ks_vmSyeLUmDaa1UCCGJ_chCV1NfNzM1NTM= | | 2018-03-15T17:06:17+00:06 |
6845353 | 4234 | 3 | BWS_74549 | 18 | | display_IDI054g4_vmSyeLUmDaa1UCCGJ_chCV1NfNzM1NTM, display_IDI0Ks_vmSyeLUmDaa1UCCfyn34ox8zn29rc3d44z8cn, banner_Z2YcoG5Pqe1uTCsz3Lkcxy342omcx4832mx4433x, banner_33r3Csz3Lk5WE3sBmExNjI4x3yzcj38ccdh43ycxui3 | 2018-03-15T17:06:17+00:06 |
For more information visit:
If you have completed all of the steps, you should be ready to serve ads.
Create Catalog
Upload Product Data to Citrus
Request Product Ads when loading a page
Display selected ads when loading a page
Create Banner Ad Content Standard
Request and Display Banner ads when loading page
Send impressions and clicks to CitrusAd for reporting
Send order data to CitrusAd for reporting
To serve your first Ad, you will need to set up a campaign. To do this Log In to your account and select ‘Create Campaign’ in the top right corner.
The steps to create your fight campaign are:
Give your campaign a name
Decide on an activity period
Select Product/s to promote
Select bidding strategy (CPC/Fixed)
Targeting search terms
Review and Launch Campaign
You will need to give your campaign a name, we suggest something that is easily referenced and relevant to the products that you will be advertising or the overall campaign strategy goals.
The next step is to optionally choose whether or not your campaign will have a specific activity period. This is dependant on your marketing efforts, but in the case of your first campaign, just select ‘No’.
Assuming you have set up your catalog, you should be able to see and search through all of your products here to select which products to promote in your campaign.
Note: ensure your selected products are available in your testing environment, and are currently in stock
Bidding strategy in this case is either Cost Per Click or fixed ad rank. Generally if a retailer is setting up a campaign they will set a fixed ad rank, and if a supplier is setting up a campaign they will be using a Cost Per Click strategy. In this case select “Fixed ad rank” and select “Position 1” from the dropdown.
You have the option of targeting search terms here, and if you do that means that when a customer is searching for those terms you are bidding on a position or placing your products in a position on the results page. If you wish to test search terms, select ‘Yes’. In this case we will skip this step and select ‘No’
That’s it! You have now got your first campaign set up, all you have to do is make sure all the details are correct, agree to the Terms and Conditions, and launch the campaign.
You should be able to see the campaign live in your testing environment when on relevant pages.