# Событие персонализации

Очень часто при выборе варианта персонализации требуется выполнить какую-то сложную JavaScript логику. Это можно сделать с помощью подписки на событие персонализации.

# Общая идея

Подписка — это специальный вызов метода внутри JavaScript кода. Подписаться можно как на персонализацию, так и на сочетание персонализации и варианта персонализации.

Результатом вызова подписки служит выполнение пользовательского кода внутри обработчика handler.

Самая простая подписка выглядит следующим образом:

// Показывать лучший отзыв у товара
window.SalesNinja.onPersonalization({
personalizationId: '6fbf1dd7-3771-45ce-a7a0-bd08187549ee',

    // вызывается при применении персонализации
    handler: (personalization, personalizationOption) => {
      switch (personalizationOption.id){
        case ("10337247-6fa7-4ac3-92ed-bb2506d79ffa"):
          // Да
          break;
        case ("fb8211d7-5aa3-40df-a3ed-54a67d72f850"):
          // Нет
          break;
        default:
          // ...
      }
    },
})

# Типы подписки

Существует три основных типа подписки:

# Указан один personalizationId (то есть ID персонализации).

В этом случае подписка будет вызвана, если персонализация будет вызвана с любым вариантом персонализации.

Фактически это означает, что подписка будет вызвана в любом случае, если сама персонализация применима исходя из условий показа.

Пример:

// Показывать лучший отзыв у товара
window.SalesNinja.onPersonalization({
personalizationId: '6fbf1dd7-3771-45ce-a7a0-bd08187549ee',

    handler: (personalization, personalizationOption) => {
      switch (personalizationOption.id){
        // вызовется для люого варианта персонализации
      }
    },
})

# Указаны personalizationId + personalizationOptionId (то есть ID персонализации и ID варианта персонализации).

В этом случае подписка будет вызвана, если персонализация вызвана с указанным вариантом персонализации.

Пример:

// Показывать лучший отзыв у товара -> Да
window.SalesNinja.onPersonalization({
    personalizationId: '6fbf1dd7-3771-45ce-a7a0-bd08187549ee',
    personalizationOptionId: '10337247-6fa7-4ac3-92ed-bb2506d79ffa',

    handler: (personalization, personalizationOption) => {
        // Вызовется, если будет выбран вариант персонализации Показывать лучший отзыв у товара = Да
    },

})

# Не указан ни personalizationId, ни personalizationOptionId

В этом случае подписка будет вызвана для каждой примененной персонализации на текущей странице.

Такой тип подписки может быть полезен для инфраструктурных вещей на клиентской стороне, например, если хотите добавить все произошедшие персонализации в самописную систему аналитики.

Пример:

window.SalesNinja.onPersonalization({

    handler: (personalization, personalizationOption) => {
        // Вызовется для каждой примененной персонализации
    },
})

# Таймаут

В некоторых случаях, персонализация является критичной по времени выполнения.

Например, если есть два варианта лендинга и некоторая "промежуточная" страница с персонализацией, суть которой — перенаправить юзера на нужный вариант лендинга, исходя из выбранного результата персонализации.

В этом случае, если:

  1. Запрос на получение персонализаций с сервера "упал"
  2. Запрос на получение персонализаций с сервера не успел выполнится

За указанное в обработчике время timeout, то вызывается другой специальный обработчик onTimeoutExceeded.

Пример:

// Показывать лучший отзыв у товара
window.SalesNinja.onPersonalization({
personalizationId: '6fbf1dd7-3771-45ce-a7a0-bd08187549ee',

    // Основной обработчик персонализации
    handler: (personalization, personalizationOption) => {
        // ...
    },

    // сколько миллисекунд ждать применения персонализаций
    timeout: 2000

    // вызывается, если подписка не применилась за указанное время
    onTimeoutExceeded: (personalization, personalizationOption) => {
      // ...
    },
})

# Несколько подписок personalizationId + personalizationOptionId с таймаутом

Если у нас несколько подписок на различные варианты одной персонализации и у каждой подписки указан таймаут выполнения, то при успешном выполнении любой из этих подписок таймаут в остальных вызван НЕ будет.

Пример:

// Показывать лучший отзыв у товара -> Нет
window.SalesNinja.onPersonalization({
    personalizationId: '6fbf1dd7-3771-45ce-a7a0-bd08187549ee',
    personalizationOptionId: 'fb8211d7-5aa3-40df-a3ed-54a67d72f850',

    handler: (personalization, personalizationOption) => {
    },

    timeout: 1000

    onTimeoutExceeded: (personalization, personalizationOption) => {
        // Не будет вызвано, если Показывать лучший отзыв у товара -> Да
        // "отработает" успешно
    },

})

// Показывать лучший отзыв у товара -> Да
window.SalesNinja.onPersonalization({
    personalizationId: '6fbf1dd7-3771-45ce-a7a0-bd08187549ee',
    personalizationOptionId: '10337247-6fa7-4ac3-92ed-bb2506d79ffa',

    handler: (personalization, personalizationOption) => {
    },

    timeout: 1000

    onTimeoutExceeded: (personalization, personalizationOption) => {
        // Не будет вызвано, если Показывать лучший отзыв у товара -> Нет
        // "отработает" успешно
    },

})

# Таймаут по-умолчанию

По-умолчанию, время таймаута указано как 5 секунд. Поэтому, если подписка имеет onTimeoutExceeded, но не имеет указанный timeout, то будет использовано значение 5 секунд.

Пример:

window.SalesNinja.onPersonalization({
    personalizationId: '6fbf1dd7-3771-45ce-a7a0-bd08187549ee',
    personalizationOptionId: '10337247-6fa7-4ac3-92ed-bb2506d79ffa',

    handler: (personalization, personalizationOption) => {
    },

    onTimeoutExceeded: (personalization, personalizationOption) => {
        // Будет вызвано через 5 секунд, если будут выполнены условия для срабатывания таймаута
    },

})

# Метод подписки возвращает Promise

Метод onPersonalization возвращает Promise (opens new window).

А это значит, что вы можете использовать await для синхронного ожидания получения результата персонализации.

В случае использования промисов необходимо дождаться готовности скрипта - window.SalesNinja.ready == true

Так же это позволяет выполнить какое-то действие асинхронно, сразу после успешного или неуспешного получения персонализации.

Пример:

// Выбор пункта выдачи по-умолчанию при оформлении заказа
window.SalesNinja.onPersonalization({
personalizationId: 'e9b3f461-0857-4b21-a6fc-1bdcbe429cd4',

    // вызывается при применении персонализации
    handler: (personalization, personalizationOption) => {
      switch (personalizationOption.id){
        case ("a554d770-3ed3-4d07-be0b-98475e27eb44"):
          // Нет
          break;
        case ("cc30da87-338c-49a2-adcc-f2c3b47ee6ed"):
          // Да
          break;
        default:
          // ...
      }
    },
}).then((personalization, personalizationOption) => {
    // После успешного отрабатывания подписки
}, (personalization, personalizationOption) => {
    // После неуспешного отрабатывания подписки
    // personalization и personalizationOption не обязательно будут заполнены!
})