Resources

Extensions Guide

Introduction

This guide is for developers of Twitch Extensions, which allow broadcasters to embed interactive, custom, third-party content on their channel pages. Extensions installed and activated by a broadcaster are automatically visible to any viewer who goes to the broadcaster’s channel page using a desktop Web browser. Viewers can see details about the extension and report an extension for bad behavior.

Broadcasters can browse and install extensions on their Dashboard’s Extension Manager tab. They can find extensions, add/remove them on their channels, and activate/deactivate them.

Installing an extension on a channel does not make it active on the channel page. To do that, after broadcasters install an extension, they configure it (if required by the developer), then activate it to make it visible to all viewers.

Getting Started

Read Required Technical Background. Understanding this information is a prerequisite to developing extensions successfully. We strongly recommend you do not try to develop extensions without learning what is in this section.

Complete the mandatory extension onboarding process. You must be onboarded before you can create extensions. See the Extensions Onboarding Guide.

Required Technical Background

Important: Please read this entire section before you start designing and developing an extension.

Types of Extensions

There are two types of extensions:

A panel extension appears in the panel area below the video player. Panel extensions remain active even when the channel is not live.

A video-overlay extension renders on top of the video player as a transparent overlay. This type of extension is viewable only when the channel is live.

Extension Life Cycle

Each version of your extension is managed independently in the Extensions section of the developer site. For each version, the Version Status tab allows you to control the lifecycle of your extension.

Every version of every extension begins in Local Test. While a version is in Local Test, all assets (HTML, JavaScript, CSS, images, fonts, etc.) are served from the defined testing base URI.

When the locally-hosted test version is satisfactory, the developer transitions it to Hosted Test. This uploads all extension assets to the Twitch CDN, allowing the developer to ensure that the extension still works when served from Twitch. Some sanity checks are performed on upload, such as making sure icons and screenshots are appropriately sized. While in either Local Test or Hosted Test, extensions are visible only to a developer-provided list of test accounts and a small subset of Twitch staff.

Once the hosted test is complete, the developer can submit the extension for Review. The developer can submit the extension for review as many times as desired, but only one version of an extension can be in review at a time. Once a version is submitted, the only way to change it is to put the extension back into Hosted Test and upload the assets again. While in review, all test accounts can continue to test the extension as before.

After the extension is reviewed by Twitch, it is placed into one of three states:

Pending Action indicates that revisions are required. Using the provided author email address, the developer is contacted and told the reason(s) the extension was not approved. The developer can then take the extension back to a Test state, iterate on the issues, and re-submit the extension for review. No new version needs to be created.

Rejected indicates that Twitch feels the extension is inappropriate and will not be accepted under any circumstances. This causes a permanent revocation of the extension’s Client ID (a unique identifier). Rejected is a permanent, terminal state.

Accepted causes developers to be notified that they can make the extension live at any time. Accepted extensions may be transitioned back to a Test state if necessary, but this incurs another full review cycle.

To go live, the developer clicks Release on the version that was Accepted. It then becomes publicly visible and can no longer be updated, only replaced with a new version. When a new version is Released, any previous released version is transitioned to Deprecated, and any installations of that extension are immediately upgraded.

When a new version is Released, developers should:

Be aware that some viewers or broadcasters may be using the old version at that very moment.

Ensure that their Extension Backend Service (EBS) can handle traffic from older versions that have not yet been refreshed.

Components of Extensions

Each extension comprises these components:

An HTML/JavaScript front end for the broadcaster's installation configuration. This is rendered as part of the normal extension installation flow, permitting one-time or infrequent setup.

An HTML/JavaScript front end for the viewer’s experience. This is rendered in an iframe (inline frame) on the channel page.

An optional HTML/JavaScript front end for the broadcaster’s live experience. This is rendered in an iframe on the broadcaster’s live dashboard page. This allows the broadcaster to perform privileged operations while live (e.g., creating a new poll).

An optional EBS, a Web-service backend which stores data or state and communicates with the front ends, by either receiving AJAX requests or using Twitch's PubSub architecture to broadcast to all viewers.

Architecture Overview

Extensions are front-end iframes. Typically they communicate via AJAX with an Extension Backend Service (EBS): a Web service that is developed, deployed, and maintained by the extension developer.

While an extension is being tested, the iframe and all its assets are sourced from a URL provided by the extension developer, allowing rapid development iteration. Once the extension is ready for review by Twitch, and later in production, assets to be hosted by Twitch are copied to the Twitch CDN (Content Delivery Network) and served from there.

An extension's iframe must import the Extension Helper JavaScript file, created and hosted by Twitch, which provides methods for dealing with authentication, receiving notifications of stream properties, and listening to PubSub events. Twitch PubSub is a system that allows backend services to broadcast real-time messages to clients.

Twitch PubSub

The Twitch PubSub system provides an additional channel for your EBS to communicate with your extension. Your extension front end can use AJAX to directly call your EBS to retrieve initial state or send viewer-initiated events (like voting). PubSub is a very efficient way for the EBS to directly broadcast real-time events or provide incremental state changes to all instances of your extension.

In a typical use case, your EBS will use the Send Extension PubSub Message endpoint to broadcast messages to viewers using PubSub. Your extension front end will then use the Extension Helper to listen for incoming messages. For details, see the Extensions Reference.

JSON Web Tokens (JWTs)

When developing Twitch extensions, it’s important to fully understand how JSON Web Tokens (JWTs) provide secure communication across Twitch, a viewer’s extension, and your EBS. If you are not familiar with JWTs, visit the official site for an introduction.

Twitch Extensions uses JWTs in two contexts:

When an extension is loaded in a broadcaster’s or viewer’s browser, a JWT is signed by Twitch and provided to the Extension Helper’s onAuthorized callback. Whenever your extension communicates with your EBS, it is best practice to send the JWT and verify it using your extension’s shared secret. This allows your EBS to verify that the request was made on behalf of the viewer or broadcaster represented by the token, and it prevents malicious users from directly calling your EBS. For details about the callback, see the Extensions Reference.

When an EBS needs to call a Twitch API, it must generate, sign, and include a JWT in the header. This is known as “bearer token authentication.” By signing your own token with the shared secret, Twitch can authenticate that the API request is coming from your EBS.

The secret is base64 encoded. The secret provided to you in the Extensions dashboard is a base64-encoded string. Depending on the JWT library you use, you probably will have to decode the string before using it as a parameter to sign or verify a JWT.

Keep your secret private. While this code contains the secret as an example, we strongly recommend that you do not store your secret in your code. It is always best practice to store sensitive information such as secrets, keys, and passwords separate from code, using a dedicated secret-management system.

Authentication Tokens

The Extension Helper provides the iframe with an authentication JWT. When the iframe wants to communicate with its EBS, it sends this token in an HTTP header to the EBS. The JWT is signed by Twitch, using a secret shared between Twitch and the extension developer. The EBS can then use this secret to verify the incoming JWT and ensure that received messages are from a legitimate source. Also, the JWT itself contains reliable information about the role of the sender; e.g., whether the incoming message is from a viewer or a broadcaster.

Opaque IDs

The Extension Helper provides:

Callback functions that are invoked with context information about the channel being viewed (e.g., video resolution, latency to the broadcaster, and channel ID).

Opaque identifiers that identify viewers without revealing their Twitch identity. Using the opaque ID, developers can determine a viewer’s authenticated state. Logged-out users also have an opaque ID, but it is not guaranteed to be the same between channels or sessions.

Opaque IDs persist across all channels, and they do not change unless viewers explicitly request to rotate their identity. We encourage developers to use their EBS to store per-viewer information, using opaque IDs as keys. If your extension needs to know the viewer’s numeric Twitch ID, instructions are provided in Extension Capabilities.

An opaque ID that begins with “A” is a logged-out user and should not be persisted. It will change every time the logged-out user loads your extension.

Focus

When a viewer clicks into an extension, Twitch sends focus back to the player, to ensure that keyboard shortcuts for the player continue to work. However, if an extension asks viewers to click on a form field element (for example, "field," “select,” “textarea”) and the viewer does so, the focus stays on the form element.

The Firefox browser has a known issue that prevents these input types from capturing focus.

Creating Your Extension

Name — The name of your extension. This cannot be changed later, so double-check the spelling.

Type of Extension — Select Panel or Video Overlay.

Summary — This will be viewable by broadcasters on the extensions listings page in the Extension Manager. It should be 1-2 brief sentences describing what your extension does. To provide more detail, use the Description field.

Description — More detail than the Summary about the functions of your extension.

Author name — The full name of the extension author or organization that will receive credit on the Extension Manager. This can be changed later.

Author email — Contact information for the extension creator. This is used to contact the developer with information about the extension’s lifecycle (e.g., reject/accept notifications). Twitch will never reveal this email to anyone on the site.

Support email — Public contact information for support-related queries from broadcasters.

(Optional) Add a logo for your extension. This must be 100px x 100px. Do not use Twitch or Glitch logos. If you do not have a logo, a default logo will be assigned.

Click Create Extension to create your extension (in the Local Test stage of the extension life cycle. You will get a verification email soon after creation.

Congratulations, you've created an extension! Be sure to check your email, as you will need to verify ownership of the provided author email address.

To change your extension’s description, summary, author name, or logo, click the Settings tab after your extension is created. These fields are not version specific: they apply to all versions of the extension.

Creating Your Extension Front End

As previously defined, extensions are front-end iframes. Now that you have created your extension and defined the settings of the first version of the extension, you are ready to create the assets that will live within the iframe.

The Extensions Boilerplate

To help our developers get started developing extensions as fast as possible, we provide the Extensions Boilerplate. It provides a starting point for developing your extension and an easily deployable, local testing environment for rapid iteration.

Extension Helper Library

An extension's iframe must import the Extension Helper JavaScript file, created and hosted by Twitch. It provides methods for dealing with authentication, receiving notifications of stream properties, and listening to PubSub events. Each HTML defined in the Asset Hosting section of your extension (Viewer, Config, Live Config) must load the Extension Helper. To do so, include this line:

For details on the Extension Helper, including the callbacks and functions it provides, see the Extensions Reference.

Creating Your Extension Backend Service (EBS)

The EBS is your optional backend service that supports the extension. Your EBS can be written in whatever language you prefer. Depending on the nature of your extension, it generally should be capable of the operations described below.

Verifying the JWT

Your EBS needs to verify the communication it receives via any AJAX call from your extension. For example, it may need to enforce a policy that certain configuration tasks can be performed only by broadcasters. It also may want to ensure that a confirmed Twitch viewer, as opposed to an unidentified agent, is connecting to the EBS. As described above, the front-end iframe can obtain a signed JWT via the Extension Helper, using the onAuthorized() callback. The extension developer may then include this token as a header when making AJAX calls to the EBS.

JWT signing and validation libraries are available for many languages at https://jwt.io. They usually follow a calling interface similar to this:

verify(<jwt>, <secret>)

Where:

<jwt> is the token received from the Twitch backend via the Extension Helper and passed as a header to the EBS.

<secret> is the previously established shared secret.

The JWTs used by Twitch Extensions expire, and verification of them fails after the expiration date. The Extension Helper automatically refreshes the token and then re-calls the onAuthorized() callback. Always use the latest JWT supplied by the Extension Helper.

For the full JWT schema and detailed notes on each field, see the “JWT Schema” section of the Extensions Reference.

Signing the JWT

In addition to verifying tokens signed by the Extension Helper, your EBS needs to be able to sign new JWTs for calls to various Extensions endpoints that use JWT as the authentication mechanism. For JWTs signed by your EBS, use the following format:

{
"exp": 1502646259,
"user_id": "27419011",
"role": "external"
}

Where:

exp is the Unix epoch timestamp when the token will expire. Be sure to provide a buffer, to allow potential positive time drift.

user_id is the Twitch user ID that owns the extension.

role is set to external.

For more information about these fields, see the “JWT Schema” section of the Extensions Reference.

Sign the token using your JWT library. They usually follow a calling interface similar to this:

sign(<token>, <secret>)

Where:

<token> is the token object created in the previous step.

<secret> is the previously established shared secret.

Send your signed JWT in the request header, following this format:

Authorization: Bearer <signed JWT>

Broadcasting via PubSub

When the EBS wants to transmit realtime messages or state via PubSub, it will use the Send Extension PubSub Message endpoint. Using this endpoint, your EBS can broadcast to all viewers of a given channel or to specific user’ via a whisper.

Please be aware of the following technical guidelines for using Twitch PubSub:

1 message per second per channel

5 KB message size

These guidelines ensure the stability and scalability of our systems.

Requesting Broadcaster Abilities

If your application needs to perform actions on behalf of the broadcaster, the required OAuth scopes must be added to the Required Broadcaster Abilities, as described in Extension Capabilities.

When you create your extension, an OAuth application is automatically registered for you, with a redirect URI set to https://localhost/. Once you move your extension into hosted testing, you should set this application redirect URI to wherever your EBS is hosted.

Required Configurations

Optionally, you can require that a broadcaster successfully configures your extension before activation is allowed. This can be useful if, for example, an active extension would show a confusing error message to all viewers if misconfigured. You enforce required broadcaster configuration with a string in the Required Configurations field. The contents of this string can be whatever you want. By using a string you provide within this field, you can easily require different configurations from version to version, so that if a new version requires reconfiguration, the broadcaster will need to complete configuration before activating the new version.

Managing Extension Secrets

Each extension maintains a shared secret that is used to sign and verify JSON Web Tokens (JWT) that provide the identity of users. Use this authentication method when making Extensions API calls from your EBS (for endpoints that support it).

Twitch extension technology relies on a secret shared between the Twitch API and the EBS, to validate JWTs. This secret has an extremely long life (100 years); however, we strongly recommend that extension developers rotate the shared secret often, to better ensure its security.

JWT Roles

Both the EBS and Twitch create JWTs.

The EBS should create and sign JWTs with the external role to perform API actions. Twitch creates JWTs with other roles, so the EBS can perform user authentication. Both use cases (the external role and other roles) use the same secret. (For a discussion of roles, see the “JWT Schema” section of the Extensions Reference.)

Creating Your First Secret

Go to the Settings page of your extension in the Extensions Dashboard.

On the left panel, click Secret Keys.

Click Create New Secret to generate a new secret key. You will see the following:

Key — The secret, base64 encoded.

Active — UTC timestamp when the secret becomes active. This allows the secret to propagate through both Twitch servers and the EBS, before you use it.

Expires — Timestamp when the secret expires. This is the latest time to use this secret to verify a JWT; the JWT should be discarded after this time.

Rotating Secrets

You must rotate your secrets before they expire. To do so, create a new secret on the extension’s Settings page under Secret Keys. The table will update, showing when the previous key will expire and the new key will be active.

Because of the activation delay, you can have multiple secrets active for some (configurable) period of time. For signing, use the active secret with the latest expiration time.

Optionally, you can create new secrets with the Create Extension Secret endpoint. For a higher level of security, you can programmatically rotate secrets on a scheduled basis.

Revoking All Secrets

At any time, if your secrets are compromised, the Revoke All Secrets option can be used on the extension’s Settings page under Secret Keys. View this as a kill switch: it immediately deletes all secrets associated with a specified extension.

Testing Your Extension

After creating your extension and setting its capabilities, you are ready to begin testing and development. Extension development typically involves iterating locally over the extension and EBS, then transitioning your extension into a hosted state for additional testing and verification.

Local Test

To locally test your extension, you can use the Extensions Boilerplate or whatever you like, to act as a local Web server. Since some operations require HTTPS, you need to create and install a self-signed certificate on your system.

You can install your extension on your own channel, in the Extension Manager section of the Broadcaster Dashboard. While your extension is in Local Test or Hosted Test mode, only viewers on the testing whitelist can see it. Other viewers see your channel without any extensions.

On the Extensions Dashboard, go to the Versions tab for your extension.

On the left panel, click Version Assets.

Choose the appropriate ZIP file.

Click Upload Assets.

This copies your assets to, and begins serving them from, the Twitch CDN. In this state, all your assets are hosted on the Twitch CDN, but the review process is not started. This gives you an opportunity to test your extension while hosted on the CDN.

If there is an issue with the upload (e.g., a file could not be accessed or your images are improperly sized), you are notified by email. To get these notifications, you must have verified the author email when creating the extension. Make sure you received a verification email when you created the extension on the dashboard and you clicked on the link in the email. If you have not done this, you will not get email notifications about any file-upload issues or when your extension is approved.

Submitting Your Extension for Review

Once your extension works properly on the Twitch CDN, it is ready to be submitted for review. Before submitting, please fill out the EULA or Terms of Service URL and Privacy Policy URL fields within Version Details on the version of the extension you want to submit.

We recommend you include screenshots of your extension in action, by uploading images in the Screenshots section of the extension. Images can be PNG, JPG, or GIF. The minimum (and recommended) image size is 1024x768. Images must have a 4:3 aspect ratio. You must have at least one screenshot (and an icon) for your extension before submission.

Before submitting your extension for review, you must complete the Review Details section of the version you will submit. Pay special attention to the following fields and issues:

Name of Channel for Review — Specify the URL of the channel that you want to be used for the review process. To complete our review of your extension, we require the version under review to be fully functional and live on a Twitch channel page until it is approved. Also, if your extension requires live data to operate, please simulate the necessary data to allow our reviewers to use the full breadth of features offered by your extension.

This field is required. Your extension will be rejected unless this field contains a valid URL from the twitch.tv domain.

Failure to provide a walkthrough guide or change log may result in extended review time or rejection.

Once you’ve completed the Review Details section, you can submit your extension for review by clicking Mark In Review in the Version Status section on the version for which you have uploaded assets.

Do’s and Don’ts

To ensure that your extension is a great experience for broadcasters and viewers, Twitch has policies that you must adhere to. During the review process, we check your extension against these policies. We reject extensions that do not adhere to our policies.

A full list of policies is in Appendix B: Guidelines and Policies. The most common issues are listed below, as a guide before you enter review. To minimize review time and the possibility of rejection, follow all these steps.

Do:

Ensure that your extension has an icon and at least one screenshot that accurately represent the extension front end.

Submit human readable, non-obfuscated code.

Include the Twitch Extension Helper as your first JavaScript file.

Make sure all aspects of your extension's functionality can be accessed on your test stream during the review period.

Encourages or rewards users for visiting or taking action on a site that is not owned and operated by Twitch or Amazon.

Sells an upgraded experience off Twitch.

Sells anything on a page that can be visited by an extension link.

Uses Flash, browser extensions, or browser plug-ins.

Uses pop-up alerts in any manner.

Uses eval in your JavaScript code.

Generates Iframes within HTML files.

Render AJAX directly in the browser window.

Collect or store data on a Twitch user, except:

To create compelling benefits that both improve the Twitch user experience in your apps and are exclusive to Twitch.

To send administrative communications, such as facilitating the redemption of digital items to users or notifying an end user of updates for customer-service purposes.

To send periodic promotional materials or notifications about features and benefits of your apps that are targeted to all Twitch users (provided that you present a mechanism to allow an end user to unsubscribe to promotional communications and the primary purpose of such communications is not to promote or drive Twitch users to competing products).

As necessary to process transactions.

Making Changes

While your extension is under review, you cannot change any version assets or details. If changes are needed, revert back to the test version by clicking Return to Testing. After making the changes, upload your modified assets to the Twitch CDN, then re-submit the version for review. Note that re-submitting resets your place in the review queue.

Releasing Your Extension

Once an extension is approved, you release it for live use by clicking the Release button on the version that was approved. If a prior version of your extension already has a state of Released, the state of that version automatically is changed to Deprecated. For a given extension, only one version can be in the Released state at a time.

Managing Extension Versions

After you click Create Extension, you are placed into the Version Status section of the Versions tab. Here, you can see the state of your extension in the extension life cycle and change the state as needed. On the left navigation bar, you will see additional sections to manage your extension version; these are described below.

Version Assets

When you are ready to upload your assets to the Twitch CDN, zip up your assets and upload them in the Version Assets section. You cannot submit your extension for review until you upload the assets to Twitch's CDN. For more information, see Hosted Test.

Extension Capabilities

Each extension is unique, and Twitch has optional capabilities to maximize your extension’s potential. These are in the Extension Capabilities section.

If your extension needs to know the viewer’s numeric Twitch ID, checkmark the Request Identity Link box. Once the viewer accepts your request to share his Twitch identity, his numeric Twitch ID is provided in the Extension Helper's onAuthorized() callback function. For details about these callbacks and the JWT format, see the Extensions Reference.

You can optionally require that a broadcaster successfully configure your extension before activation is allowed. This can be useful if, for example, an active extension would show a confusing error message to all viewers if misconfigured. You enforce required broadcaster configuration with a string in the Required Configurations field. The contents of this string can be whatever you want. This is covered further in Creating Your Extension Backend Service (EBS).

If your application needs to perform actions on behalf of the broadcaster, the required OAuth scopes must be added to Required Broadcaster Abilities. Using this comma-separated list of OAuth scopes, we set up the authorize call with the specified redirect URI, so when the user accepts the scopes your application requests, we will use that redirect URI to send you the user’s token. (See the Twitch Authentication guide for a list of scopes.) This is covered further in Creating Your Extension Backend Service (EBS).

Optionally, if your extension is required to open an external URL for configuration or as a core functionality for the panel, list the URLs under Whitelisted Config URLs or Whitelisted Panel URLs. Linking to an external site for a video overlay extension is strictly prohibited.

Asset Hosting

After your extension’s initial creation, you will need to update the default paths for your assets, in the Asset Hosting section of the extension version you are editing.

Change your Testing Base URI to reflect the root URI for all assets related to this extension version. The URI must end with a forward slash. The URI is completely up to you; it need not match the version in any way. During test, the assets are served directly from this URI, so you can update your code without re-submitting anything. For more information on how to test locally, see Local Test.

The Viewer Path contains the HTML file that is shown to viewers on the channel page. This page is presented to viewers in either the panels area or the video overlay, depending on the extension's specified anchor.

The Config Path contains the HTML file that is shown to broadcasters while they are configuring the extension but before activating it within the Extension Manager. This page is displayed in an iframe with dynamic width and fixed height (720px). This should be a path relative to the testing base URI. It should be used for infrequent, install-time configuration.

The optional Live Config Path contains the HTML file that is shown to broadcasters in the Live module of the Dashboard. It is used for broadcaster actions taken while the extension is active, such as creating a new poll. It should be a path relative to the testing base URI.

Access

Add the account IDs of all accounts being used to test the extension, under Testing Accounts in the Access section. Specify a comma-separated list of account IDs (not names) which have access to this version of the extension while it is in test.

You may want to add the account IDs of specific broadcasters to the Broadcaster Whitelist. This prevents broadcasters outside the whitelist from installing the extension once it is approved. If this is empty or missing, all broadcasters can use this extension. To convert account names to account IDs, see Translating from User Names to User IDs.

If your extension has whitelisted broadcasters when you submit it for review, the approved extension will be visible only to those broadcasters. After review, changing the whitelist requires re-submission and another review cycle. So, be sure to check your whitelist before submitting your extension for review.

Updating Your Extension

To update your extension after it is released, you must create a new version of the extension and submit it for review. To create a new version, start by clicking the Versions tab within the extension you want to manage. This displays a table with all extension versions and their statuses.

Once the new version of your extension is approved, you can Release it live to broadcasters to use. This retires your previous extension, which is displayed on the bottom of the Version Status page.

Deleting Your Extension

If you decide to no longer support your extension, you can choose to delete your extension: click the Delete Extension button from the Settings section of your extension. This removes your extension from all broadcasters Extension Manager pages.

You cannot delete specific versions of your extension. Deleting an extension is irreversible.

Appendix A: Design Best Practices

Design is subjective, so we do not dictate what "good design" means on Twitch. However, there are several best practices you should consider, to ensure that your extension is a good experience for your audience. Please take these into account whenever you develop an extension.

Branding — Your extension’s branding should be clean, recognizable, and unique. In general, use your logo sparingly and use brand color to enhance your brand on Twitch. Your extension cannot include Twitch-branded elements, including the Twitch or Glitch logos.

Color — Use a limited color palette. If your extension is for a specific game, use a complimentary color palette where appropriate. For a video-overlay extension, consider how it will blend into the content behind the extension (video, game data, or other stream-overlay components). Use a key color for emphasis and calls to action. Avoid using the same colors for interactive and noninteractive elements.

Contrast and accessibility — Always provide enough contrast between colors, to ensure your designs are as accessible as possible. Avoid links on backgrounds that are of similar contrast. Consider your color-blind audience.

Layout — Use alignment and hierarchy for ease of visual scanning. Also see the "video-overlay considerations" below.

Typography — Use font weight, size, and color for emphasis. If possible, try to use a single font; using multiple fonts can make your extension feel fragmented. Instead, use font styling (bold, italic) and a limited number of font sizes. Use built-in browser fonts: they perform best and and work on all browsers. Here are some Web-safe fonts:

Extensions on mobile — Overlay and panel extensions are not supported on the Twitch mobile app or mobile website.

Panel considerations — Panel extensions are limited to 320px wide x 500px high, to avoid iframe scrolling. Within this box, try to allow 10px of inner padding for any text within your extension, for maximum readability.

Stateful feedback — Preload wherever possible, especially on overlay extensions. Overlay extensions should avoid the use of "loading" indicators, which can interfere with the viewing experience. If a panel extension needs to display a loading state, design your loading state to be as clear and concise as possible. Consider adding a loading indicator. Use status indicators to communicate updates, errors, and other statuses that your extension may require; your audience should not have to guess what is happening during a call to action.

Navigation — In general, avoid multi-layered navigation in extensions. If you must have hierarchical navigation, always provide a clear path, to let users know where they are. Ask yourself if each navigation element is necessary.

Video Overlay Design Considerations

Video-overlay extensions are meant to enhance the viewer’s experience, so be aware that each extension element covers valuable real estate.

Sizing — When designing your extension UI, take into consideration that it needs to scale and adapt when the browser and video player resize. By default, a video-overlay extension functions at all sizes while the broadcaster is live. Consider hiding your extension when the size is reduced to a point that the extension becomes non-functional.

Covering up player elements — If you have extension UI elements over the Twitch video player, interactions with those elements may not work. Here is a diagram of areas to consider when you design your video-overlay extension:

iFrame boundaries — For drag-and-drop elements, consider how your video-overlay extension will respond when a user tries to move an element outside the video player’s viewing area. Design your extension to block elements from being relocated to outside the viewing area and/or force them to "spring" back into the viewing area.

Disabling — A video-overlay extension disables itself when the broadcaster goes offline or hosts another channel. When a viewer pauses the video, the extension iframe is hidden until the viewer unpauses the video.

Player control layers — Keep in mind that your video-overlay extension will be rendered below all our video-player controls, such as pop-up menus, mouseovers, LIVE indicator, and channel information in the top left of popout/ember versions of the video player. Remember that theater mode, full screen, and embed have different UI layouts than the "normal" Twitch player.

Double-click behavior — The video player provides full-screen toggle functionality via double click. If your extension relies heavily on clicking, users may see full screen toggled back and forth, if they click fast enough. While your extension will still work, this can negatively affect the user experience.

To opt-out of this functionality, intercept the dblclick event on any elements you consider critical to your extension’s behavior, using standard JavaScript event-bubbling methods. Here is a basic code sample, to stop propagating double clicks to the video player:

We recommend you allow double clicks to propagate to the parent frame. If you need to disable double clicks for a component of your overlay extension functionality, it is best to block double-click propagation only temporarily, while input is being gathered, then restore doublec-lick propagation once input is complete.

Appendix B: Guidelines and Policies

Technical Guidelines

For released extensions, all HTML, JavaScript, and CSS files must be served from the Twitch CDN. When crafting the broadcaster’s and viewer’s HTML, JS, and CSS files that eventually will deploy to Twitch edge servers, follow the guidelines below. If you fail to do so, Twitch probably will not approve your extension.

Do not submit an extension that issues any console.log commands.

Do not use eval() statements. If you rely on libraries that use eval(), do not combine those libraries into any minified JavaScript, but instead source them separately so our reviewers can know the source of any eval() statements.

All extensions must have an icon and at least one screenshot that accurately represent the extension front end.

All extensions submitted by a given company or individual should be generated using a single Twitch account.

Commerce:

Extensions may provide differentiated experiences or functionality to broadcasters, in exchange for compensation from broadcasters. For example, tiered access to features or purchasable plugins to add functionality.

Extensions may not provide differentiated experiences to viewers in exchange for compensation from viewers, except with regard to the use of Twitch/Amazon commerce instruments.

Extensions may not transact or encourage the transacting of monetary exchange in relation to any non-Twitch/Amazon commerce instruments.

No advertising or sponsorship content (static or dynamic) may be displayed in any extension.

Off-site linking:

Video-overlay extensions may not contain links of any kind.

Panel extensions must submit a whitelist of domains requested for off-site linking.

Off-site links must be related to the extension’s core functionality.

Off-site links may not refer users to sites that deliver functionality effectively similar to that available on Twitch.tv.

Settings and configuration of extension functionality must be managed through the on-site extension configuration and live dashboard iframes.

Extensions may not encourage or reward users for consuming Twitch content on a site other than Twitch.tv.

Extensions may not request or require OAuth permissions from extension viewers.

Extensions may not encourage or facilitate users to break Twitch user terms of service, including:

No sexually explicit content.

No encouragement of violence, bullying, or hate speech.

No deceptive behavior or impersonation.

No facilitation of illegal activities.

Extensions may not use keyboard shortcuts to power functionality.

Extensions may not use Twitch branding, the Twitch logo, or the Twitch Glitch in their extension content.

Extensions may not include anything intentionally malicious or designed to circumvent Twitch security or safety precautions.

Extensions must respect intellectual property rights. The extension developer is responsible for any claims filed against intellectual property displayed by an extension. An extension may be removed until such claims are resolved.

Extensions may not use irrelevant, misleading, or excessive keywords in titles, descriptions, or metadata.

An extension listing must describe the functionality of the extension accurately and completely.

Developers may not try to manipulate an extension's placement within the extension manager or any future extension-discovery mechanism.

Extensions that provide social media are allowed, provided the core functionality of the extension does not link offsite or offer features that directly compete with Twitch/Amazon functionality and features, and it is reasonably aware to users that they could be participating on social media through the extension.

Twitch reserves the right to remove any extension, for any reason, at any time.

Content Security Policies

To ensure the security and privacy of our viewers and broadcasters, we employ content security policies. While developing, you may see a message like this in your console:

Refused to load the stylesheet 'https://somedomain.net/bad.css' because it violates the following Content Security Policy directive: "style-src 'self' https://fonts.googleapis.com".