Configure SSAI for VOD using the POST workflow

Stitch server-side ads into your VOD delivery with the recommended VOD implementation

You can use the VOD implementation POST endpoint to initialize an SSAI session for a VOD media item, retrieve the SSAI-enabled manifest, and tailor the viewer’s ad experience with session and break data.

The POST workflow sends a single request with the VOD media item, ad config ID, and optional settings, returning the SSAI-enabled manifest URL and session data for playback and tracking. Because initialization occurs directly, it simplifies setup and provides immediate access to session context, unlike the GET endpoint’s redirect-based flow.

In a single initialization request, you can:

  • Create the SSAI session
  • Return the playback manifest URL
  • Support client-side beaconing
  • Pass custom ad parameters with adsParams
  • Configure options such as stitch_mode
  • Return a MediaTailor-compatible response format when schema=aws

This approach gives you more control over session initialization, ad decisioning, and the user’s ad experience.


POST workflow summary

At a high level, the POST workflow requires the following steps to set up SSAI for VOD:

  1. Initializes the VOD implementation session with the POST endpoint, including optional settings such as reportingMode, adsParams, stitch_mode, and schema if desired.
  2. Retrieves the SSAI-enabled manifest URL from the POST response.
  3. Embeds that manifest URL in your player.
  4. Uses the session URL returned at initialization to fetch session data.
  5. (Optional) Retrieves break-level data to preload ads for a specific break.
  6. Uses the session data to customize the viewer’s ad experience.



Prerequisites

Item Notes
Property-level enablement Toggle turning on the feature for an entitled property

Follow these steps to enable SSAI:
  1. On the Properties page, click the name of a property. The property settings appear.
  2. Under Content & ads enhancements, click Media & ads. The Media & ads tab opens.
  3. Under Server-side ad integration, toggle Enable SSAI to ON.
VOD content Video-on-demand media that is hosted on the JW Platform and prepared to stream

Get started with media management in the JW Platform.
Player embed Player library embedded on the web page

You can use the JWP player or a third-party player.

If you are using JWP, learn how to add a cloud-hosted or self-hosted player.
Site ID Unique identifier of the property or site that owns a media item

Follow this step to obtain a site ID:
  1. On the Properties page, in the Property ID column, click to copy the ID.
Media ID Eight-character, alphanumeric ID that uniquely identifies the media

Follow these steps to obtain a media ID:
  1. From the Media library page, click a media item. The media details page appears.
  2. In the Media ID field, click to copy the ID.
Ad config ID Unique identifier of an ad config

Follow these steps to obtain an ad config ID:
  1. On the Advertising page, click the Ad config tab.
  2. In the ID column, click to copy the ID of your desired ad config.

If you have not already, create an ad config.

NOTE: For VOD media, the ad config defines:
  • The ad break duration
  • The default time between ad breaks in your content
  • The ad tag URL from which ads are fetched


Configure SSAI for VOD

📘

Learn how to configure your SSAI VOD implementation with client-side beaconing.

🚧

JIT advertising is available only for certain supported renditions when using SSAI for VOD.

Learn more
You can stitch ads JIT for VOD media items with the following renditions:
  • 320x180
  • 480x270
  • 640x360
  • 960x540
  • 1280x720
  • 1920x1080

If a media item uses a different rendition, the non-JIT workflow applies automatically, and ad breaks are stitched before the video is delivered.

Follow these steps to configure SSAI for VOD using the POST workflow:

  1. Make a POST call to the SSAI manifest endpoint. The POST response initializes the SSAI session and returns the values needed to stream and handle the session.

    curl --request POST \
      --url https://cdn.jwplayer.com/v2/sites/{site_id}/media/{media_id}/ssai.{manifest_extension} \
      --header 'Content-Type: application/json' \
      --data '{
        "ad_config_id": "{ad_config_id}",
        "reportingMode": "server",
        "adsParams": {
          "cust_params": "genre=sports&tier=premium",
          "ppid": "user-12345"
        },
        "stitch_mode": "default",
        "schema": ""
      }'
    

  2. Retrieve the SSAI-enabled manifest URL (manifest_url) from the successful response.

    📘

    The field names in the response may vary depending on your selected response schema, but all schema values will respond with the streaming manifest.

    {
      "manifest_url":   "https://cdn.jwplayer.com/v2/sites/{site_id}/media/{media_id}/ssai_session/{session_id}/jit.m3u8",
      "tracking_url": 
    "https://cdn.jwplayer.com/v2/sites/{site_id}/media/{media_id}/ssai_session/{session_id}/info.json"
    }
    
  3. Pass the SSAI-enabled manifest URL into your player’s file property during setup.

    When the player starts streaming content using the SSAI-enabled manifest, ads will play as part of the stitched stream.

    <div id="vodPlayer"></div>
    
    <script src="https://cdn.jwplayer.com/libraries/{playerLibraryId}.js"></script>
    
    <script>
      jwplayer.key = "{yourPlayerLicenseKey}";
    
      const manifestUrl = "https://cdn.jwplayer.com/v2/sites/{siteId}/media/{mediaId}/ssai_session/{sessionId}/jit.m3u8";
    
      const playerInstance = jwplayer("vodPlayer");
    
      playerInstance.setup({
        file: manifestUrl,
        type: "hls",
        autostart: true,
        width: "100%",
        aspectratio: "16:9"
      });
    </script>
    

  1. Once playback begins, fetch the session data. The endpoint will return a JSON representation of the ad breaks in the session.

    📘

    Example JSON before ads are stitched
    This JSON contains the metadata for each ad break in the session, including break durations and tracking events. However, the ads have not yet been stitched for the break (ads_requested equals false).

    You can retrieve the ad break data for a JSON with stitched ads.

    NOTE: If you use a non-JIT rendition, the session data endpoint will return a JSON representation with ads already stitched.
    {
      "breaks": [
        {
          "ad_break_tracking_events": null,
          "ads": null,
          "break_id": "break_0_0",
          "duration": 30.72,
          "time_offset": 0,
          "ads_requested": false,
          "url": "profile/mpegts-25-1920-v1/breaks/0/info.json"
        },
        {
          "ad_break_tracking_events": null,
          "ads": null,
          "break_id": "break_1_0",
          "duration": 120.96,
          "time_offset": 62.72,
          "ads_requested": false,
          "url": "profile/mpegts-25-1920-v1/breaks/1/info.json"
        },
        {
          "ad_break_tracking_events": null,
          "ads": null,
          "break_id": "break_2_0",
          "duration": 120.96,
          "time_offset": 195.68,
          "ads_requested": false,
          "url": "profile/mpegts-25-1920-v1/breaks/2/info.json"
        }
      ]
    }
    
  2. (Optional) Retrieve data for an ad break.
  3. Customize the viewer experience.

Retrieve data for an ad break

JWX allows you to fetch specific ad break data.

By default, JWX stitches ads just-in-time (JIT). However, retrieving the break data triggers the SSAI system to stitch ads in advance.

Preloading ads this way can reduce the risk of playback buffering or black states, provide tighter control over the timing and behavior of the player UI, and enable developers to fine-tune the ad experience based on session logic or user status. This approach is ideal for highly curated or premium content.

Follow these steps to retrieve data for a specific ad break:

  1. Within the returned session data, identify the specific ad break you wish to target.
  2. Copy the url parameter for the specific ad break.
  3. In the session endpoint, replace info.json with the url value.
  4. Make another GET call to the updated endpoint. This call prepares the SSAI system to stitch ads for the targeted break.
    curl --request GET \
         --url 
    https://cdn.jwplayer.com/v2/sites/{site_id}/media/{media_id}/ssai_session/{ssai_session_id}/{appended_break_url}
    
    The endpoint will return a JSON representation of the session with ads stitched for the targeted break.

    📘

    Example JSON after ads are stitched
    This JSON contains the metadata for each ad break in the session, as well as the ads that occur in the preloaded break.
    {
      "breaks": [
        {
          "break_id": "break_0_0",
          "time_offset": 0,
          "duration": 30.72,
          "ads_requested": true,
          "ads": [
            {
              "id": "0",
              "start_time": 0,
              "duration": 7.68
            },
            {
              "id": "7",
              "start_time": 7.68,
              "duration": 9.6
            },
            {
              "id": "17",
              "start_time": 17.28,
              "duration": 9.6
            }
          ],
          "url": "profile/mpegts-25-1920-v1/breaks/0/info.json"
        },
        {
          "break_id": "break_1_0",
          "time_offset": 62.72,
          "duration": 120.96,
          "ads_requested": false,
          "ads": [],
          "url": "profile/mpegts-25-1920-v1/breaks/1/info.json"
        },
        {
          "break_id": "break_2_0",
          "time_offset": 195.68,
          "duration": 120.96,
          "ads_requested": false,
          "ads": [],
          "url": "profile/mpegts-25-1920-v1/breaks/2/info.json"
        }
      ]
    }
    
    

Now that you have fetched your break data, you can perform various actions to control and improve the advertising experience.


Customize the viewer experience

After retrieving session and break data, you can view details about the ads in each break, including their start times, durations, and tracking events. You can then use this information to customize the playback experience with the following actions.

Action Description
Check fill status of an ad break Determine whether a break is fully or partially filled and take appropriate action

Follow these steps:
  1. After retrieving the break-level session JSON, inspect the ads array.
  2. Sum the duration of each ad in the break.
  3. Compare the total to the break’s duration field.
  4. If the ad durations fall short of the break duration, treat it as partially unfilled.
Skip unused filler time Improve viewer experience by skipping black slates or unfilled ad slots

Follow these steps:
  1. Check ads_requested and compare total ads[].duration to the break’s duration.
  2. If ads_requested is false or total ad time is shorter, programmatically skip to the end of the break.
  3. Use your player API (such as the seek() or play()) to jump to the break end time.
Display ad countdowns Show viewers how much ad time remains to improve transparency and UX

Follow these steps:
  1. Extract the ads list from the break-level JSON.
  2. Track the current playback position.
  3. Subtract elapsed time within the break from total ad durations to display a real-time countdown.
Control playback UI during ads Comply with advertiser requirements and improve viewer engagement

Follow these steps:
  1. Use the break’s start_time and duration to detect when an ad in playing.
  2. Temporarily disable player controls like seeking or skipping using your player API.
  3. Optionally show a “Skip Ad” button based on timing logic or tracking events (such as appearing after 5 seconds).



FAQ

Will an ad be requested again if the user scrubs back?

No. Once an ad is stitched into the stream, it behaves like regular video content. If a user scrubs back, the same ad content will replay as part of the stitched video, but a new ad request will not be sent.

This helps maintain session consistency and avoids duplicate ad requests.




© 2007- Longtail Ad Solutions, Inc.