개요
The Epsilon Retail Media platform supports closed caption and transcript files for Banner X video campaigns. Advertisers upload caption files (.vtt, .srt) and transcript files (.txt) alongside their video assets. Your integration consumes these file URLs from the ad response and renders captions in your video player.
This integration helps you meet accessibility requirements such as the European Accessibility Act (EAA), which mandates user-controlled closed captions on public-facing video content.
- Caption files are time-synced subtitle tracks for your video player.
- Transcript files are plain-text representations of the video's audio content for SEO and screen reader use.
This guide covers:
- How caption and transcript files appear in VAST and JSON ad responses
- VAST 4.3
<ClosedCaptionFile>element structure - JSON
videoTranscriptFiles[]array structure - How to render captions using the provided CDN URLs
- Testing and validation
Delivery model
Caption file URLs (.vtt / .srt) are delivered only via VAST, not JSON.
Transcript file URLs (.txt) are delivered only via JSON, not VAST.
Captions are consumed by your video player; transcripts are consumed at the page level.
Integration flow
Caption and transcript files follow the same delivery path as video assets. No additional API calls are required beyond your existing Banner X ad request.
- An advertiser uploads video, caption, and transcript files via the campaign wizard.
- Files are validated, stored, and served via CDN.
- Your existing Banner X ad request returns caption URLs in VAST and transcript URLs in JSON.
- Your video player reads the caption file URL and renders subtitles.
- Your page optionally displays transcript text for accessibility or SEO.
Supported file types
| Asset | Formats | Max size |
|---|---|---|
| Closed captions | .vtt (WebVTT), .srt (SubRip) | Configurable per retailer content standard (typically 1–4 MB) |
| Transcript | .txt (plain text) | Configurable per retailer content standard (typically 1–4 MB) |
Files are served as-is; the platform does not convert formats. Your video player is responsible for rendering captions.
사전 필수 조건
Before integrating captions and transcripts, confirm the following:
- Existing Banner X video integration — you already consume
<MediaFiles>from the VAST tag in the adm field. See Video ads for a complete ad response example that includes caption and transcript file delivery. - Video player with caption support — WebVTT or SRT caption tracks (e.g. HTML5
<track>element, or equivalent native player API). - Feature enabled for your namespace — contact your account team to enable caption and transcript uploads for your namespace.
- CORS configured — allow cross-origin fetch of
.vttfiles from the Epsilon CDN domain when using HTML5<track>elements.
Authentication and security
No additional authentication is required. Caption and transcript files are served via the same CDN as video assets. File URLs returned in the ad response are publicly accessible, using the same security model as video file URLs.
If your video player uses HTML5 <track> elements to load .vtt files, ensure your page's Content Security Policy allows fetching from the Epsilon CDN domain. The CDN sets appropriate CORS headers for cross-origin <track> loading.
Step 1: Parse caption files from the VAST response
Purpose: Retrieve time-synced caption file URLs from the VAST XML in the adm field for rendering in your video player.
What you need to do
- In your VAST parser, look for the
<ClosedCaptionFiles>element within each<Linear>creative (inside<MediaFiles>). - Each
<ClosedCaptionFile>child element contains the CDN URL as its text content. - The
typeattribute indicates the MIME type (text/vttorapplication/x-subripfor SRT). - The
languageattribute indicates the caption language (e.g.en).
Example VAST response
<Linear>
<Duration></Duration>
<MediaFiles>
<ClosedCaptionFiles>
<ClosedCaptionFile type="text/vtt" language="en"><![CDATA[https://dev12.flavedo.io./citrus/0f04cbc2-c933-4384-8d37-772e939d8d02]]></ClosedCaptionFile>
</ClosedCaptionFiles>
<Mezzanine><![CDATA[https://dev12.flavedo.io./citrus/37bb15a2-fd4d-4eb1-9dd7-7630b5df29d1]]></Mezzanine>
<MediaFile delivery="progressive" type="video/mp4" width="1280" height="720" bitrate="8700" codec="h264"><![CDATA[https://dev12.flavedo.io./citrus/37bb15a2-fd4d-4eb1-9dd7-7630b5df29d1]]></MediaFile>
</MediaFiles>
<VideoClicks>
<ClickTracking><![CDATA[https://integration.dev12.citrusad.com/v1/resource/second-c/...]]></ClickTracking>
<ClickThrough></ClickThrough>
</VideoClicks>
</Linear>Validation
- Confirm your VAST parser extracts the
<ClosedCaptionFile>URL when present. - Confirm your parser gracefully handles the absence of
<ClosedCaptionFiles>(not all campaigns include captions).
Common errors
| 오류 | Cause |
|---|---|
<ClosedCaptionFiles> not found | The campaign may not have an approved caption file, or caption delivery is not yet enabled for your environment. This is expected for campaigns without captions. |
Step 2: Parse transcript files from the JSON response
Purpose: Retrieve plain-text transcript file URLs from the JSON ad response for SEO or screen reader accessibility.
What you need to do
- In the Banner X generate response, look for the
videoTranscriptFilesarray on each ad object. - Each entry includes a
videoFileIdso you can match transcripts to their corresponding video. - Transcripts are plain text (
.txt) — use them for SEO metadata, screen readers, or alternative text display.
Example JSON response
"videoTranscriptFiles": [
{
"videoFileId": "a6f4c4a6-6982-4a8c-9a81-ecdfd4b3fa36",
"format": "txt",
"url": "https://dev12.flavedo.io./citrus/03d98ae2-67d5-49d3-9e9b-c8f278520657",
"language": "en"
}
]Validation
- Confirm your JSON parser reads the
videoTranscriptFilesarray when present. - Confirm graceful handling when the array is empty or absent.
Caption file URLs (for
.vtt/.srt) are only delivered via VAST, not JSON. Transcript files (.txt) are only delivered via JSON, not VAST. This separation reflects the different consumption patterns: captions are for video players (VAST), transcripts are for page-level accessibility (JSON).
Step 3: Render captions in your video player
Purpose: Display closed captions to shoppers during video playback.
What you need to do
- After parsing the caption URL from VAST, add a
<track>element to your HTML5 video player (or equivalent in your native player SDK). - Set
kind="captions". Use thedefaultattribute if you want captions enabled by default. - For .srt files, some players require conversion to WebVTT at runtime (prepend
WEBVTT\n\nand replace comma with period in timestamps).
Example HTML5 implementation
<video controls crossorigin="anonymous">
<source src="https://cdn.citrusad.com/video/abc123.mp4" type="video/mp4">
<track
kind="captions"
src="https://cdn.citrusad.com/captions/def456.vtt"
srclang="en"
label="English"
default
>
</video>Validation
- Play the video and confirm captions appear as an overlay.
- Confirm the shopper can toggle captions on/off via player controls.
- Confirm captions are time-synced with the video audio.
Common errors
| 오류 | Solution |
|---|---|
| Captions don't load (CORS error in console) | Ensure your Content Security Policy and CORS configuration allow fetching .vtt files from the Epsilon CDN domain. |
| Captions appear garbled or empty | Verify the file URL returns valid WebVTT content. Fetch the URL directly to inspect the file. |
Step 4: (Optional) Display transcript text
Purpose: Provide accessible text content alongside or below the video for screen readers and SEO.
What you need to do
- Fetch the transcript URL from the
videoTranscriptFilesentry in the JSON response. - Use the transcript text for accessibility, SEO, screen readers, or other retailer-specific use cases.
예시
<details>
<summary>Video transcript</summary>
<p id="transcript-content"></p>
</details>
<script>
fetch('https://cdn.citrusad.com/transcripts/ghi789.txt')
.then(r => r.text())
.then(text => {
document.getElementById('transcript-content').textContent = text;
});
</script>Data models and field definitions
VAST: ClosedCaptionFile element
ClosedCaptionFile element| Attribute / field | 유형 | 필수 입력 항목입니다 | 설명 | Accepted values |
|---|---|---|---|---|
type | 문자열 | 예 | MIME type of the caption file | text/vtt, application/x-subrip |
language | 문자열 | 아니요 | Language of the caption track | e.g. en |
| Element text | string (URL) | 예 | CDN URL of the caption file | HTTPS URL |
JSON: videoTranscriptFiles
videoTranscriptFiles| 필드 | 유형 | 필수 입력 항목입니다 | 설명 | Accepted values |
|---|---|---|---|---|
videoFileId | 문자열 | 예 | ID of the video file this transcript belongs to | UUID |
format | 문자열 | 예 | File format of the transcript | txt |
url | string (URL) | 예 | CDN URL of the transcript file | HTTPS URL |
language | 문자열 | 예 | Language of the transcript | e.g. en |
Backward compatibility
These additions are fully backward-compatible:
- If no caption files are attached to a campaign, the
<ClosedCaptionFiles>element is omitted from VAST entirely. - If no transcript files are attached,
videoTranscriptFilesis absent or an empty array in JSON. - Existing integrations that do not parse these new elements continue to work without changes.
Testing, sandbox, and go-live
Sandbox / test environment
- Request access to a test namespace with caption and transcript uploads enabled (contact your account team).
- Upload a test campaign with a sample
.vttcaption file via the campaign wizard. - Approve the campaign through the review cycle.
- Call the Banner X generate endpoint and inspect the VAST and JSON response.
Sample test cases
| Test | Steps | Expected result |
|---|---|---|
| VAST caption present | Request ad for campaign with approved .vtt caption | VAST contains <ClosedCaptionFiles> with valid CDN URL |
| VAST caption absent | Request ad for campaign without captions | No <ClosedCaptionFiles> element in VAST |
| JSON transcript present | Request ad for campaign with approved .txt transcript | JSON contains videoTranscriptFiles array with entry |
| Caption file accessible | Fetch the CDN URL from the VAST response directly | Returns valid WebVTT content with WEBVTT header |
| Player renders captions | Load video + caption track in your player | Captions display time-synced with video audio |
| CORS for track element | Load .vtt via <track> cross-origin | No CORS errors in browser console; captions render |
Go-live checklist
- VAST parser extracts
<ClosedCaptionFile>URLs when present - JSON parser reads
videoTranscriptFiles[]when present - Graceful fallback when captions or transcripts are absent
- Video player renders captions from CDN URL
- Shopper can toggle captions on/off
- CORS validated for cross-origin
.vttfetch - Transcript text accessible (if implementing Step 4)
- Tested with both
.vttand.srtcaption formats
Troubleshooting and FAQ
<ClosedCaptionFiles> element missing from VAST response
<ClosedCaptionFiles> element missing from VAST responseLikely cause: The campaign does not have an approved caption file, or caption delivery is not enabled in your environment.
Solution:
- Confirm the campaign has an approved caption file (uploaded and passed review).
- Contact your account team to verify the feature is enabled for your namespace.
CORS error when loading .vtt via <track> element
.vtt via <track> elementLikely cause: Content Security Policy or browser CORS enforcement blocking cross-origin fetch of the .vtt file.
Solution:
- Add the Epsilon CDN domain to your Content Security Policy's
connect-srcandmedia-srcdirectives. - Set
crossorigin="anonymous"on the parent<video>element if required.
Captions render but are not synced with video
Likely cause: The caption file was authored with incorrect timestamps, or the file is an SRT being loaded as VTT without conversion.
Solution:
- Fetch the caption file URL and inspect timestamps against video playback.
- If the file is .srt and your player only supports .vtt, convert at runtime (prepend
WEBVTT\n\n, replace,with.in timestamps).
Transcript URL returns 404
Likely cause: The campaign was updated and the transcript file was removed, or CDN propagation delay.
Solution:
- Re-fetch the ad response to get the current file URL.
- If the issue persists, contact support.
When contacting support, include:
- Request ID or correlation ID from the generate call
- Timestamp (UTC) of the ad request
- The
<ClosedCaptionFile>orvideoTranscriptFilesURL that is failing - Browser console error (for CORS issues)
- Namespace and campaign ID

