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:
- Initializes the VOD implementation session with the
POSTendpoint, including optional settings such asreportingMode,adsParams,stitch_mode, andschemaif desired. - Retrieves the SSAI-enabled manifest URL from the
POSTresponse. - Embeds that manifest URL in your player.
- Uses the session URL returned at initialization to fetch session data.
- (Optional) Retrieves break-level data to preload ads for a specific break.
- 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:
|
| 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:
|
| Media ID | Eight-character, alphanumeric ID that uniquely identifies the media Follow these steps to obtain a media ID:
|
| Ad config ID | Unique identifier of an ad config Follow these steps to obtain an ad config ID:
If you have not already, create an ad config. NOTE: For VOD media, the ad config defines:
|
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:
320x180480x270640x360960x5401280x7201920x1080If 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:
-
Make a
POSTcall to the SSAI manifest endpoint. ThePOSTresponse 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": "" }'
-
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 allschemavalues 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" } -
Pass the SSAI-enabled manifest URL into your player’s
fileproperty 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>
- 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_requestedequalsfalse).
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" } ] } - (Optional) Retrieve data for an ad break.
- 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:
- Within the returned session data, identify the specific ad break you wish to target.
- Copy the
urlparameter for the specific ad break. - In the session endpoint, replace
info.jsonwith theurlvalue. - Make another
GETcall to the updated endpoint. This call prepares the SSAI system to stitch ads for the targeted break.The endpoint will return a JSON representation of the session with ads stitched 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}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:
|
| Skip unused filler time | Improve viewer experience by skipping black slates or unfilled ad slots Follow these steps:
|
| Display ad countdowns | Show viewers how much ad time remains to improve transparency and UX Follow these steps:
|
| Control playback UI during ads | Comply with advertiser requirements and improve viewer engagement Follow these steps:
|
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.
