Integration of 1C-Bitrix with Dynamic Yield

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
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Integration of 1C-Bitrix with Dynamic Yield

Dynamic Yield is an enterprise personalization platform by Mastercard, a competitor to Adobe Target and Optimizely. Used by large retailers for A/B testing, content personalization, and real-time recommendations. Integration with Bitrix is built on two layers: Data Feed for catalog synchronization and Experience OS JavaScript SDK for transmitting behavioral events.

Data Feed: Catalog Synchronization

Dynamic Yield accepts product feeds in JSON or CSV format. JSON is more flexible—allows transmitting arbitrary attributes for segmentation.

JSON feed structure:

{
  "version": "1.0",
  "type": "full",
  "products": [
    {
      "sku": "PROD-001",
      "name": "Product Name",
      "url": "https://example.ru/catalog/product/",
      "price": 1500.00,
      "in_stock": true,
      "image_url": "https://example.ru/upload/iblock/abc/photo.jpg",
      "categories": ["Electronics", "Smartphones"],
      "group_id": "GROUP-001",
      "description": "Brief product description",
      "brand": "Samsung",
      "keywords": ["smartphone", "android"],
      "custom_attributes": {
        "color": "Black",
        "weight": "185g",
        "supplier_id": 42
      }
    }
  ]
}

Feed generator in Bitrix:

function generateDynamicYieldFeed(): string
{
    $products = [];

    $res = CIBlockElement::GetList(
        [],
        ['IBLOCK_ID' => CATALOG_IBLOCK_ID, 'ACTIVE' => 'Y'],
        false,
        false,
        ['ID', 'NAME', 'DETAIL_PAGE_URL', 'DETAIL_PICTURE',
         'PREVIEW_TEXT', 'IBLOCK_SECTION_ID']
    );

    while ($el = $res->GetNextElement()) {
        $fields = $el->GetFields();
        $props  = $el->GetProperties();

        $price     = CCatalogProduct::GetOptimalPrice($fields['ID']);
        $priceVal  = (float)($price['PRICE']['PRICE'] ?? 0);

        $quantity  = (int)(CCatalogProduct::GetByIDEx($fields['ID'])['QUANTITY'] ?? 0);
        $inStock   = $quantity > 0;

        $imgUrl = '';
        if ($fields['DETAIL_PICTURE']) {
            $f = CFile::GetFileArray($fields['DETAIL_PICTURE']);
            if ($f) $imgUrl = 'https://' . SITE_SERVER_NAME . $f['SRC'];
        }

        $section   = CIBlockSection::GetByID($fields['IBLOCK_SECTION_ID'])->Fetch();
        $categories = $section ? [$section['NAME']] : [];

        $product = [
            'sku'        => $props['CML2_ARTICLE']['VALUE'] ?? (string)$fields['ID'],
            'name'       => $fields['NAME'],
            'url'        => 'https://' . SITE_SERVER_NAME . $fields['DETAIL_PAGE_URL'],
            'price'      => $priceVal,
            'in_stock'   => $inStock,
            'image_url'  => $imgUrl,
            'categories' => $categories,
            'description'=> strip_tags($fields['PREVIEW_TEXT'] ?? ''),
        ];

        // Add custom attributes from properties
        $customAttrs = [];
        foreach (['BRAND', 'COLOR', 'WEIGHT'] as $propCode) {
            if (!empty($props[$propCode]['VALUE'])) {
                $customAttrs[strtolower($propCode)] = $props[$propCode]['VALUE'];
            }
        }
        if ($customAttrs) {
            $product['custom_attributes'] = $customAttrs;
        }

        $products[] = $product;
    }

    return json_encode([
        'version'  => '1.0',
        'type'     => 'full',
        'products' => $products,
    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}

Feed is published by URL and specified in Dynamic Yield → Feeds. Recommended update frequency—daily; with frequent price changes—multiple times daily via agent.

JavaScript SDK: Behavioral Events

Dynamic Yield requires initialization on every page:

window.DY = window.DY || {};
DY.recommendationContext = { type: 'HOMEPAGE' }; // overridden on each page type

(function(d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) return;
    js = d.createElement(s); js.id = id;
    js.src = '//cdn.dynamicyield.com/api/<?= DY_SITE_ID ?>/api_dynamic.js';
    fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'DY-api-script'));

DY_SITE_ID—ID from Dynamic Yield personal account.

Page context—Dynamic Yield personalizes content by page type:

// In product page template
?>
<script>
window.DY = window.DY || {};
DY.recommendationContext = {
    type: 'PRODUCT',
    data: ['<?= $arResult['ID'] ?>']  // Current product SKU
};
</script>
<?php

// In category template
?>
<script>
DY.recommendationContext = {
    type: 'CATEGORY',
    data: ['<?= $sectionCode ?>']
};
</script>
<?php

Add to cart event:

DY.API('event', {
    name: 'Add to Cart',
    properties: {
        dyType: 'add-to-cart-v1',
        value: price * quantity,
        currency: 'RUB',
        productId: String(productId),
        quantity: quantity,
        cart: currentCartItems.map(function(item) {
            return { productId: String(item.id), quantity: item.qty, itemPrice: item.price };
        })
    }
});

Purchase event:

DY.API('event', {
    name: 'Purchase',
    properties: {
        dyType: 'purchase-v1',
        uniqueTransactionId: String(orderId),
        value: orderTotal,
        currency: 'RUB',
        cart: orderItems.map(function(item) {
            return { productId: String(item.product_id), quantity: item.quantity, itemPrice: item.price };
        })
    }
});

Data for this event is transmitted through HTML data attributes or inline PHP variables on the "Thank you for your order" page.

User Identification

Dynamic Yield links anonymous and authorized sessions. On authorization, call:

DY.API('event', {
    name: 'Login',
    properties: {
        dyType: 'login-v1',
        hashedEmail: sha256(userEmail.toLowerCase().trim())
    }
});

SHA-256 email hash is computed on the client. Dynamic Yield doesn't accept email in plain text.

Widgets: Recommendation Blocks

Dynamic Yield displays personalized blocks through "widgets"—configured in personal account. On Bitrix side—just HTML container with ID:

<!-- In product page template: "You might like" -->
<div class="dy-recommendations" id="dy-widget-product-page"></div>

<!-- On homepage: "Personal recommendations" -->
<div class="dy-recommendations" id="dy-widget-homepage"></div>

Dynamic Yield itself fills these containers with recommendations based on user behavior.

Implementation Timelines

Scope Composition Duration
Feed + basic SDK (context + cart + purchase) Feed generator + JS events 2–4 days
Identification + all page types + hashed email + contexts +1–2 days
A/B tests + segments + widgets DY setup + widget testing separate budget line