Integrating Rutube videos into 1C-Bitrix product pages

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages

RuTube Video Integration in 1C-Bitrix Product Card

RuTube is Russian video platform increasingly used as YouTube alternative on domestic projects. Technically RuTube integration in product card differs from YouTube: different Video ID format, different embed-link structure, no public thumbnail CDN. Here's how to implement without extra dependencies.

RuTube URL Structure and Video ID

RuTube uses UUID (32 characters without dashes) as video identifier. Link formats:

  • https://rutube.ru/video/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4/ — standard URL
  • https://rutube.ru/play/embed/a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 — already embed-link

Parsing Video ID:

function parseRutubeId(string $url): ?string
{
    if (preg_match(
        '/rutube\.ru\/(?:video|play\/embed)\/([a-f0-9]{32})/',
        $url,
        $m
    )) {
        return $m[1];
    }
    return null;
}

function getRutubeEmbedUrl(string $videoId): string
{
    return 'https://rutube.ru/play/embed/' . $videoId
         . '?rel=0&showControls=1&skinColor=ff0000&startFrom=0&mute=0';
}

RuTube embed parameters much poorer than YouTube: main — rel (don't show similar videos), skinColor (player elements color in HEX without #), mute.

Storage in 1C-Bitrix Infoblock

Similar to YouTube — "String" type property with code VIDEO_RUTUBE, multiple if needed:

CIBlockProperty::Add([
    'IBLOCK_ID'     => CATALOG_IBLOCK_ID,
    'NAME'          => 'RuTube Video',
    'CODE'          => 'VIDEO_RUTUBE',
    'PROPERTY_TYPE' => 'S',
    'MULTIPLE'      => 'Y',
    'SORT'          => 210,
]);

If project uses both sources (YouTube + RuTube), can create one universal VIDEO_URL property and detect platform by URL domain.

Getting Thumbnail via API

Unlike YouTube, RuTube has no public CDN for preview by template URL. Thumbnail must be obtained via API:

GET https://rutube.ru/api/video/{VIDEO_ID}/?format=json

Response contains thumbnail_url field — direct thumbnail link. Also available title, description, duration.

function getRutubeVideoInfo(string $videoId): ?array
{
    $cacheKey = 'rutube_' . $videoId;
    $cache = \Bitrix\Main\Data\Cache::createInstance();

    if ($cache->initCache(3600 * 24, $cacheKey, '/rutube/')) {
        return $cache->getVars();
    }

    $http     = new \Bitrix\Main\Web\HttpClient();
    $response = $http->get("https://rutube.ru/api/video/{$videoId}/?format=json");

    if ($http->getStatus() !== 200) {
        return null;
    }

    $data = json_decode($response, true);
    if (empty($data['id'])) {
        return null;
    }

    $result = [
        'id'            => $data['id'],
        'title'         => $data['title'] ?? '',
        'thumbnail_url' => $data['thumbnail_url'] ?? '',
        'duration'      => $data['duration'] ?? 0,
    ];

    $cache->startDataCache(3600 * 24, $cacheKey, '/rutube/');
    $cache->endDataCache($result);

    return $result;
}

24-hour cache mandatory — RuTube API has no published limits, but frequent requests on high traffic create load and slow page response.

Output in Product Card Template

$rutubeUrls = (array)($arResult['PROPERTIES']['VIDEO_RUTUBE']['VALUE'] ?? []);

foreach ($rutubeUrls as $rutubeUrl) {
    $videoId = parseRutubeId($rutubeUrl);
    if (!$videoId) continue;

    $info     = getRutubeVideoInfo($videoId);
    $thumbUrl = $info['thumbnail_url'] ?? '/local/img/video-placeholder.jpg';
    $embedUrl = getRutubeEmbedUrl($videoId);

    echo '<div class="rutube-facade" data-embed="' . htmlspecialchars($embedUrl) . '">';
    echo '<img src="' . htmlspecialchars($thumbUrl) . '"
               alt="' . htmlspecialchars($info['title'] ?? 'Video review') . '"
               loading="lazy" width="640" height="360">';
    echo '<button class="play-btn" aria-label="Watch video"></button>';
    echo '</div>';
}

JavaScript initialization (similar to YouTube facade):

document.querySelectorAll('.rutube-facade').forEach(function(el) {
    el.addEventListener('click', function() {
        const iframe = document.createElement('iframe');
        iframe.src = this.dataset.embed + '&autoplay=1';
        iframe.width = '640';
        iframe.height = '360';
        iframe.allowFullscreen = true;
        iframe.allow = 'autoplay; encrypted-media';
        this.replaceWith(iframe);
    });
});

Joint YouTube and RuTube Usage

If card needs both services, unify handling via one VIDEO_URL property:

function detectVideoSource(string $url): string
{
    if (str_contains($url, 'youtube.com') || str_contains($url, 'youtu.be')) {
        return 'youtube';
    }
    if (str_contains($url, 'rutube.ru')) {
        return 'rutube';
    }
    return 'unknown';
}

Simplifies manager's work: one property type, paste any link, system figures it out.

SEO Markup VideoObject for RuTube

Search engines accept VideoObject markup for RuTube too:

if ($info) {
    $schema = [
        '@context'    => 'https://schema.org',
        '@type'       => 'VideoObject',
        'name'        => $info['title'],
        'thumbnailUrl'=> $info['thumbnail_url'],
        'embedUrl'    => getRutubeEmbedUrl($videoId),
        'duration'    => 'PT' . gmdate('H\Hi\Ms\S', $info['duration']),
        'uploadDate'  => date('c'),
    ];
    echo '<script type="application/ld+json">'
       . json_encode($schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
       . '</script>';
}

RuTube videos indexed in Yandex search and may appear in video results. Google doesn't guarantee RuTube content indexing yet, but markup won't hurt.

Implementation Timeline

Variant Work Timeline
Basic (single video, iframe without preview) Property + template 0.5 day
With API preview and facade pattern API request + cache + JS 1–2 days
Universal (YouTube + RuTube + SEO + gallery) Single property + platform routing + markup 2–3 days