Skip to end of metadata
Go to start of metadata

Deep linking is the ability to launch the channel and go directly to a piece of content.  Deep linking is used by multiple places in the Roku OS to communicate with your channel.  All public Roku channels are now required to implement deep linking in order to pass certification.  Channels are required to implement it as per this documentation.  

Implementing Deep Linking in a Channel

Deep linking is implemented by sending parameters to the function main().   These launch arguments are passed in an associate array similar to argc in C.   The channel is responsible for parsing those parameters and doing the appropriate action or in the case of an error detecting it and going to the channel's home screen.  Crashing from an invalid deep link will cause you to fail certification. 

Accepting deep linking parameters in Main()

The first step is to modify the Main method to accept the deep linking parameters in BrightScript.  You can name it what you like but in the documentation, we always call it "args"

Function Main (args as Dynamic) as Void

Ad parameter

The first thing you want to do in your channel is parse args.  This first stanza is not required it is just a good idea.   It has nothing to do with deep linking.   You want to know if your channel was launched from an Ad and if so you want to record that fact.   This is fast and independent of all other code so do it first.

if (args.reason = “ad”) then
    if (args.refmarker <> invalid) then
    end if
end if
  • Args.reason - is always there.  It states why the channel was launched.
  • Args.refmarker - almost always will be there.  It is passed when the channel is launched from an ad. This parameter can be used to determine which ad launched the channel.
  • fireAdBeacon() - is a function for any tracking beacons that need to be fired.
    • Note: This is a function that the developer has to write. It is not a Roku SDK function

Am I deep linking or is it just a normal channel launch?

The next thing to do is determine if the channel is being deep linked to.   If it is then args.ContentID and args.MediaType will both be not invalid if you are deep linking.   If either of them are invalid then it is a normal channel launch and both can be safely ignored.

if (args.ContentId <> invalid) and (args.MediaType <> invalid)
end if

Next what kind of deep link are you doing?

You deep link to pieces of content. We break content into types in our system. The type of content that is being deep linked to is passed in via args.MediaType. The required behavior is dependent on args.MediaType.

MediaType must be one of the following values:

MediaTypeContentIDRequired Behavior
"movie"Movie to be playedGo to play the content directly. If the content is paywalled or the user is not authenticated you can redirect to the appropriate screen. The user should be able to play content directly after the required action is performed.
"episode"Episode to be played
"short-form"Item to be played
"season"ContentId of an episode in the seasonGo to the episodic picker screen for this season. Select the episode who's ContentId was passed in. Do not autoplay the content.

If you believe your content doesn't fall within a particular MediaType, use special.

I don't have all of these content!

If you don't have a particular form of content you don't have to implement deep linking for that. For example, a channel which is all speeches would not have movies or seasons. In that case, I would use "short-form". In general, try to implement "movies" or " season" first. Those are what is currently used in Roku Search.

More pseudo code :

if (args.ContentId <> invalid) and (args.MediaType <> invalid)
   if (args.mediaType = “movie” ) 
      if (movie_is_free(args.ContentId)
          doSpringBoard(ContentID, Screen)
          doPlayMedia(ContentID, Screen)
   else if (args.mediaType = “short form” or args.mediaType = “Live” or mediaType = “episode”) then
      doplayMedia(ContentID, Screen)
   else if (args.MediaType = "season")
      doEpisodicPicker(ContentID, Screen)
    ' Always print an error message.  Don't fail silently
    print “Unknown media type “, args.mediaType
end if

So what is in this ContentId?

The contents of ContentId is a defined by the channel.   As far as Roku is concerned it is just a string less than 255 characters long.   The only restriction we put on it is that it has to be passable as a command line argument in a curl command.   So no "&" characters.   Channels frequently will send multiple values in the ContentId and delimit them with "|".    There is more information about using curl below.

Is the user authenticated?

Something to consider when designing this flow is what to do about unauthenticated users.   Users can deep link to the channel even when the channel is not installed.   This happens via Roku global search and when it happens the system will prompt the user to install the channel before continuing with the deep link.  This means that the first time your channel is launched it is a deep link to a particular piece of content.

How to test your deep link code

We use the ECP commands to test deep linking.   ECP is basically a pseudo web server built into the device.   Here is more information about ECP.   The curl command below does an http post to the Roku at IP address   It launches the side loaded app ("dev") and it passes the ContentID of 1234 and the MediaType of season.   Please note Roku Associative Arrays are not case sensitive so "args[MediaType]" is the same as "args.mediatype" :

curl -d '' ''

Another way to test deep linking is with the deep linking tester app. 

Here is the install link for our old test tools for Luddites like the author: 


  • No labels