Request Lifecycle
The following steps describe what happens during a playback session with Brightcove Recommendations enabled:
- Video starts playback — The player requests recommendations from the Recommendations service. A regular
video_viewevent is tracked. - Recommendations are displayed — The recommendation slate appears (based on the timing configuration). A
recommendation_impressionevent is tracked for each recommended video shown in the slate, so a slate that displays multiple videos counts multiple impressions. The initial video is registered as watched. - Countdown begins — If autoplay is enabled, the countdown timer starts. The next recommended video is pre-fetched.
- Recommended video plays — A new
video_viewis tracked withsource_video_idset to the initial video's ID. The player requests the next set of recommendations based on the initial video (not the current one). Previously watched videos are filtered out. - Cycle continues — Steps 2–4 repeat for each subsequent recommendation. All requests remain anchored to the initial video.
Algorithms
Brightcove Recommendations offers three recommendation strategies. Each uses a different primary signal but all apply the same eligibility and restriction rules.
Related Content
Finds semantically similar content using AI-based similarity as the primary ranking signal. The system analyzes your video metadata to identify the most closely related content in your catalog.
Two boosters refine the results:
- Tag similarity — Favors videos with overlapping tags, improving precision when metadata is well-structured.
- Recency booster — Slightly favors newer content so that fresh videos surface alongside evergreen matches.
Trending Now
Identifies viral and popular content by combining multiple signals:
- Popularity score — Based on total video views within the configured timeframe (daily or weekly).
- Momentum score — Measures the acceleration of video views, identifying content that is gaining traction quickly.
- Time decay — Favors recently trending content over older spikes.
After calculating trending scores, the results are rescored by semantic similarity to the initial video and tag matching to maintain relevance.
Recently Added
Surfaces the latest published content by sorting videos by their publication date (newest first). The results are then rescored by semantic similarity to the initial video and tag matching so that the most relevant new content ranks higher.
Deduplication
The player automatically tracks which videos have already been shown during a session and filters them from future recommendations. The source video is also excluded from its own recommendations.
If the player state is reset (e.g., a page refresh), the tracking resets and previously shown videos may appear again.
Fallback Strategy
When the Expand Recommendations setting is enabled in the Admin module and no results are found:
- The system retries the query without the look-back period and duration constraints.
- Restrictions remain enforced during fallback — they are never relaxed.
This ensures that recommendation slates are not empty while still respecting editorial guardrails.
Recommendations API
In addition to the player plugin, you can access recommendations programmatically via the Recommendations API to power custom UX elements such as rails, carousels, and discovery pages.
Base URL
https://recommendations.api.brightcove.com
Authentication
The Recommendations API uses Brightcove OAuth. Include a Bearer token in the Authorization header. The required permissions depend on the endpoint:
Authorization: Bearer {access_token}
| Endpoint | Permission |
|---|---|
GET /settings |
video-cloud/setting/read |
POST /settings |
video-cloud/setting/write |
POST /recommendations |
Any valid Brightcove OAuth token. No specific permission is required. |
See Managing API Authentication Credentials for details on obtaining OAuth credentials.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
string | Yes | Your Video Cloud account ID. |
GET /v1/accounts/{account_id}/settings
Returns the recommendation settings for the specified account. If no settings exist, the API creates and returns default settings.
Response
Returns an AccountRecommendationSettings object. See the Settings Model section below for full field reference.
Example
GET /v1/accounts/1234567890/settings
Authorization: Bearer {access_token}
Sample Response
{
"account_id": "1234567890",
"timeframe_days": 365,
"max_video_duration": 1800,
"min_video_duration": 0,
"excluded_tags": [],
"lock_offs": [],
"campaigns": [],
"trending_recurrence": "daily",
"fallback_content": true
}
POST /v1/accounts/{account_id}/settings
Creates or updates the recommendation settings for the specified account. The request body must match the account_id in the path.
Request Body
The body is an AccountRecommendationSettings object. See the Settings Model section below for full field reference. You can pass only the fields you want to update.
Response
Returns the updated AccountRecommendationSettings object.
Errors
| Status | Description |
|---|---|
422 |
The account_id in the request body does not match the path parameter, or validation failed. |
500 |
Failed to save settings. |
Example
POST /v1/accounts/1234567890/settings
Authorization: Bearer {access_token}
Content-Type: application/json
{
"account_id": "1234567890",
"timeframe_days": 180,
"max_video_duration": 3600,
"min_video_duration": 30,
"excluded_tags": ["internal", "draft"],
"trending_recurrence": "weekly",
"fallback_content": true
}
POST /v1/accounts/{account_id}/recommendations
Returns video recommendations for the specified source video. Use this endpoint to power custom recommendation UI elements outside the Brightcove Player.
Request Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
video_id |
string | Yes | — | The source video ID (currently playing or anchor video). |
excluded_ids |
array of strings | No | null | List of video IDs to exclude from results (for deduplication). |
limit |
integer | No | 1 | Maximum number of recommendations to return. Range: 1–50. |
mode |
string | No | related |
Recommendation strategy: related, trending, or recent. |
enable_featured_content |
boolean | No | true | Whether to include promoted content campaigns in the results. |
Response
Returns a RecommendationsResponse object:
| Field | Type | Description |
|---|---|---|
recommendations |
array | List of recommended videos. Each item contains video_id (string) and reason (string: related, trending, recent, or featured). |
count |
integer | Number of recommendations returned. |
Example
POST /v1/accounts/1234567890/recommendations
Authorization: Bearer {access_token}
Content-Type: application/json
{
"video_id": "6345678901234",
"limit": 6,
"mode": "related",
"excluded_ids": ["6345678901111", "6345678901222"],
"enable_featured_content": true
}
Sample Response
{
"recommendations": [
{
"video_id": "6345678901235",
"reason": "related"
},
{
"video_id": "6345678901236",
"reason": "related"
},
{
"video_id": "6345678901237",
"reason": "featured"
}
],
"count": 3
}
Settings Model
The following tables describe every field in the AccountRecommendationSettings model, used by both the GET and POST settings endpoints.
Core Settings
| Field | Type | Default | Description |
|---|---|---|---|
account_id |
string | — | Your Video Cloud account ID. |
timeframe_days |
integer | 365 | Only videos published within this many days are eligible. Range: 1–730. |
max_video_duration |
integer | null | 1800 | Maximum video duration in seconds. Set to null or 0 for no limit. |
min_video_duration |
integer | null | 0 | Minimum video duration in seconds. Set to null or 0 for no limit. Cannot exceed max_video_duration. |
excluded_tags |
array of strings | null | null | Videos with any of these tags are excluded from all recommendation results. |
trending_recurrence |
string | daily |
Time window for trending scoring: daily or weekly. |
fallback_content |
boolean | false | When true, falls back to a relaxed query (no timeframe or duration limits) if eligible results are too few. Restrictions remain enforced. |
Lock-offs
Lock-offs are editorial constraints that narrow recommendations. A lock-off bundles one or more constraints that are combined with AND logic. A constraint only applies if the source video also has the matching value(s) (intersection logic).
| Field | Type | Default | Description |
|---|---|---|---|
lock_off_id |
string | — | Unique lock-off identifier. |
name |
string | — | Human-readable name for the lock-off. |
description |
string | null | null | Optional description. |
status |
string | active |
active or archived. Only active lock-offs within their date range are applied. |
start_date |
datetime | null | null | ISO 8601. Lock-off is active from this date onward. |
end_date |
datetime | null | null | ISO 8601. Must be after start_date. |
constraints |
array | — | At least one constraint required. All constraints in a single lock-off must share the same type. |
Lock-off Constraints
| Field | Type | Description |
|---|---|---|
type |
string | Constraint type: tag or custom_field. |
field_name |
string | null | Required when type is custom_field. The custom field name to match against. |
value |
string | The tag name or custom field value that recommended videos must match. |
Featured Content Campaigns
Campaigns insert promoted videos into the recommendation carousel before organic results. Campaign videos are assigned reason: "featured".
| Field | Type | Default | Description |
|---|---|---|---|
campaign_id |
string | — | Unique campaign identifier. |
status |
string | active |
active or archived. Only active campaigns within their date range are included. |
video_id |
string | — | The video ID to feature in recommendations. |
frequency_percentage |
decimal | — | Probability the campaign appears in a request (when no carousel_position is set). Range: 0.0–100.0. |
view_goal |
integer | null | null | Target impression count. The campaign is skipped once this goal is reached. |
start_date |
datetime | — | ISO 8601. Campaign becomes active from this date. |
end_date |
datetime | — | ISO 8601. Must be after start_date. |
carousel_position |
integer | null | null | 0-indexed position in the carousel. When set, the campaign appears at this exact slot instead of using random frequency. |
Validation Rules
timeframe_daysmust be between 1 and 730.min_video_durationcannot exceedmax_video_duration.- All constraints within a single lock-off must share the same
type(alltagor allcustom_field). end_datemust be afterstart_datefor both lock-offs and campaigns.frequency_percentagemust be between 0.0 and 100.0.- Each lock-off must have at least one constraint.