Users prefer to watch or listen to content that they can already access, such as their existing subscription content. If Google knows what content a user can access on your app or platform, then Google can construct a better search result or response to direct the user to that content.
Identify content access requirements
You must identify the access requirement for each content package in your catalog. When you do so, consider the following questions:
- Do users need to log in to your app or platform to access the content?
Do users need a subscription?
Watch Actions only:
- Do users need a subscription from an external service provider?
- Do you offer a tiered, multi-package, or add-on subscription?
Watch Actions only: Do users need to rent or purchase the content?
Does the access requirement change over time?
Does the access requirement depend on the device location?
Access restriction types
There are two kinds of access restrictions:
Paywall type
You can restrict access to content by its paywall type. The following table details the different paywall types:
Paywall type | Example | Category |
---|---|---|
No purchase or login is required. | Crackle | nologinrequired |
The user must be logged in, but doesn't need a paid subscription. | Vudu (AVOD) | free |
The user must have an active subscription. Access is independent of the subscription tier. | Netflix |
|
The user must have an active subscription. Access is dependent on the subscription tier. | Hulu (add-ons) |
|
The content is available for a finite amount of time after the purchase. | Vudu | rental |
The content is available for an indefinite amount of time after the purchase. | Vudu | purchase |
The content is available by cable subscription. | HBO Go | externalSubscription |
Paywall type for Watch Actions
To specify the content paywall type for Watch Actions, use the
category
property in the
Action access specification:
"potentialAction": {
"@type":"WatchAction",
"target": { … },
"actionAccessibilityRequirement": {
"@type": "ActionAccessSpecification",
"category": "subscription",
"availabilityStarts": "2018-06-01T10:35:29Z",
"availabilityEnds": "2019-05-31T10:35:29Z",
"eligibleRegion": {
"@type": "Country",
"name": "US"
}
},
...
}
Paywall type for Listen Actions
To specify the content paywall type for Listen Actions, use the
category
property in the
offer object:
"potentialAction": {
"@type":"ListenAction",
"target": { … },
"expectsAcceptanceOf":{
"@type":"Offer",
"category":"subscription",
"availabilityStarts": "2018-06-01T10:35:29Z",
"availabilityEnds": "2019-05-31T10:35:29Z",
"eligibleRegion": {
"@type":"Country",
"name":"US"
}
},
...
}
Geographic area
You must specify the geographic areas where the content is available. Use one or both of the following properties:
- The
eligibleRegion
property of an Action access specification object. This property is required. - The
ineligibleRegion
property of an Action access specification object.
A user can access content if the device location is within any region that's
specified in eligibleRegion
and isn't within any region that's specified in
ineligibleRegion
.
The eligibleRegion
and ineligibleRegion
properties allow the following
values:
- A list of
Country
,City
, andState
. - A
GeoShape
object. See theGeoShape
properties section for detailed requirements. - A list of
GeoShape
objects.
If the content is available globally, use the following special value for
eligibleRegion
:
"eligibleRegion": "EARTH",
eligibleRegion use cases
The following are use-case examples of the eligibleRegion
property:
- Example 1:
eligibleRegion
with a list of countries. - Example 2:
eligibleRegion
with aGeoShape
object that contains a list of ZIP codes. - Example 3:
eligibleRegion
with aGeoShape
object that contains a list of Forward Sortation Area (FSA) codes. - Example 4:
eligibleRegion
with aGeoShape
object that contains a DMA ID. - Example 5:
eligibleRegion
with a list ofGeoShape
objects. Each contains a DMA ID. - Example 6:
ineligibleRegion
with blocked-out ZIP codes.
Example 1
eligibleRegion
with a list of countries:
"actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "subscription", "requiresSubscription": { "@type": "MediaSubscription", "@id": "http://www.example.com/north_america_network/subscription", "name": "Example Subscription", "commonTier": true }, "eligibleRegion": [ { "@type": "Country", "name": "US" }, { "@type": "Country", "name": "CA" } ] }
Example 2
eligibleRegion
with a GeoShape
object that
contains a list of ZIP codes:
"actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "subscription", "requiresSubscription": { "@type": "MediaSubscription", "@id": "http://www.example.com/local_tv_network/subscription", "name": "Example Subscription", "commonTier": true }, "eligibleRegion": { "@type": "GeoShape", "@id": "http://example.com/area1", "addressCountry": "US", "postalCode": [ "94118", "94119" ] } }
Example 3
eligibleRegion
with a GeoShape
object that
contains a list of Forward Sortation Area (FSA) codes:
"actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "subscription", "requiresSubscription": { "@type": "MediaSubscription", "@id": "http://www.example.com/local_tv_network/subscription", "name": "Example Subscription", "commonTier": true }, "eligibleRegion":{ "@type": "GeoShape", "@id": "http://example.com/area2", "addressCountry": "CA", "postalCode": [ "1A1", "K1A" ] } }
Example 4
eligibleRegion
with a GeoShape
object that
contains a DMA ID:
"actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "subscription", "requiresSubscription": { "@type": "MediaSubscription", "@id": "http://www.example.com/abcd/subscription", "name": "Example Subscription", "commonTier": true }, "eligibleRegion":{ "@type": "GeoShape", "@id": "http://example.com/area3", "addressCountry": "US", "identifier": [ { "@type": "PropertyValue", "propertyID": "DMA_ID", "value": "501" } ] } }
Example 5
eligibleRegion
with a list of GeoShape
objects.
Each contains a DMA ID:
"actionAccessibilityRequirement" : { "@type" : "ActionAccessSpecification", "eligibleRegion" : [ { "@id" : "http://example.com/dma/601", "@type" : "GeoShape", "addressCountry" : "US", "identifier" : { "@type" : "PropertyValue", "propertyID" : "DMA_ID", "value" : "601" } }, { "@id" : "http://example.com/dma/602", "@type" : "GeoShape", "addressCountry" : "US", "identifier" : { "@type" : "PropertyValue", "propertyID" : "DMA_ID", "value" : "602" } } ] }
Example 6
ineligibleRegion
with blocked-out ZIP codes:
"actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "subscription", "requiresSubscription": { "@type": "MediaSubscription", "@id": "http://www.example.com/local_tv_network/subscription", "name": "Example Subscription", "commonTier": true }, "eligibleRegion": { "@type": "Country", "name": "US" }, "ineligibleRegion": { "@type": "GeoShape", "@id": "http://example.com/area1", "addressCountry": "US", "postalCode": [ "94118", "94119" ] } }
Entitlement identifier
The entitlement identifier, entitlementId
, refers to a string that represents
access to a group of content in your media catalog. To determine whether a user
has access to your content, Google takes the following steps:
- We make an API call to your Entitlements endpoint to receive the user's entitlement identifiers.
- We look up the content's required entitlement identifiers from your Media Actions feed.
- We match a user's
entitlementId
to theidentifier
property of the media subscription object in your feed. If at least oneentitlementId
matches, we determine that the user can access the content.
Google recommends that you use the following syntax for entitlementId
:
<domain name> + colon (:) + <access level to content>
Syntax examples:
example.com:basic
example.com:premium
example.com:sports
Entitlement identifier example
MediaExampleCompany's feed specifies that Movie XYZ
requires the
example.com:basic
entitlementId
, as shown:
{ "@context": ["http://schema.org", {"@language": "en"}], "@type": "Movie", "@id": "www.example.com/movie_xyz", "url": "www.example.com/movie_xyz", "name": "Movie XYZ", "potentialAction": { "@type": "WatchAction", "target": [ … ], "actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "subscription", "requiresSubscription": { "@type": "MediaSubscription", "@id": "http://www.example.com/basic_subscription", "name": "Basic subscription", "commonTier": true ... }, ... } }, ... }
Common access use cases
The following are common access use cases:
- Free (no login required): The content is available without login, subscription, or purchase.
- Free (login required): The content requires users to be logged in but doesn't require a subscription.
- Single-tier subscription: The content requires a subscription. All subscribers can access the same content, whether movies or episodes, regardless of their subscription package.
- Multi-tier subscription: The content requires a subscription. Subscribers can access different content, whether movies or episodes, based on their subscription tier. For example, Silver versus Gold.
- Add-on subscription: The content requires a subscription. Subscribers can add premium content on top of their regular subscription.
- One-time purchase: The content can be purchased, after which the user can access it indefinitely.
- Live TV: A subscription includes access to local, national, and premium channels.
- Third-party subscription: The content requires the user to log in with their cable provider.
Free (no login required)
No login required
The content is available without login or subscription.
{ "actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "nologinrequired", "availabilityStarts": "2015-01-01T00:00Z", "availabilityEnds": "2015-12-31T00:00Z", "eligibleRegion": { "@type": "Country", "name": "US" } } }
- Set
category
tonologinrequired
. - Do not include
expectAcceptanceOf
.
Free (login required)
Login required
The content requires users to be logged in but doesn't require a subscription.
{ "actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "free", "availabilityStarts": "2015-01-01T00:00Z", "availabilityEnds": "2015-12-31T00:00Z", "eligibleRegion": { "@type": "Country", "name": "US" } } }
- Set
category
tofree
. - Do not include
expectAcceptanceOf
.
Single-tier subscription
In a single-tiered subscription model, a service provider has one subscription tier. All subscribers can access the same content, whether movies or episodes, regardless of their subscription package.
{ "actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "subscription", "availabilityStarts": "2015-01-01T00:00Z", "availabilityEnds": "2015-12-31T00:00Z", "requiresSubscription": { "@type": "MediaSubscription", "name": "Example Package", "commonTier": true, "@id": "http://www.example.com/example_package" }, "eligibleRegion": { "@type": "Country", "name": "US" } } }
Multi-tier subscription
In a tiered subscription model, a service provider has multiple subscription tiers, such as Gold, Silver, and Bronze. Users who have the upper tier subscription can access all the lower tier content. However, users who have the lower tier subscription can't access the upper tier content.
Consider the following scenario:
- Jane subscribes to the Gold tier. Your entitlements
endpoint returns the following
entitlementId
identifiers:example.com:bronze
example.com:silver
example.com:gold
- John subscribes to the Bronze tier. Your entitlements
endpoint returns the following
entitlementId
:example.com:bronze
- Your Media Actions feed describes the following requirements:
- Movie A requires
example.com:bronze
. - Movie B requires
example.com:silver
.
- Movie A requires
In this scenario, Google determines the following access levels for Jane and John:
- Both Jane and John have access to Movie A.
- Jane has access to Movie B, but John doesn't.
{ "actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "subscription", "requiresSubscription": { "@type": "MediaSubscription", "@id": "http://www.example.com/basic_subscription", "name": "Bronze", "commonTier": true ... }, ... } }
Add-on subscription
In an add-ons subscription model, a service provider allows users to expand their entitlements and add channels to a base subscription. Users can add as many channels as they want to.
Consider the following scenario:
- Jane has PRO and Sportz in addition to the
Basic subscription. Your entitlements endpoint returns the
following
entitlementId
identifiers:example.com:basic
example.com:pro
example.com:sportz
- John only has the Basic subscription. Your entitlements
endpoint returns the following
entitlementId
:example.com:basic
- Your Media Actions feed describes the following requirements:
- Movie A requires
example.com:basic
. - Movie B requires
example.com:pro
.
- Movie A requires
In this scenario, Google determines the following access levels for Jane and John:
- Both Jane and John have access to Movie A.
- Jane has access to Movie B, but John doesn't.
{ "actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "subscription", "availabilityStarts": "2015-01-01T00:00Z", "availabilityEnds": "2015-12-31T00:00Z", "eligibleRegion": { "@type": "Country", "name": "US" "requiresSubscription": [ { "@type": "MediaSubscription", "@id": "https://www.example.com/package/basic", "name": "Basic", "sameAs": "https://www.example.com/package/basic", "commonTier": true }, { "@type": "MediaSubscription", "@id": "https://www.example.com/packages/basic/pro", "name": "PRO", "sameAs": "https://www.example.com/package/pro", "identifier": "example.com:pro", "commonTier": false }, { "@type": "MediaSubscription", "@id": "https://www.example.com/package/sportz", "name": "Sportz", "sameAs": "https://www.example.com/package/sports", "identifier": "example.com:sportz", "commonTier": false } } } }
One-time purchase
Purchase
The content is available for an indefinite amount of time after the purchase.
{ "actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "purchase", "availabilityStarts": "2015-01-01T00:00Z", "availabilityEnds": "2015-12-31T00:00Z", "eligibleRegion": { "@type": "Country", "name": "US" }, "expectsAcceptanceOf": { "@type": "Offer", "price": 7.99, "priceCurrency": "USD", "seller": { "@type": "Organization", "name": "Example", "sameAs": "http://www.example.com/" } } } }
- Set
category
topurchase
. - Include
expectAcceptanceOf
inactionAccessibilityRequirement
to indicate the price of the purchase.
Rental
The content is available for a finite amount of time after the purchase.
{ "actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "rental", "availabilityStarts": "2015-01-01T00:00Z", "availabilityEnds": "2015-12-31T00:00Z", "eligibleRegion": { "@type": "Country", "name": "US" }, "expectsAcceptanceOf": { "@type": "Offer", "price": 7.99, "priceCurrency": "USD", "seller": { "@type": "Organization", "name": "Example", "sameAs": "http://www.example.com/" } } } }
- Set
category
torental
. - Include
expectAcceptanceOf
inactionAccessibilityRequirement
to indicate the price of the rental.
Live TV
In a Media Actions feed, you can restrict access to a Live TV channel or event based on the following two user conditions:
-
The user's device location
To restrict access to the TV channel, specify the area where users have access to it. This condition usually applies to local broadcast TV channels.
-
The user's account status
If access to a TV channel depends on a user's account-level setting, use entitlement identifiers to represent the restriction.
This condition usually applies to the following use-cases:
- Bundle: National channels are often included in bundles, and users choose which bundle they want to subscribe to.
- Add-on: Some premium channels require users to selectively add extra channels to their subscription.
- Regional Sports Network (RSN): RSNs are usually associated with a user's "home" location. Users can watch content on the RSN even when they travel outside of their "home" location.
Third-party subscription
Third-party subscription
The content is available to the subscribers from a different service.
{ "actionAccessibilityRequirement": { "@type": "ActionAccessSpecification", "category": "externalsubscription" "availabilityStarts": "2015-01-01T00:00Z", "availabilityEnds": "2015-12-31T00:00Z", "requiresSubscription":{ "@type": "MediaSubscription", "@id": "https://www.example.com/faq", "name": "Example", "sameAs": "https://www.example.com/faq", "authenticator": { "@type": "Organization", "name": "TVE" } }, "eligibleRegion": { "@type": "Country", "name": "US" } } }
- Add
authenticator
to indicate that a different service authenticates the subscribers. For example, HBO GO requires a subscription from the cable provider.
Common tier packages
Common tier content is available to all subscribers regardless of their
subscription package. The common tier applies to all content with the category
of subscription
. For more information on the category
property, check the
Paywall type section.
Why is a common tier package required?
Multiple Google products provide TV & movie recommendations to users; this includes Google Search, Android TV, and Google Assistant. To set user expectations about cost, Google must understand what content is available to all subscribers through use of the common tier. Google must also understand what content is available to subscribers with specific subscription packages.
Google recommends titles available on the common tier unless you support the entitlement API. The API lets Google understand the non-common-tier titles each specific user can access.
When should I create a common tier package?
A common tier package is required when your service offers content that's available to all subscribers. This includes services that offer only one package and services that offer multiple packages or add-ons.
Providers that have no content available to all subscribers don’t need to create a common tier package. An example is service providers that provide mutually exclusive content across all of their packages.
Common tier examples
The following are examples of the common tier.
Tiered Subscription
In a tiered subscription model, a service provider has multiple subscription tiers, such as Gold, Silver, and Bronze tiers. Users with the upper-tier subscription have access to all the content in the lower tiers. Users with the lower-tier subscription don’t have access to the content in the upper tier. The following image is an example of the package structure.
In the following code example, the bronze package is the common tier because all users have access to all content in that tier.
"requiresSubscription": [ { "@type": "MediaSubscription", "@id": "https://www.example.com/package/bronze", "name": "Bronze", "sameAs": "https://www.example.com/package/bronze", "commonTier": true }, { "@type": "MediaSubscription", "@id": "https://www.example.com/package/silver", "name": "Silver", "sameAs": "https://www.example.com/package/silver", "identifier": "example.com:silver", "commonTier": false }, { "@type": "MediaSubscription", "@id": "https://www.example.com/package/gold", "name": "Gold", "sameAs": "https://www.example.com/package/gold", "identifier": "example.com:gold", "commonTier": false } ],
Add ons
In an add-ons subscription model, a service provider allows users to expand their entitlements and add channels to a basic subscription. Users can add as many channels as they want. The following image is an example of the package structure.
If you have a channel available to all users and there's no cost for the channel, you can merge the package with the common tier package.
In the following code example, the basic package is the common tier because all users have access to all content in this package.
"requiresSubscription": [ { "@type": "MediaSubscription", "@id": "https://www.example.com/package/basic", "name": "Basic", "sameAs": "https://www.example.com/package/basic", "commonTier": true }, { "@type": "MediaSubscription", "@id": "https://www.example.com/packages/basic/pro", "name": "PRO", "sameAs": "https://www.example.com/package/pro", "identifier": "example.com:pro", "commonTier": false }, { "@type": "MediaSubscription", "@id": "https://www.example.com/package/sportz", "name": "Sportz", "sameAs": "https://www.example.com/package/sports", "identifier": "example.com:sportz", "commonTier": false }, { "@type": "MediaSubscription", "@id": "https://www.example.com/package/moviemax", "name": "Moviemax", "sameAs": "https://www.example.com/package/moviemax", "identifier": "example.com:moviemax", "commonTier": false } ],
Packages with content that intersects
In a content model where packages have content that intersects, a service provider sells packages that include some content from other packages. The following image is an example of the package structure.
In the following code example, the provider offers three packages where some content intersects across all of the packages. In this case, a fourth package that represents the common tier is required. It must include all content available across all three packages.
"requiresSubscription": [ { "@type": "MediaSubscription", "@id": "https://www.example.com/package/1", "name": "Package 1", "sameAs": "https://www.example.com/package/1", "identifier": "example.com:package1", "commonTier": false }, { "@type": "MediaSubscription", "@id": "https://www.example.com/package/2", "name": "Package 2", "sameAs": "https://www.example.com/package/2", "identifier": "example.com:package2", "commonTier": false }, { "@type": "MediaSubscription", "@id": "https://www.example.com/package/3", "name": "Package 3", "sameAs": "https://www.example.com/package/3", "identifier": "example.com:package3", "commonTier": false }, { "@type": "MediaSubscription", "@id": "https://www.example.com/package/common", "name": "Common Tier Package", "sameAs": "https://www.example.com/package/common", "commonTier": true } ],
Packages without content that intersects
In a content model where all of the content packages don't intersect, a service provider sells packages that include no content from other packages. The following image is an example of the package structure.
In the following example, the provider offers three packages with no content intersecting across all of the packages. No common tier package is required.
"requiresSubscription": [ { "@type": "MediaSubscription", "@id": "https://www.example.com/package/1", "name": "Package 1", "sameAs": "https://www.example.com/package/1", "identifier": "example.com:package1", "commonTier": false }, { "@type": "MediaSubscription", "@id": "https://www.example.com/package/2", "name": "Package 2", "sameAs": "https://www.example.com/package/2", "identifier": "example.com:package2", "commonTier": false }, { "@type": "MediaSubscription", "@id": "https://www.example.com/package/3", "name": "Package 3", "sameAs": "https://www.example.com/package/3", "identifier": "example.com:package3", "commonTier": false } ],
Entitlements endpoint
Use the information from this section to host an HTTPS endpoint that returns the entitlements associated with a user.
Prerequisite
Before you begin, verify that your service supports the OAuth 2.0 flow with Google.
Request
To receive a user's entitlements, Google sends a request that contains the user's OAuth token. Your endpoint needs to identify the user based on that OAuth token. See the following example:
GET /resource HTTP/1.1
Host: server.example.com
Authorization: Bearer <OAuthToken>
Response
Your endpoint needs to return a response with the following properties:
Property | |
---|---|
subscription |
Required This is a field inside the root response. |
subscription.type |
Required This property can have the following values:
|
subscription.expiration_date |
Optional The expiration date of this entitlement, in ISO 8601 format, which includes the timezone. For more details, see Expiration dates. |
entitlements |
Optional This a root property contains the |
entitlements.entitlement |
Required if access to your streaming catalog varies based on the type of subscription. This property contains the |
entitlements.expiration_date |
Optional The expiration date of this subscription, in ISO 8601 format, which includes the timezone. For more details, see Expiration dates. |
Expiration dates
There are two properties in an endpoint response that deal with expiration
dates: subscription.expiration_date
and entitlements.expiration_date
. You
can include one of them or neither, but not both. Which one you use depends on
your subscription model.
Subscription model | |
---|---|
Access to your streaming catalog is the same for all subscribers. | Because you don't need to specify the entitlements
property, specify subscription.expiration_date . |
Access to your streaming catalog varies based on the details of a user's subscription. |
If your subscription model has multiple tiers or add-ons that expire over time, do one of the following:
|
Example responses
The following are example responses of different subscription states:
- Active subscription
- Active subscription with an expiration date
- No subscription
- Active subscriptions to multiple tiers or add-ons
Active subscription
Active subscription
A user has an active subscription to example.com. In this case, all subscribers have access to your entire streaming catalog regardless of their subscription type.
{ "subscription" : { "type": "ActiveSubscription", } }
Active subscription with an expiration date
Active subscription with an expiration date
A user has an active subscription to example.com, and the subscription has an expiration date. In this case, all subscribers have access to your entire streaming catalog regardless of their subscription type.
{ "subscription" : { "type": "ActiveSubscription", "expiration_date": "2019-11-10T10:00:00Z" } }
No subscription
No subscription
A user has no subscription to example.com.
{ "subscription" : { "type": "InactiveSubscription" } }
Active subscriptions to multiple tiers or add-ons
Active subscriptions to multiple tiers or add-ons
A user has a subscription to example.com:premium
until a certain date.
{ "subscription" : { "type": "ActiveSubscription", } "entitlements": [ { "entitlement": "example.com:premium", "expiration": "2019-11-10T10:00:00Z" } ] }
Rate limit
Google refreshes a user's entitlements information up to every six hours. To smooth out the maximum queries per second (QPS), Google distributes the queries to your endpoint evenly over time. Thus, you can estimate the expected average QPS for your endpoint with the following formula:
Expected average QPS = <total number of users> / 21,600 seconds (6 hours x 60 minutes x 60 seconds)
If you support a large number of users, Google can adjust the 6-hour interval. If necessary, contact Google to discuss the configuration.
Contact Google
When your endpoint is ready, contact Google to inform the endpoint's URL.
Action access specification properties
See the action access specification properties section for reference information.