How the plugin platform works

A plugin is a standalone frontend JavaScript application that runs in an iframe inside the Tracker app. An SDK is provided for its development. Using React is considered a priority. There is also a vanilla JavaScript library that allows you to avoid being tied to React.

The platform covers the entire lifecycle of plugins: it provides tools for development and debugging, versioning, and publishing, as well as a repository for storing plugins. Administrators can install, update, and disable plugins, controlling their availability to users and contexts.

Running a plugin in an iframe

The interface part of plugins is static content hosted on Tracker's servers. It runs in an isolated iframe on a cookieless domain, where almost everything is forbidden, including any network requests. Therefore, all communication with Yandex services, the Tracker public API, and the outside world is done through the SDK.

SDK

Interacting with Tracker is done using the SDK, which is connected as a library. The SDK provides methods for interaction at the user interface level, methods for working with the Tracker public API, and a plugin data storage.

The SDK is delivered as two npm packages:

  • core — API client and basic integration primitives (JS/TS).
  • react — React wrappers over core for easy UI development.

CLI

CLI is a command-line utility in the form of an NPM package that covers the entire plugin lifecycle: creation, debugging, validation, and publishing.

UI components

A library of UI components in Tracker's style, available for use in plugins.

Manifest

The manifest is a manifest.json file located in the plugin's root directory. The manifest describes the plugin's metadata.

Main fields:

  • id — unique identifier of the plugin. Lowercase Latin letters, numbers, and hyphens are allowed. The maximum length is 63 characters. To highlight a scope, which is a unifying attribute for your plugins, use two hyphens. For example, yandex-tracker--import-csv.

  • version — version of your plugin.

  • permissionsrequired permissions. A granted permission is necessary but not sufficient to perform any action, because the rights of the plugin user are also taken into account.

  • slots — integration points of the plugin into the Tracker interface. More about slots.

    A plugin can be integrated into multiple interface locations at the same time. For each integration location, you can specify different entry points to the plugin in the entrypoint parameter. The slot object also contains a title parameter, which holds the name of the button or menu item that will be used to invoke the plugin.

    For each slot, you must specify the contextLevel parameter, which determines the level of context available to the plugin:

    • basic — the context only contains the current entity ID and basic metadata. Suitable for most plugins that do not need the full entity data.
    • full — full context with live entity data, for example, all issue fields. Use this level only if the plugin really needs the full data.
    "slots": {
      "tracker": {
        "issue.action": [
          {
            "entrypoint": "index.html",
            "contextLevel": "basic",
            "title": {
              "ru": "Мой плагин",
              "en": "My Plugin"
            }
          }
        ]
      }
    }
    
  • categories — list of plugin categories to display in the catalog. For the full list of available values, see the How to prepare a plugin for publishing page.

  • externalHost — allows you to specify an external domain where the plugin interface will open. This method is not recommended and requires explicit approval from the Tracker team.

The manifest also currently contains fields that will be displayed to users in the plugin installation interface: author, support, keywords, whatsnew, description, name.

Manifest information for AI

When creating a plugin via CLI, a JSON schema will be created next to the manifest file. If the AI has issues working with the manifest, you can explicitly point to this file.

Permissions

There are 4 categories of permissions:

  • data — permissions for working with data. They have the format SERVICE:DOMAIN:ACTION, for example, tracker:issues:write is a write permission for issues in Tracker. The domain is determined by the first part of the path in the REST API.
  • device — permissions for accessing the microphone, camera, or audio.
  • ui — permissions for certain actions with the interface. For example, popup — showing a pop-up window.
  • external — permissions for access outside Tracker.

Access level

A granted permission is necessary but not sufficient to perform any action, because all actions are performed on behalf of and with the rights of the current user.

Plugin data storage

The platform provides a unified plugin data storage and an API for working with it, which supports two modes:

  • Contextual storage [Coming soon] — data is linked to a specific Tracker entity and a granularity level (organization, user, queue, portfolio, project, issue, issue-comment). This is suitable for settings and states that depend on an organization, user, queue, or specific issue. The storage context does not have to match the plugin installation context.

  • Key-value mode — data is stored as key → value pairs in the plugin's namespace. This is suitable for simple configurations and service data where quick access by key is more important than linking to a domain entity.

In both modes, the API covers reading, writing, updating, and deleting data, supports concurrent change control (versioning/optimistic locking), and stores pluginVersion for managed data migrations when the plugin is updated.

For more information about the current storage implementation and its API, see the Plugin data storage section.

Access to external APIs (OAuth and Proxy)

The platform provides a secure mechanism for integrations with external services: a generic proxy for making HTTP requests to the outside and a secret vault for storing OAuth tokens.

  • Generic proxy — a single endpoint for calling external APIs on behalf of the plugin. The plugin sends the request parameters: URL, method, headers, body. The platform executes the request on the backend and returns the result. Access is restricted declaratively (domain allowlist). The platform blocks unsafe destinations (private networks/localhost, unauthorized redirects), runs audits, and applies rate limits per pluginId and organization.

  • OAuth and Secret vault — the platform takes over the OAuth flow and token storage: access/refresh tokens are saved in the secret vault and never end up in the plugin's iframe. Tokens are supported in two contexts: user (personal) and organization (shared across the organization, created by the administrator). During proxy requests, the platform automatically inserts the appropriate token, and upon expiration, it either performs a refresh on the backend or signals the need for re-authorization.

For more information on how to call external APIs from a plugin, see the External APIs section.

Integration points (slots)

The location where the plugin will be opened, as well as the mechanism for invoking it (such as a button or as part of a form), is determined by the slot. The slot is specified in the manifest.

Available slots and details of their use are described in the Integration points section.

Plugin launch context

The plugin launch context is determined by the slot it is in and contains the following information:

  • Current host theme
  • Current host language
  • Slot context — data from the environment of the page where the plugin is running. For example, in the issue.action slot, information about the open issue will be returned. The context format is as close to the public API types as possible.

Slot context levels

The context level is set by the contextLevel parameter in the slot description in manifest.json and determines what data will be available to the plugin via useTrackerPluginContext.

basic

Only the current entity ID and basic metadata are available:

type BasicContext = {
    /** Current entity ID */
    entityId: string;
    /** Additional basic information about the entity.
     *  For example, for a comment, this will contain the parent issue ID. */
    entityMeta?: Record<string, string>;
};

Use basic if the plugin only needs to know the entity ID — this is a lighter option without unnecessary overhead.

full

Full context with live entity data. The format matches the public API types. For example, for the issue.action slot, it's the full Issue object. The data is up to date as of the moment the plugin is opened.

Use full only if the plugin really needs the full entity data.

Choosing a context level

Request only the context level that the plugin actually needs. If you don't need full entity data, use basic.