contento-logo
Welcome to Contento! Either explore the interactive and shiny Contento explorer tool , download the GraphQL Schema or check out our visualization of Contento's most important interfaces & types

The GraphQL schema is accessible through above-mentioned link, but you can also find it in the documentation section in Contento Explorer, which contains the most up-to-date documentation on queries, types and interfaces.

Type behaviour grid

Not all these types are exposed as GraphQL types. See the Content.titleType field

TvShow KidsTvShow Single CurrentAffairs TvSeries KidsTvSeries
Typical title Go' kväll Abel & Fant En runda till Rapport Tunna blå linjen Jobbigt
Characteristics Separate episodes that do not need to be viewed in order. Latest episode broadcast is usually the most viewed A protected, predictable title to put the younger kids in front of. A stand-alone content without episodes, e.g. a movie or short film. Always the most up-to-date on a certain topic. Episodic content, intended to be watched in a specific order. It usually consists of a number of seasons, each with a number of connected episodes in them. Episodic content that should be watched in order. Newly released episodes account for most of the viewing.
Play queue
Default episode to play if no history exists Newest episode Newest episode Start video Newest episode Oldest episode Newest episode
After the user has played an episode The next more recently published episode in the episode list The next older episode in the episode list End screen recommendations The next more recently published episode in the episode list The next more recently published episode in the episode list The next more recently published episode in the episode list
After the user has played the last episode in the playback order End screen recommendation, Barnplay: Oldest episode - loops the entire title Loops back and start from the beginning, i.e. first season. End screen recommendations End screen recommendations End screen recommendations End screen recommendations
Skip-to-next No Yes No No Yes Yes
Presentation
SVT Play & Barnplay Newest first Newest first Newest first Oldest first Newest first
Episode grouping Production period or custom section Season or custom section Production period or custom section Season or custom section Season or custom section
Recommendations
Keep watching Playback order Playback order Always latest (incl. ongoing live) Playback order Playback order

Core concepts and business rules

The concept of Teaser

Svt Play consists of several views with different kinds of lists of content. These lists are called selections in Contento. A Selection consists of fields that signals how to render a certain list. It also contains the actual items to display in the list. These items are called Teasers in Contento.

Teasers can differ from one another even though they "tease" for the same thing, like for instance the same episode of a show. It all depends on the context in which aTeaser is displayed, meaning, if it is in the realm of the start page, a details page or a category page.

So why have we done this, and how should clients use it? Contento takes responsibility for the context-based-logic so that clients, across platforms, can render any list regardless of where, without having to think about context or additional fields other than those that come with a Teaser. This in return has a positive impact on the ongoing work on harmonizing platforms.

It is worth mentioning that the field item is a reference to the actual underlying data item, for example an Episode or a TvSeries or a Clip. Clients should not have to use this reference to render the list-item, but it can be used for error investigations or to test different concepts.

To explore this further please use the contento explorer . You can for example try the startForSvtPlay query which returns selections containing items that are teasers. There you can explore all fields that exists on a Teaser. You can also explore the documentation inside Contento explorer.

How teasers can differ depending on contexts

To visualize how a teaser for the same episode can be different in different contexts we here have a real example with screenshots of the same episode of Julkalendern placed in selections on three different views. Here you can see that the image, heading and subheading differs in the different contexts even though it´s the same episode being teased for.

The start page

startpage_teaser

The details page

detailspage_teaser

The category page

categorypage_teaser

KidsTvShow

The KidsTvShow is the youngest sibling to TvShow, TvSeries and Single. As stated in the type behaviour grid above, this type of content is aimed for younger kids. It is divided into seasons, where episodes are suggested to be viewed in reverse order (compared to tv series, e.g. the same order as for a tv shows). A looping logic can be applied to kids tv shows when creating a play queue for them.

Analytics Identifiers

Contento provides analytics data for clients to use for click and impression tracking. Clients can access this data through two formats: a structured map or a raw JSON field. Contento strives to remove all client side logic for analytics data. Clients should pass all the provided key-value pairs in the analytics objects to the tracking backends.

Example:

startForSvtPlay{
  analytics{
    map{
      ... on StringAnalyticsValue{
        key
        stringValue
      }
      ... on NumericAnalyticsValue{
        key
        numericValue
      }
    }
    json
  }
}
This query yields the analytics data in the following format:
 "analytics": {
    "map": [
      {
        "key": "viewId",
        "stringValue": "start"
      },
      {
        "key": "viewType",
        "stringValue": "start"
      }
    ],
    "json": {
      "viewId": "start",
      "viewType": "start"
    }
  }
                        

Merging Analytics Data

Contento delivers analytics data at various levels within the graph structure. To ensure a comprehensive understanding of user interactions, it is crucial for clients to merge analytics objects from all levels. However, it is important to note that some levels contain analytics data intended exclusively for that particular level. Such data should not be used in lower levels. To manage this selective merging process, the mergeable flag has been implemented in the analytics object. Clients should merge an analytics object into lower levels only if the mergeable flag is set to true. This flag serves as an indicator of whether the data is intended for broader use or if it should remain confined to its original level.

In the example below the client should not send the superhero.analytics data if a user clicks on a teaser in the superhero.selection.items list as indicated by the mergable flag.
startForSvtPlay{
  analytics{
    mergeable # true
    json
  }
  modules{
    items{
      analytics{
        mergeable # true
        json
      }
      superhero{
        analytics{
          mergeable # false
          json
        }
        selection{
          items{
            analytics{
              mergeable # false
              json
            }
          }
        }
      }
    }
  }
}
                 

Episode names

The episode names are decided by a set of rules, in the following priority order. Meaning, if rule #1 applies, don't continue checking rule #2 and so on. If the play content is:
  1. a single: The episode name == alternativeProgramTitle if present, otherwise programTitle (e.g. Trumped!)*
  2. episodic AND it has an official episode title : The episode name == X. officialEpisodeTitle (e.g. 1. Kul med gitarr)
  3. episodic: The episode name == Avsnitt X (e.g. Avsnitt 1)
  4. NOT episodic , NOT time focused, BUT there's an official episode title present: The episode name == officialEpisodeTitle (e.g. Helena Bergström)
  5. NOT episodic BUT time focused AND yesterday/today/tomorrow: The episode name == yesterday|today|tomorrow time (e.g. Igår 21:00)
  6. NOT episodic BUT time focused AND NOT yesterday/today/tomorrow: The episode name == Day date time (e.g. Fre 13 jan 21:00)
  7. a case where none of the rules above apply: The episode name == Avsnitt X (e.g. Avsnitt 2)
* = The alternativeProgramTitle logic for singles is to handle titles such as "Dox", "Dokument Inifrån", "Världens historia" etc. where we don't want to add "Dox: Apollo 11 - de första stegen på månen" on SVT Play

Image selection logic

Images contains wide, portrait, cleanWide, cleanPortrait and logotype. All images are populated with data from Edit. The logic for these are:
  • wide: Use by most clients and contains keyart if present. If no keyart wide is present, the fallback is cleanWide, screenCapture, parent titles wide image or image missing image.
  • portrait: Use by most clients for images in portrait mode and contains keyart if present. If no keyart portrait is present, the fallback is cleanPortrait, parent titles portrait image, wide, cleanWide, screenCapture or image missing image.
  • cleanWide: Used for wide images without keyart. If no cleanWide is present, the fallback is wide, screenCapture, parent titles cleanWide image or image missing image.
  • cleanPortrait: Used for portrait images without keyart. If no cleanPortrait is present, the fallback is portrait, parent titles cleanPortrait image, wide, cleanWide, screenCapture, or image missing image.
  • logotype: Used for logotypes. If no logotype is present it is null.
NOTE! ⚽️ The screenCapture fallback above is only set when their is a live sports episode. The editorial tag "Direktsänd sport" is used to select these episodes.

Understanding Start Page Modules

As of the spring 2024 we introduced the concept of "Modules" on the start page. The "Modules" concept allows for a versatile arrangement of content sections, ranging from featured shows to surveys, enhancing navigation and user engagement.

Overview of Modules

The Start Page is composed of various modules, each serving a unique purpose. You'll find a diverse mix of content including a prominently featured show, interactive elements like surveys, and even breaking news sections. Below is a breakdown of the current module types:

  • Breaking: Breaking News! If there is a breaking news event, this module will replace the superhero/hero and will be shown as the first item of the Start Page
  • Superhero: The most prominent show on the Start Page, displayed in a large and prominent manner along with associated display window.
  • Hero: Similar to Superhero but less prominent. Includes associated display window as well.
  • Selection: A curated list of teasers for user exploration.
  • Favorites (Min lista): A personalized selection of the user's favorite content.
  • Continue watching: The continue watching selection (Fortsätt titta). If you don't use this field it will be included in the selection field instead.
  • Survey: Surveys for the start page. If you include this field you also need to specify the platform parameter and surveysToExclude for this field. If a survey is present for this platform and ab-test is connected to active survey, and not excluded by parameter, it will be returned in this module.
  • Login promotion: The login prompt for the start page. If you don't use this field, or if the user is already logged in, the login prompt will not be returned. If the client has pressed the "No" button. Please exclude this in the query using:
    
        loginPromotion @include(if: $showLoginPromotion) {
            heading
            (...)
        }
                            
  • Login slurp promotion: Promotion to prompt the user to add his/her local history to an SVT Play account. If the client already has uploaded local history to the account or has pressed the "No" button. Please exclude this in the query using:
    
        slurpPromotion @include(if: $showSlurpPromotion) {
            heading
            (...)
        }
                            
  • Push notification permission: Push notification permission info, used by mobile clients. E.g. "Missa aldrig en bra serie! Aktivera push-notiser för att få tips... ". If a client already has accepted push notification or denied the CTA. Please exclude this in the query using:
    
        pushNotificationPermission @include(if: $showPushNotificationPermission) {
            heading
            (...)
        }
                            

Sample Start Page Query

A basic query for a Start Page might look as follows, demonstrating how modules can be queried:

                    {
                      startForSvtPlay {
                        modules {
                          items {
                            breaking {
                              current {
                                heading
                              }
                            }
                            superhero {
                                heading
                            }
                            hero {
                              heading
                            }
                            favorites {
                              name
                              items {
                                heading
                              }
                            }
                            selection {
                              name
                              items {
                                heading
                              }
                            }
                          }
                        }
                      }
                    }
                

Module Flexibility and Ordering

Modules are designed to be flexible and paginable, allowing for customized ordering. Currently, Hero and Superhero modules are positioned at the top, but this arrangement may evolve. The query's result depends on the included fields, and it's important to note:

  • The Breaking field is optional but recommended. Including it allows for display window selection in a Breaking module. When returned (i.e. a breaking event is happening) the first item, Superhero or Hero will be placed as the first item of the recommended list
  • The Superhero and Selection fields are mandatory.
  • The Hero field is optional. Including it allows for display window selection in a Hero module, if Superhero is not present. If omitted, the display window appears in a standard selection module.
  • The Favorites field is optional and should be excluded if favorites are presented in a separate view on the platform.
  • If the Selection field is omitted from Superhero and Hero, the display window appear in the regular selections.
  • We have four so called Call to action modules which are Survey, Login promotion, Login slurp promotion and Push notification permission. Only one of these may be retured with the priority
    1. Survey
    2. Login promotion
    3. Login slurp promotion
    4. Push notification permission

This modular design future-proofs the Start Page, facilitating the introduction of new modules without disrupting existing layouts or user experiences. Only requested modules will appear, ensuring a tailored and efficient interface. With this design the pagination will work out of the box as well when modules only appear if you support them and asks for them.

Slug logic

Spaces translates to dashes. Ampersand becomes "och". Double-space translates to one dash. Digits remain intact. Special characters are removed. Some examples:
  • "Utan tvivel är man inte klok" - Tage Danielsson becomes utan-tvivel-ar-man-inte-klok-tage-danielsson
  • Go'kväll becomes gokvall
  • Guld-Greta - en hisnande kärlekshistoria becomes guld-greta-en-hisnande-karlekshistoria
  • Scott & Bailey becomes scott-och-bailey

Example queries

Here are a couple of GraphQL queries to get you started. Each of them are linked to Contento Explorer tool.

Give me all the content (tv shows, tv series, singles...) in the Humor genre

              
            query Genres {
              genres(ids: "humor") {
                selections(include: [all]) {
                  name
                  items {
                    name
                  }
                }
              }
            }
              
        

Give me the category page, divided into sections (tabs) for the Drama category/genre

              
            query Category {
              categoryPage(id: "drama") {
                id
                tabs {
                  name
                  selections {
                    items {
                      name
                    }
                  }
                }
              }
            }
              
        

Search for "Bing" and show me what type (__typename) of results I get

              
            query Search {
              search(query: "Bing") {
                id
                name
                item {
                  __typename
                }
              }
            }
        

Give me upcoming live broadcasts for Rapport

              
            {
              listables(ids: "eoVPJNz") {
                name
                associatedContent(include: upcomingLive) {
                  name
                  items {
                    name
                  }
                }
              }
            }
              
        

Show me the flat play queue for what to play after episode 7 of Bing

            
                query FlatPlayQueue {
                  playQueue(variantId: "jJbYqMj") {
                    flat {
                      name
                      item {
                        videoSvtId
                      }
                    }
                  }
                }
            
        

Give me all the names and ids, and for tv shows and series show me all episodes and their images

            
    {
      playContent {
        all {
          name
          id
          ... on TvShow {
            productionPeriods {
              name
              episodes {
                id
                name
                image {
                  id
                }
              }
            }
          }
          ... on TvSeries {
            seasons {
              number
              episodes {
                id
                name
                image {
                  id
                }
              }
            }
          }
          ... on Single {
            id
            name
            image {
              id
            }
          }
        }
      }
    }