Video Sitemap Generator

This sample demonstrates how you can generate a video sitemap using the CMS API.

Sample app

Source code

Find all the code associated with this sample in this GitHub repository.

Sample app

See the Pen CMS API Sample: Video Sitemap Generator by Brightcove Learning Services (@rcrooks1969) on CodePen.

Introduction

Before using this app, you should read Making Your Video Content Indexable to get a better understanding of the purpose of video sitemaps and strategies for automating the generation of them using the CMS API. Generating the XML for the sitemap is fairly straightforward. The biggest challenge is that you need to include a unique URL for each video, and the CMS API does not have automatic access to this information. To overcome this, there are a couple of things you can do:

  1. Add the URL where the video is published to the video metadata. The simplest way to do this would be to create a custom metadata field to store the URL in.
  2. Host the videos on a single page, using a URL parameter to specify the video id or reference_id that custom JavaScript in the page will use to load the video into the player.

    There are various ways to get the value of a specific URL parameter for the page. Below is a function that we use in some of our sample apps:

                /**
                 * gets value of a URL param on current page URL if exists
                 * @param {string} name the param you want the value of
                 * @return {string} result value of param if exists or null
                 */
                function getURLparam(name) {
                    var regex,
                        results;
                    name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
                    regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
                    results = regex.exec(location.search);
                    return results === null ? null : decodeURIComponent(results[1].replace(/\+/g, " "));
                }

    Once you have the id or reference_id, you need to add it to the player. How you do that will depend on whether you are using the standard (iframe) or advanced (in-page) player embed code. Probably the simplest and safest thing to do is to load the player dynamically (or not, if for some reason the URL param with the id is not present).

    An example of a single page of HTML that can be used for this purpose is document in the Single page section below.

The sample app below allows you to use either method - you just have to tell it which by entering information into the appropriate fields.

Notes on the sample app:

  1. The app makes a request to the Analytics API to get the all-time video views, so if the client credentials you provide do not include permissions for the Analytics API, the app will fail.
  2. The maximum number of videos that can be included is 50,000 and there is also a 50mb limit to the file size, which you might hit with fewer than 50,000 videos. If you have more videos than that to include, you will have to split them into multiple sitemaps and add a sitemap index file. See Google's sitemap documentation for more information.
  3. The sitemap generated by the sample app does not include some of the optional tags for videos (see the Google doc referenced above for information on them). If you would like to include these, you can take the code from this app and create a modified version. There are comments in the JavaScript and HTML code to indicate what you would need to do.
    Optional Tags Included or Not
    Tags Included Tags Not Included
    • player_loc
    • duration
    • expiration_date (if applicable)
    • view_count
    • publication_date
    • family_friendly
    • (geo) restriction (if applicable)
    • content_loc
    • rating
    • platform
    • price
    • requires_subscription
    • uploader
    • live
    • tag
    • category
    • gallery_loc
  4. Videos will be skipped if they do not meet necessary conditions, as follows:
    • If you are storing the video page URL in a custom field, any video that does not have a value for that custom field
    • If you are using a single page to host your videos, and using the reference_id to include them, and the video lacks a reference_id
    • The video has no thumbnail image
    • The video has no MP4 rendition
    • The video is inactive
    • The video is scheduled to start at a future date
    • The video was scheduled to end prior to the current date

    Note that for any video that is skipped, I log a message to the browser Console indicating the reason and the video id.

Finally, if you want to validate your sitemap after you generate it, there are several free tools on the web for doing so - for example:

Free Sitemap Validator

Get credentials

To use the CMS API you will need proper credentials.

The easiest way to get credentials in most cases is through the Studio Admin API Authentication section (requires admin permissions on your account). See Managing API Authentication Credentials for details. In most cases, you probably just want to get permissions for all CMS API operation:

CMS API Permissions
CMS API Permissions

If the permissions you need are not available in Studio, or if you prefer to get them directly from the OAuth API, use your choice of the Get Client Credentials documents listed below. Whichever option you choose, you will need to ask for the correct operation permissions. The following can be used with cURL, Postman, or our online app to get all permissions for the CMS API:

              "operations": [
                "video-cloud/video/all",
                "video-cloud/playlist/all",
                "video-cloud/sharing-relationships/all",
                "video-cloud/notifications/all"
                "video-cloud/analytics/read"
              ]

Using the CodePen

Here are some tips to effectively use the above CodePen:

  • Toggle the actual display of the player by clicking the Result button.
  • Click the HTML/CSS/JS buttons to display ONE of the code types.
  • Click Edit on CodePen in the upper right corner to fork this CodePen into your own account.
  • Find all the code associated with this sample in this GitHub repository.

Single page

As mentioned above, you can create an HTML page that can be used for the location of every video. The app will alter the URL for the page by using a query parameter that defines the video ID the page should use. For instance, the app will generate JSON that contains location URLs similar to the following for the location of the video pages:

            <loc>
                <![CDATA[https://my.site.net/videos.html?videoId=5984663997001]]>
            </loc>
            ...
            <loc>
                <![CDATA[https://my.site.net/videos.html?videoId=5982130568001]]>
            </loc>

Note that only the video ID is changing.

The actual HTML page reads the videoId URL parameter then dynamically generates a player using the video ID obtained from the URL. The entire HTML page appears as follows:

            <!doctype html>
            <html>
            
            <head>
              <meta charset="UTF-8">
              <title>Load Player Dynamically from URL Param</title>
              <!-- Page styles -->
              <style>
                .video-js {
                  width: 640px;
                  height: 360px;
                }
              </style>
            </head>
            
            <body>
              <div id="placeHolder"></div>
              <!-- custom script -->
              <script type="text/JavaScript">
                var myPlayer,
                  playerHTML,
                  playerData = {},
                  theURLParam = '',
                  // Set the account ID to your account
                  myAccountId = '1507807800001';
            
                 // Read URL param for video ID
                theURLParam = geturlparam('videoId');
            
                // Assign data for the player instantiation
                playerData = {
                  'accountId': myAccountId,
                  'playerId': 'default',
                  'videoId': theURLParam
                };
            
                // Call function that builds player
                addPlayer();
            
                /**
                 * gets value of a url param on current page url if exists
                 * @param {string} name the param you want the value of
                 * @return {string} result value of param if exists or null
                 */
                function geturlparam(name) {
                  var regex,
                    results;
                  name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
                  regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
                  results = regex.exec(location.search);
                  return results === null ? null : decodeURIComponent(results[1].replace(/\+/g, " "));
                };
            
                // Dynamically adds player to page
                function addPlayer() {
                  // Dynamically build the player video element
                  playerHTML = '<video-js id=\"myPlayerID\" data-video-id=\"' + playerData.videoId + '\"  data-account=\"' + playerData.accountId + '\" data-player=\"' + playerData.playerId + '\" data-embed=\"default\" class=\"video-js\" controls></video-js>';
                  // Inject the player code into the DOM
                  document.getElementById('placeHolder').innerHTML = playerHTML;
                  // Add and execute the player script tag
                  var s = document.createElement('script');
                  s.src = "https://players.brightcove.net/" + playerData.accountId + "/" + playerData.playerId + "_default/index.min.js";
                  document.body.appendChild(s);
                  s.onload = callback;
                }
            
                 // Initialize the player and start the video
                function callback() {
                  myPlayer = bc('myPlayerID');
                  // Can also use the following to assign a player instance to the variable if you choose not to use IDs for elements directly
                  // myPlayer = bc(document.getElementById('myPlayerID'));
                  myPlayer.on('loadedmetadata', function () {
                    // Mute the audio track, if there is one, so video will autoplay on button click
                    myPlayer.muted(true);
                    myPlayer.play();
                  })
                }
              </script>
            </body>
            
            </html>

You will have to put in your account number. For a full explanation of the code, see the Brightcove Player Sample: Loading the Player Dynamically document.

Proxy code

In order to build your own version the sample app on this page, you must create and host your own proxy. (The proxies used by Brightcove Learning Services only accept requests from Brightcove domains.) A sample proxy, very similar to the one we use, but without the checks that block requests from non-Brightcove domains, can be found in this GitHub repository. You will also find basic instructions for using it there, and a more elaborate guide to building apps around the proxy in Using the REST APIs.