Интеграция ClientoBox с использованием JavaScript

Если вы пользуетесь ClientoBox и имеете свой собственный сайт для работы с клиентами, вам может пригодится наша js-библиотека. При помощи API вызовов библиотеки и специально сформированной HTML страницы на вашем сайте вы сможете автоматизировать большую часть работу с клиентами.

Примечание

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

Введение

У вас есть сайт, на котором пользователи оставляют заявки для связи с вашим менеджером:

  • клиент заходит на сайт, заполняет форму заявки;
  • менеджеру на почту приходит уведомление о заявке;
  • менеджер создает сделку в ClientoBox;
  • менеджер отвечает на обращение клиента.

Минусы подхода: постоянная рутинная работа с почтой и занесение сделок в ClientoBox.

После внедрения нашей js-библиотеки процесс заказа выглядит следующим образом:

  • клиент заходит на сайт, заполняет форму заявки;
  • менеджер отвечает на обращение клиента.

Для подключения js-библиотеки ClientoBox к вашему сайту необходимо:

  • Получить JS-ключ, который привязан вашему аккаунту ClientoBox, по ссылке https://app.clientobox.ru/settings/api. В поле JS-ключ будет строка вида 55_1234_b077d2a1234503d8baеа234.
  • Настройте формы на вашем сайте для передачи данных в ClientoBox, используя API вызовы. Пример разобран ниже в данном документе.

Подробное описание всех API вызовов вы можете прочитать в разделе api. JS-ключ работает только на добавление данных в ваш аккаунт.

Пример использования библиотеки

Подключение библиотеки

Для подключения библиотеки разместите следующую строку в разделе <head> вашего сайта:

<script type="text/javascript" src="//static.clientobox.ru/js/clientobox.js"></script>

Настройка параметров библиотеки

Разместите следующий скрипт перед закрывающим тегом </body>

<script type="text/javascript">
    var cb = clientobox;
    // Короткий псевдоним - так удобнее набирать названия функций или констант

    cb.log.minLogLevel = cb.log.LogLevels.INFO;
    // Информативность вывода в консоль.
    // При отладке можете использовать cb.log.LogLevels.DEBUG

    cb.api.useHttps = false;
    // Если ваш сайт использует https — рекомендуется поставить true,
    // при этом надо добавить или изменить порт по умолчанию, добавив параметр
    // cb.api.servicePort=443;

    cb.api.apiKey = '<ваш JS-ключ>'; //ВАЖНО!!! Используйте только JS-ключ!
    cb.api.ignoreEntitySavingErrors = true;
    // Игнорировать ли ошибки создания других сущностей. Например, если вы создаёте
    // организацию, потом сделку, к которой привязываете эту организацию, и по какой-то
    // причине организация не создалась - в этом случае сделка всё равно будет создана
    // (параметр установлен в true). Если установить в false - при первой же ошибке
    // создания сущности выполнение скрипта прекращается.

    cb.api.requestTimeout = 3000;
    // Таймаут на каждый запрос к серверу ClientoBox (в миллисекундах)

    /// --- ВАШ СКРИПТ ПО ОБРАБОТКЕ ФОРМЫ --- ///

</script>

Сразу после настройки параметров библиотеки разместите сам скрипт, выполняющий необходимую обработку (в коде выше это место помечено тегом /// --- ВАШ СКРИПТ ПО ОБРАБОТКЕ ФОРМЫ --- ///). При использовании jQuery работать с библиотекой ClientoBox будет удобнее. Но вы можете выполнить обработку и без неё.

Интеграция без использования библиотеки jQuery с применением средств JavaScript

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

Вы можете привязывать данные к уже существующим в вашем аккаунте сущностям — для этого надо создать соответствующий JavaScript-объект и передать в него идентификатор сущности (он фигурирует в адресной строке, если вы перейдёте в карточку соответствующей сущности), например:

var organization = new cb.api.Organization(555);
// Организация с ID=555 - Эту организацию можно использовать в дальнейшем

var deal = new cb.api.Deal(123);
var contact = new cb.api.Contact(875);
var product = new cb.api.Product(666);

При этом соответствующая сущность создаваться не будет, так как подразумевается, что она уже есть в системе.

Рассмотрим пример скрипта, который выполняет полную обработку и создание соответствующих сущностей:

var org = new cb.api.Organization({

    // Если вы хотите составить параметр из нескольких элементов,
    // часть из которых не определена при загрузке страницы
    // (например - данные формы: при загрузке страницы форма ещё не заполнена),
    // их получение необходимо обернуть в функцию
    // Кроме того, вам доступен контекст this,
    // который берёт данные из других полей данной сущности
    name: function () {
        return 'Новая организация в городе ' + this.city;
    },
    // cb.lval - функция берёт значение из input с id, указанным в качестве аргумента.

    // Данную конструкцию можно дополнительно не оборачивать в функцию,
    // т.к. значение из поля будет браться перед сохранением объекта.
    // НО! если данная конструкция используется в выражении
    // (например, 'Текст' + cb.lval('org_city')), то выражение
    // обязательно должно быть обёрнуто функцией, иначе его значение будет вычислено сразу
    city: cb.lval('org_city'),

    // Вы можете заполнить все поля сущности (полный список вы можете найти в документации
    // по серверному API):
    legal_address: 'Площадь свободы, дом 1',
    fact_address: 'Фактический адресс',
    inn: 1234444455,
    kpp: 9876666611,
    phone: 89209876543,
    email: cb.lval('org_email'),
    site: cb.lval('org_site'),

    // также вы можете добавить комментарии к сущности (в данном случае - к организации):
    // для этого достаточно передать массив нужных комментариев
    // они будут сохранены как отдельные комментарии
    comments: ['Комментарий в конструкторе 1', cb.lval('org_comment')]
});

// Комментарии можно добавить отдельно от создания объекта, методом addComments
// Вы можете передать комментарии как аргументами функции,
// так и в виде массива (а также аргументами с массивами):
org.addComments('Новый комментарий 1', ['Комментарий 2', 'Комментарий 3'], function () {

    // последний комментарий покажет сколько их всего добавлено
    // ссылка на parent доступна только в комментариях и продуктах сделки
    return 'Всего комментариев: ' + this.parent.comments.length;
});

Далее мы можем создать контакт, который связан с данной организацией:

var contact = new cb.api.Contact({
    name: function () {

        // name в организации org - это функция, помним об этом и вызываем правильно, обернув
        // внутрь функции!
        return 'Контакт в организации "' + this.org.name() + '"';
    },
    email: function () {

        // Не обязательно использовать this, можно получить доступ через context
        // для корректного доступа к информации
        // (в дочерних сущностях уже не нужно, пример: contact.context.org.email)
        return org.context.email; //возьмём email из организации
    },
    phone: 89201112233,
    org: org,
    skype: 'contact_skype',
    social: function () {

        // Допустим, мы ошиблись, с кем не бывает. Ничего не должно упасть, должен быть warning
        // в консоли и null как значение, объект при этом не сломается  и нормально сохранится
        return this.errorMethod();
    }
});

Создаём сделку, к которой будет привязан контакт, указанный выше

var deal = new cb.api.Deal({
    name: function () {
        return 'Сделка с "' + this.contact.name() + '"';
    },
    //stage: 1,

    // Вы можете указать ID этапа в системе, для этого придётся поковыряться в коде страницы...
    stage_name:'Продолжить дело',

    // Гораздо удобнее указать название воронки (channel_name) и название этапа (stage_name)
    channel_name: 'ТЕСТ',
    org: org,
    contact: contact,
    status: cb.api.DealStatuses.IN_PROGRESS,

    // Отмечаем, что сделка в процессе (по умолчанию). Также возможны варианты:
    // cb.api.DealStatuses.FAIL (проиграна) и cb.api.DealStatuses.WON (выиграна)
    price_currency: 'RUB',

    // Можно не указывать - тогда будет использована валюта вашего аккаунта по умолчанию
    comments: function () {
        return 'Продуктов в сделке: ' + this.parent.products.length;
    },

    // К сделке можно добавить продукты (по именам или с использованием ID продукта).
    // Цена сделки будет рассчитана автоматически на основании цен продуктов
    products: ['Тот, которого нет', 'Колбаса', 'Сыр', 1]
});

Также можно создать задачу, к которой привязать уже созданные сущности:

var action = new cb.api.Action({
    name: function () {
        return 'Задачка для сделки №' + this.deal.id;
    },
    action_date: '2015-03-21',
    action_time: '15:00',
    deal: deal,
    contact: contact,
    org: org,
    description: cb.lval('org_comment'),
    performed: 0,
    action_type: cb.api.ActionTypes.MEETING

    // Тип задачи. Допустимы значения: cb.api.ActionTypes.MEETING,
    // cb.api.ActionTypes.CALL, cb.api.ActionTypes.TASK, cb.api.ActionTypes.MAIL
});

После создания всех сущностей необходимо выполнить сохранение элемента. Обратите внимание, что все сущности перечислять не обязательно, все связанные сущности будут сохранены автоматически Параметр history хранит статус сохранения каждой сущности в виде массива объектов с полями entity, success, errorMessage. Для сохранения в любое время можно просто вызвать метод

cb.api.saveEntitiesToService([contact, deal, action], function(success, history){
    console.log('End save', success, cb.api.historyHasErrors(history), history);
});

Примечание

Если параметр cb.api.ignoreEntitySavingErrors=true (по умолчанию), то параметр success, который передаётся в callback всегда будет равен true. В данном режиме ошибки сохранения сущностей игнорируются. Чтобы узнать, были ли ошибки в этом случае нужно использовать cb.api.historyHasErrors(history). При выключении данного режима сохранение будет прервано на первой не сохранившейся сущности (при этом учтите, что ошибки сохранения комментариев и продуктов сделки игнорируются всегда).

Так как обычно для сохранения формы используется событие submit, для более простой интеграции в библиотеке создан функционал, который откладывает выполнение submit до отправки всех сущностей в систему ClientoBox (в примере ниже прикрепляем отправку данных к форме с id main_form):

// Автоматическое сохранение на submit формы —
// этот метод можно вызывать до загрузки страницы,
// так как он вызовет cb.utils.dom.onDOMContentLoaded автоматически, если нужно
cb.api.saveEntitiesToServiceOnFormSubmit('main_form', [deal], function (entities, form) {
    cb.log.info('Before Save', {
        entities: entities,
        form: form
    });

    // здесь можно изменить список сущностей (или заполнить с нуля,
    // если передавать в родительскую функцию пустой массив)
    entities.push(action);
},
function (success, history, entities, form) {

    // Можно добавить вывод в консоль успешно ли прошла операция сохранения
    cb.log.info('After Save', {
        success: success,
        hasErrors: cb.api.historyHasErrors(history),
        history: history,
        entities: entities,
        form: form
    });

    // отменяем сабмит, если нужно
    return false;
});

Пример с использованием jQuery

Приведенный пример является сокращённой версией разобранного выше. При разборе примера подразумевается, что вы ознакомились с работой библиотеки без использования jQuery (Интеграция без использования библиотеки jQuery с применением средств JavaScript). Если это не так — ознакомьтесь с указанным разделом.

Также не стоит смешивать методы работы с DOM из библиотеки (все из cb.utils.dom и cb.api.saveEntitiesToServiceOnFormSubmit) и методы работы с DOM от jQuery, это может привести к непредсказуемым последствиям. При наличии jQuery лучше использовать именно его, как в примере ниже

$(function () {

    $('#main_form').submit(function () {
        var form = this;

        var org = new cb.api.Organization({
            name: function () {
                return 'Новая организация в городе ' + this.city;
            },
            city: $('#org_city').val(),
            legal_address: 'Площадь свободы, дом 1',
            fact_address: 'Фактический адресс',
            inn: 1234444455,
            kpp: 9876666611,
            phone: 89209876543,
            email: $('#org_email').val(),
            site: $('#org_site').text(),
            comments: ['Комментарий в конструкторе 1', $('#org_comment').val()]
        });

        var entities = [org];

        // Сохраняем объекты и выполняем стандартый submit формы - это нужно делать
        // какому-нибудь событию, например по клику на кнопку “Отправить”
        cb.api.saveEntitiesToService(entities, function (success, history) {
            cb.log.info('After Save', {
                success: success,
                hasErrors: cb.api.historyHasErrors(history),
                history: history,
                entities: entities,
                form: form
            });

            form.submit();
        });
        return false;
    });
});

Заключение

Для JavaScript можно использовать только JS-ключ, так как он хранится в открытом виде! Мы рекомендуем проводить валидацию формы на клиентской стороне (с использованием JavaScript) до сохранения сущностей в систему ClientoBox. Чтобы избежать занесения в ClientoBox заведомо ложных сведений.