Skip to main content

End-to-End Integration Flow: Sponsored Display Ads

Step-by-Step Walkthrough

The high-level flow for requesting and displaying a Sponsored Display ad on a page is as follows:

  1. User visits a page with a display ad slot.

    When the user navigates to a page that includes a Sponsored Display placement (e.g. the homepage or a category landing page), your system begins rendering that page. The frontend should allocate a container (div or view) for the ad slot, but initially it can be empty or a placeholder.

  2. (Optional) Gather page context.
    If the page has any contextual information that can inform ad selection, the backend collects that data. For example, on a search results page, the list of products shown can be captured; on a category page, the category name or ID is known. For a generic homepage, there may be no specific context beyond the fact that it’s a homepage view. This context data will be included in the ad request to improve targeting (though it’s not strictly required for the ad call).

  3. Prepare the ad request.
    The backend (or a middleware layer on your server) constructs a JSON payload for the GoWit Ads API. This payload must include your Marketplace ID (to identify your account) and the Placement ID for the ad slot, as well as a Session ID to uniquely identify the user session. The session_id should be a persistent identifier that remains constant for the user across pages and visits (e.g. stored in a cookie or device storage) – this is crucial for attribution and frequency capping. Along with these required fields, include any relevant context collected.

  4. Call GoWit’s Ads API (server-to-server).
    Your backend sends a POST request to the GoWit /server/v2/ads endpoint (using the staging environment base URL) with the JSON payload. This call should be made asynchronously as part of your page rendering pipeline. Do not block the entire page load waiting indefinitely for the ad – implement a strict timeout (e.g. 100 ms) for this API call. The request is typically made in parallel with other page content fetching. Use HTTPS and include the Authorization header with your API token.
    (For example, in staging: POST https://<your-stage>.gowit.com/server/v2/ads with header Authorization: <Your-API-Key>.)

  5. Receive ad response from GoWit.

    The GoWit ad server will process the request and respond with either:

    • An HTTP 200 OK and a JSON body containing one or more ads for the requested placement, or
    • An HTTP 204 No Content with an empty body if no ad is eligible for that placement at the moment.

    If the response is 200, it will include the placement_id and an array of ads objects. Each ad object contains fields like a unique ad_id, the advertiser_id (seller) who sponsored it, the creative_id, the img_url of the creative asset, a redirect (click-through URL), etc. (Detailed schema is discussed in the Ad Response Handling section below.) If the response is 204 or if the API call times out, treat it as “no ad”.

  6. Render the ad creative on the frontend (if provided).

    If an ad was returned in step 5, your backend should pass the relevant ad data to the frontend. Since Sponsored Display responses include a ready-to-display creative, no further content lookup is needed on your side – unlike product ads, you do not need to query your product catalog for titles or images. The frontend’s role is simply to take the provided img_url and redirect and render them in the placement container. This typically means setting the image source of an <img> tag to the img_url, and wrapping it in a clickable link that uses the provided URL (or using an <iframe> if an HTML creative was provided, though image URLs are most common).

    Make sure to mark or label the ad as sponsored according to your site’s UX guidelines (e.g. a small "Sponsored" tag or similar, to comply with advertising disclosure policies). The creative will be exactly the dimensions specified by the placement (e.g. a 300x250 image for a 300x250 slot), so ensure the container on your page is the correct size to avoid distortion. If multiple ads were returned for the placement (e.g. you requested max_ads > 1 for a rotating carousel), you can either display them sequentially (rotation) or choose one – but in most standard integrations, you request and show a single ad at a time.

  7. Graceful fallback if no ad was returned.
    If the ad request resulted in no content (empty list or a 204 response) or if the API call did not return within your timeout threshold, your integration should simply proceed without any ad for that slot. In this case, instruct the frontend to collapse or hide the ad container, or fill it with alternate content (such as a placeholder or your own house promo) if desired. The key is that the user should not see a broken empty frame. Your backend should not retry the ad request on that page load and should not delay the page waiting any longer than the timeout – just move on and render the page without a sponsored banner in that spot. This ensures the user experience is not negatively impacted by unavailable ads. On subsequent page loads or navigations, you can attempt to fetch ads again, but each page view gets only one opportunity for an ad fill in that slot.


The above flow ensures that whether an ad is available or not, your pages render swiftly and without errors. Next, we’ll dive into the specifics of the API request format and how to implement the call with proper error handling and timeouts.

Example: Pseudocode for Server-Side Ad Request with Timeout and Fallback (sponsored display logic)

AD_REQUEST_TIMEOUT_MS = 100  # e.g. 100ms timeout for ad call

# Prepare the ad request payload with required fields and any available context
payload = {
"marketplace_id": MARKETPLACE_ID,
"placements": [
{ "placement_id": DISPLAY_PLACEMENT_ID, "max_ads": 1 }
],
"session_id": SESSION_ID,
# Optional context fields:
# "search": SEARCH_QUERY, # e.g. "wireless headphones"
# "category": CATEGORY_PATH, # e.g. "Electronics > Headphones"
# "products": [ # visible products on page (if any)
# { "id": "SKU-111", "category": "Electronics > Headphones" },
# { "id": "SKU-112", "category": "Electronics > Headphones" }
# ],
# "customer": { "id": USER_ID, ... }, # e.g. user or segment info (if available)
# "region_id": REGION_CODE, # e.g. "US-CA" if applicable
# ... (other optional fields as needed)
}

display_ads = [] # will hold any returned ads for the placement
try:
response = http_post(GOWIT_STAGE_ADS_URL, json=payload, timeout=AD_REQUEST_TIMEOUT_MS,
headers={"Authorization": API_KEY})
if response.status_code == 200:
# Parse the JSON for ads. Assuming one placement requested:
resp_json = response.json()
if resp_json.get("placements"):
display_ads = resp_json["placements"][0].get("ads", [])
# If status_code == 204 or "ads" list is empty, we'll fall through with display_ads = []
except TimeoutError:
# The request took longer than 100ms and was aborted
display_ads = [] # treat as no ads
# === Post-processing: send ad data to frontend ===
if display_ads:
# We have at least one sponsored banner to show
ad = display_ads[0] # take the first ad (position 1)
# No need to enrich with product info – creative is ready to use.
# Prepare the data for front-end rendering, e.g.:
banner_data = {
"img_url": ad["img_url"],
"click_url": ad["redirect"]["url"],
"ad_id": ad["ad_id"]
# (plus perhaps alt text or other metadata if provided)
}
# The front-end should use this data to render the image and link.
else:
# No ad to show (either no fill or timeout) – mark the placement as empty
banner_data = None
# Continue generating the page content, including the ad slot (filled or empty).

In the above pseudocode, the backend calls the server/v2/ads endpoint with a JSON payload and a short timeout. If an ad comes back in time, we capture it; if not, we move on. Notice that we do not attempt to retry on that page load, and we do not cache any ad responses for reuse.

Ad Timeout & No-Fill Fallback Policy

As demonstrated, you must implement a strict timeout and fallback when calling GoWit for ads. We recommend around 100ms timeout for the ad request – if the ad server hasn’t responded by then, assume no ad is available and let the page proceed. Do not hold up page rendering waiting for ads beyond the timeout, and do not retry the call on the same page load. In practice, this means if the ad service is slow or returns no content, the user simply sees the page without the ad and likely never notices anything was missing. This policy is important to ensure that a slow ad response never degrades your site’s performance or user experience. It applies to both web and mobile app integrations.

Similarly, if the ad API returns an explicit 204 No Content or an empty list of ads, treat it the same as a timeout case – no ads for that view. Design your front-end to gracefully handle an empty ad slot by collapsing it or using a placeholder. Never leave a blank rectangle or a broken image on the page. The goal is a seamless experience: if an ad arrives, it’s shown; if not, the page looks normal with only organic content.

Do Not Cache Ad Responses

Do not cache the responses from the GoWit /ads API. Each ad request should be made fresh, and the results should never be reused for another user or a later time. Sponsored ad selection is real-time, depending on the current context (page, user session, etc.) and dynamic campaign conditions (budgets, targeting, pacing). Using a cached response (even one from earlier in the same user session) can result in showing outdated or ineligible ads, misreporting impressions/clicks, and other inconsistencies. Always call the API anew for each page view that needs an ad, and use the response immediately. (Caching at the HTTP layer, CDN, or in-memory is strongly discouraged for ad calls.)

Sample Ad Request Payloads

A Sponsored Display / Sponsored Banner Display ad request is a JSON object that includes both required fields and optional context fields. Below we provide example payloads for common scenarios. The request is made as an HTTP POST to the staging ads endpoint (e.g. https://<your-stage>.gowit.com/server/v2/ads) with content type application/json and your API key in the Authorization header.

Example 1: Homepage Banner Ad Request (no specific context)

When a user visits the homepage (or any general landing page) that contains a sponsored display banner slot, you should request an ad for that placement. In this scenario, there is no search query or product list to send. The request simply identifies the placement and session, and optionally any user or regional info if available. For instance, a homepage banner request could look like:

{
"marketplace_id": 42,
"page_number": 0,
"placements": [
{
"placement_id": 501,
"max_ads": 1
}
],
"session_id": "abc123-456-def789-0001"
}

Explanation

In this minimal payload, we specify the marketplace (42 in this example), and one placement with ID 501 (assume this is the "Homepage Banner" placement configured in GoWit). We request at most 1 ad ("max_ads": 1), which is typical for a single banner slot. We include a session_id ("abc123-456-def789-0001"), which is a UUID representing the user session.

We did not include search, category, or products because on the homepage there are no inherent search terms or product list context. The ad server will return the best available display ad for a general context (possibly using other targeting like audience or just default campaign priority).

If your platform knows something about the user (e.g., they are a logged-in user with ID 123 or located in a specific region), you could include that in a customer or region_id field, but it’s not required.

Example 2: Search Results Page Banner Ad Request

If you have a Sponsored Display banner placement on a search results page (for example, a banner that appears above or between the product results), you should provide the search context so the ad can be relevant to the query. Let’s say a user searched for “running shoes” and your page shows a list of shoe products. Your ad request might be:

{
"marketplace_id": 42,
"search": "running shoes",
"placements": [
{
"placement_id": 510,
"max_ads": 1
}
],
"page_number": 0,
"session_id": "abc123-456-def789-0001",
"products": [
{
"id": "SKU-11111",
"category": "Sportswear > Shoes > Running Shoes"
},
{
"id": "SKU-11112",
"category": "Sportswear > Shoes > Running Shoes"
},
{
"id": "SKU-11113",
"category": "Sportswear > Shoes > Running Shoes"
}
]
}

Explanation

Here we include the search term "running shoes" in the request. The placement_id 510 corresponds to a banner slot on the search results page. We indicate page_number: 0 (first page of results). We also provide a list of the top products shown on that search page in the products array, each with an ID and category.

Including this product context is optional for display ads, but we show it here to illustrate the format – it can help if, for example, an advertiser has a display campaign tied to certain products or categories (Connected Products feature). The ad server will use the search keyword and possibly the categories of the listed products to find a banner that matches (say, a sportswear brand’s banner targeting “running” or related categories). If no keyword-targeted banner is available, it might just serve a general ad.

Note that even though we sent a products list, the returned ad will be a banner image, not one of those specific products (display ads aren’t product detail ads). Also, by setting max_ads: 1, we only want one banner back even if multiple could be eligible.

Example 3: Category Page Banner Ad Request

On a category listing page (for instance, the user navigates to “Electronics > Cameras”), you might have a display ad slot on that page. In the ad request, include the category context so that category-targeted campaigns can be matched. For example, for a category page showing digital cameras:

{
"marketplace_id": 42,
"category": "Electronics > Cameras > Digital Cameras",
"placements": [
{
"placement_id": 520
}
],
"page_number": 0,
"session_id": "abc123-456-def789-0001"
}

Explanation

We provide the full category path of the page in the category field. The placement_id 520 is assumed to correspond to a banner on the Electronics/Cameras page. We did not specify max_ads here, so the default for this placement will apply (likely 1).

We also omitted the products list in this example – you could include the list of products shown on the Cameras page (and it may help the system prefer a camera-related banner if one is available), but it’s not strictly necessary for display ads. Even with just the category context, GoWit can filter for any Sponsored Display campaigns targeting the Electronics or Cameras category. The session_id is included as usual.

The ad server will attempt to return a banner relevant to “Electronics > Cameras”. If an electronics brand or camera advertiser has a display campaign for that category, that banner might be returned. If not, a more general ad could fill the slot (or no ad if nothing matches).

These examples demonstrate the structure of Sponsored Display ad requests in various contexts. Always include the basics (marketplace_id, placement_id, session_id), and add contextual fields like search, category, and products when you have them to improve targeting. Ensure the JSON is correctly formatted and that you use real IDs from your integration (the above IDs are illustrative).

Ad Response Handling and Creative Rendering

When you call the ads API, a successful response (HTTP 200) will return a JSON body describing the ads to display. It’s important to understand this response format to properly render the ads and handle tracking. An HTTP 204 response means “no ad content” – in that case there’s no JSON to parse (just skip showing an ad). Below we describe the response structure for Sponsored Display ads and how to use it.

Response structure

The JSON response will have a top-level placements array corresponding to each placement you requested. (In most cases you request only one placement per call, so there will be one element in this array.) Each placement result contains the placement_id and an ads array. For example:

{
"placements": [
{
"placement_id": 501,
"ads": [
{
"ad_id": "02180dcc-089b-410c-9593-ca05ef890b2e",
"advertiser_id": "1002",
"creative_id": 1301,
"img_url": "https://assets.gowit.com/stage/.../f450572b-7959-43ff-ab7c-a4c4292b0898.png",
"position": 1,
"products": null,
"redirect": {
"type": "custom",
"url": "https://advertiser.example.com/promo-page"
},
"size": "300x250"
}
]
}
],
"response_id": "5832b387-101c-4161-bb42-2b125c6dfbed"
}

Ad Response Field Details

  • ad_id – A unique UUID for this ad impression. This ID ties together the impression and any subsequent click or conversion events. You should keep track of it (e.g., send it to the frontend, so if the user clicks the ad, you can later report that click with this ad_id). It’s also used by GoWit for attribution (to know which ad was seen).

  • advertiser_id – The identifier of the advertiser (seller or brand) who is running the ad campaign. This corresponds to the IDs in your advertiser (seller) feed. While the frontend doesn’t typically display this directly, you might use it for logging if needed. It’s mainly informational for you, and for event tracking.

  • creative_id – An internal ID for the creative (the actual ad asset) that was served. This can be useful for debugging or if you need to request creative details from GoWit. Generally, your integration logic doesn’t need to use this ID; it’s more for reference.

  • img_url – The URL of the image creative to display. This is typically a link to a CDN where the banner image is hosted. Your frontend should load this URL into an <img> element (or as a background image) in the placement container. Treat it like any other image URL – you may want to add loading attributes or styling as needed, but do not alter the image’s aspect ratio. The image is already designed for the placement’s dimensions.

  • position – The position rank of this ad in the returned list. If you only get one ad, it will usually have "position": 1. If you requested multiple (max_ads > 1), the ads may have positions 1, 2, etc., indicating the order they should be considered. In most cases, you will render all returned ads in the order given (for instance, if you have multiple ad slots or a rotating banner). Ensure you respect this ordering because it’s determined by the ad server’s ranking.

  • products – Additional product references associated with the ad. For Sponsored Display ads, this will generally be null or empty, because the ad is not tied to a single product. (In other formats, this might carry associated product info.) You can ignore this field for display ads.

  • redirect – An object describing the click-through behavior for the ad. Typically it has a type and a url. For example, "type": "custom" with a url indicates the user should be taken to the provided URL when they click the banner. The URL might be an external site (e.g., the advertiser’s own website) or an internal link (e.g., a page on your marketplace, if the campaign is set that way). In any case, your frontend should use this URL as the target of the click. Usually, you’ll wrap the image in an anchor tag pointing to this URL, or handle the click event in a mobile app to open a webview or browser to that URL.

  • size – The dimensions of the creative asset, as widthxheight. For example, "300x250" in the above response. This should match the placement’s expected size. It’s a good practice to double-check that the size matches what you expect for that placement, especially if you support multiple sizes. You normally don’t need to use this field explicitly, but it can be used to verify you’re inserting the ad into an appropriately sized container.

  • response_id (top-level field) – A unique ID for the response as a whole. This can be useful for logging or troubleshooting (GoWit support might ask for a response_id to trace a particular request in their logs). You don’t need it for rendering.

When your backend receives this JSON, it should extract the ad info and pass it to the frontend in whatever way fits your architecture (it could be injected server-side into the HTML, returned via an AJAX response to the client, etc.). The frontend then needs to render the banner using the provided img_url.