Как стать автором
Обновить

Создаем простой сервис коллтрекинга, часть 1

Время на прочтение10 мин
Количество просмотров4.1K
В рамках статьи будет рассмотрен один из возможных вариантов реализации коллтрекинга на сайте. Данный материал написан сугубо в образовательных целях и не несет в себе цели замены существующих специализированных сервисов, предоставляющих услугу «calltracking».

Требования к функционалу


  1. Сервис должен предоставлять возможность подстановки номера (номеров) по источнику перехода на сайт — переход из поисковых систем, переход по рекламе, переход по ссылкам с utm метками.
  2. Сервис должен закреплять показываемый номер за посетителем сайта и отображать данный номер при дальнейшем посещении.
  3. При инициации звонка на показываемый номер сервис должен инициировать создание события в Google Analytics.

Общая механика


При переходе на сайт мы определяем источник перехода, после чего проверяем закреплен ли за данным посетителем номер. Если посетитель перешел на сайт впервые, то присваиваем ему уникальный идентификатор, после чего закрепляем за ним номер из пула номеров, относящихся к данному источнику перехода. В дальнейшем при повторном переходе посетителя на сайт мы отображаем присвоенный ему ранее номер.

Основной акцент хотелось бы сделать на журнале вызовов. Подменить номер, закрепить его за пользователем — это вопрос техники, главное — это иметь возможность сопоставления конкретного вызова и номера, который в данный момент времени закреплен за пользователем. Если используемая телефония позволяет на постоянной основе получать детализацию по своершаемым звонкам, то зная момент звонка на конкретный номер и обладая информацией о том какой номер отображался в этот момент на сайте у какого пользователя возможно инициировать создание события в Google Analytics и связать его с РК.

Структура


  1. ct-server.ru — здесь будет размещен исполняемый скрипт веб-сервиса, база данных для хранения настроек номеров и логирования посетителей;
  2. refer-to-site-with-ct-code.ru — на этой площадке мы будем эмулировать переход из поисковой сети;
  3. site-with-ct-code.ru — сайт, на котором будет размещен скрипт подстановки номера.

Приступим к реализации


Приведенный ниже пример будет реализован на локальном сервере.

Создадим виртуальных хост site-with-ct-code.ru, в который положим файл index.html следующего содержания.

<!DOCTYPE HTML>
<html>
<head>
  <meta charset='utf-8'>
  <title>CT</title>
  <script src="http://ct-server.ru/script.js"></script>
  <script>
    //эмулируем куку google  id
    document.cookie = '_ga=GA1.2.1212121212.1212121212; expires=Thu, 18 Dec 2077 12:00:00 UTC; path=/';
  </script>
</head>
<body>
  <p id='calltracking'>79000000000</p>
</body>
</html>

Как видно из примера мы подключаем внешний скрипт ct-server.ru/script.js, который будет осуществлять «общение» между site-with-ct-code.ru и ct-server.ru, а так же взаимодействовать с DOM-деревом сайта site-with-ct-code.ru. Подстановка номера будет осуществляться по id элемента — 'calltracking'.

Теперь создадим refer-to-site-with-ct-code.ru, который будет содержать в себе ссылку на site-with-ct-code.ru для возможности проверки закрепления номера по переходу с рефера.

<!DOCTYPE HTML>
<html>
<head>
  <meta charset='utf-8'>
  <title>CT</title>
</head>
<body>
  <a href="http://site-with-ct-code.ru">поехали</a>
</body>
</html>

После этого поднимем хост ct-server.ru, который будет иметь следующую структуру:

index.php — файл исполняемого скрипта, который будет принимать Post-запросы от site-with-ct-code.ru и взаимодействовать с базой данных;

script.js — файл скрипта, который будет подключаться на сайтах, где будет осуществляться подстановка номера.

База данных


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

CREATE TABLE `ct` (
  `id` int(11) NOT NULL,
  `phone` varchar(200) NOT NULL,
  `refer` varchar(200) NOT NULL,
  `utm` varchar(200) NOT NULL,
  `host` varchar(200) NOT NULL,
  `ga` varchar(200) NOT NULL,
  `login` varchar(200) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `ct`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `id` (`id`);

ALTER TABLE `ct`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;

Небольшое пояснение по добавленным полям:

phone — подставляемый номер телефона;
refer — источник перехода;
utm — ссылка на страницу, на которой должна происходить подстановка номера;
host — сайт, на котором размещен скрипт подстановки номера;
ga — id счетчика Google Analytics;
login — логин владельца номера.

Наполняем табличку данными.

INSERT INTO `ct` (`id`, `phone`, `refer`, `utm`, `host`, `ga`, `login`) VALUES
(2, '78000000001', '', 'http://site-with-ct-code.ru/?utm_medium=cpc', 'http://site-with-ct-code.ru', 'UA-12345678-1', ''),
(3, '78000000002', 'http://refer-to-site-with-ct-code.ru/', 'http://site-with-ct-code.ru/', 'http://site-with-ct-code.ru', 'UA-12345678-1', ''),
(4, '78000000003', 'http://refer-to-site-with-ct-code.ru/', 'http://site-with-ct-code.ru/', 'http://site-with-ct-code.ru', 'UA-12345678-1', ''),
(5, '78000000004', 'http://refer-to-site-with-ct-code.ru/', 'http://site-with-ct-code.ru/', 'http://site-with-ct-code.ru', 'UA-12345678-1', ''),
(6, '78000000005', '', 'http://site-with-ct-code.ru/', 'http://site-with-ct-code.ru', 'UA-12345678-1', '');

image

Теперь создадим табличку numbers.

CREATE TABLE `numbers` (
  `id` int(11) NOT NULL,
  `phone` varchar(200) DEFAULT NULL,
  `ct_user` varchar(200) DEFAULT NULL,
  `refer` varchar(200) DEFAULT NULL,
  `gid` varchar(200) DEFAULT NULL,
  `page` varchar(200) DEFAULT NULL,
  `time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `numbers`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `id` (`id`),

ALTER TABLE `numbers`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;COMMIT;

В этой табличке мы будем фиксировать у какого посетителя, какой номер и в какой момент времени отображается на сайте. В дальнейшем эти данные можно сопоставить с журналом звонков чтобы инициировать целевое действие — отправку событие в Google Analytics, создание лида в CRM, отправку письма и т.п.

phone — номер телефона;
ct_user — id посетителя;
refer — источник перехода;
gid — кука Google Analytics;
page — страница на котрой отображается номер;
time — время отображения номера.

Создаем обработчик запросов


Взаимодейтсвие между веб-сервисом ct-server.ru и сайтом, на котором размещается скрипт будет осуществляться через кросс-доменные XHR(XMLHttpRequest) POST — запросы.

Откроем созданный ранее файл ct-server.ru/index.php и добавим проверку на прием данных с разрешенных хостов, в нашем случаем это site-with-ct-code.ru, site-with-ct-code2.ru и site-with-ct-code3.ru.

<?php
if (isset($_SERVER["HTTP_ORIGIN"]) === true) {
    $host = $_SERVER["HTTP_ORIGIN"];
    //список допустимых хостов
    $allowHosts = array("http://site-with-ct-code.ru", "http://site-with-ct-code2.ru", "http://site-with-ct-code3.ru");
    if (in_array($host, $allowHosts, true) === true) {
        header('Access-Control-Allow-Origin: ' . $host);
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Allow-Methods: POST');
        header('Access-Control-Allow-Headers: Content-Type');
    //здесь мы будем разбирать  post- запросы и взаимодействовать с базой
    }
    if ($_SERVER["REQUEST_METHOD"] === "OPTIONS") {
        exit;
    }
}
?>

Записываем в переменные значения POST-запросов, пришедших от site-with-ct-code.ru

$phone = $_POST["phone"];
$ct_user = $_POST["ct_user"];
$gid = $_POST["gid"];
$refer = $_POST["ref"];
$page = $_POST["page"];

Кука _ga имеет вид _ga=GA1.2.1212121212.1212121212, приведем её к виду «1212121212.1212121212».

if ($gid) {
    $pos = strpos($gid, '.', strpos($gid, '.') + 1);
    $gid = substr($gid, $pos + 1);
}

Установим соединение с базой данных, где мы ранее создали наши таблицы.

$conn = new mysqli("localhost", "root", "", "calltracking");
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}


Взаимодействие с веб-сервисом будет осуществляться через два метода — get_num_first и get_num.

Метод get_num_first вызывается при первом взаимодействии посетителя с сайтом для получения номера путем выборки из базы согласно критериям — почта, рефер, utm, host. Если результат выборки возвращает значение, то выводим номер телефона.

Помимо этого мы отправляем событие в Google Analytics через Google Measurement Protocol. Этот же способ применим для отслеживания офлайн действий, в дальнейшем его можно применить при сопоставлении журнала звонков и лога номеров в таблице numbers.

if ($_POST['method'] == 'get_num_first') {
    $sql = "SELECT * FROM `ct` where `host` = '" . $host . "' and `refer` = '" . $refer . "' and `utm` = '" . $page . "'  ORDER BY RAND() LIMIT 1 ";
    $result = $conn->query($sql);
    if ($result->num_rows > 0) {
        while ($row = $result->fetch_assoc()) {
            print_r($row["phone"]);
            $event = file_get_contents('https://www.google-analytics.com/collect?v=1&tid=UA-12345678-1&cid=' . $gid . '&t=event&ec=GetNumber&ea=number&z=' . $row["phone"] . '');
        }
    } else {
        //echo "0";
        $sql = "SELECT * FROM `ct` where `host` = '" . $host . "' and `refer` = '" . $refer . "' ORDER BY RAND() LIMIT 1 ";
        $result = $conn->query($sql);
        print_r($row["phone"]);
        $event = file_get_contents('https://www.google-analytics.com/collect?v=1&tid=UA-12345678-1&cid=' . $gid . '&t=event&ec=GetNumber&ea=number&z=' . $row["phone"] . '');
    }
}


Метод get_num необходим для логирования записей в таблице numbers.

else if ($_POST['method'] == 'get_num') {
    $sql = "INSERT INTO `numbers` (`phone`, `ct_user`, `gid`, `refer`,`page`) VALUES ( '" . $phone . "', '" . $ct_user . "', '" . $gid . "', '" . $refer . "', '" . $page . "');";
    $result = $conn->query($sql);
    $sql = "SELECT * FROM `numbers` where `ct_user` = '" . $ct_user . "'  ORDER BY `id` DESC LIMIT 1 ";
    $result = $conn->query($sql);
    if ($result->num_rows > 0) {
        while ($row = $result->fetch_assoc()) {
            print_r($row["phone"]);
            $event = file_get_contents('https://www.google-analytics.com/collect?v=1&tid=UA-12345678-1&cid=' . $gid . '&t=event&ec=ShowNumber&ea=number&z=' . $row["phone"] . '');
        }
    } else {
      //echo "0";
    }
}

$conn->close();

Скрипт подстановки номера


Далее мы перейдем к скрипту ct-server.ru/script.js, который мы подключаем на сайте site-with-ct-code.ru

Для начала создадим две функции — setcookie для создания и getcookie для чтения куки. Мы будим использовать их для записи и получения значений кук id пользователя и номера телефона.

//задаем куку
function setcookie(phone, value, expires, path, domain, secure) {
  document.cookie =
    phone +
    "=" +
    escape(value) +
    (expires ? "; expires=" + new Date(expires) : "") +
    (path ? "; path=" + path : "") +
    (domain ? "; domain=" + domain : "") +
    (secure ? "; secure" : "");
}

//читаем куку
function getcookie(phone) {
  var cookie = " " + document.cookie;
  var search = " " + phone + "=";
  var setStr = null;
  var offset = 0;
  var end = 0;

  if (cookie.length > 0) {
    offset = cookie.indexOf(search);

    if (offset != -1) {
      offset += search.length;
      end = cookie.indexOf(";", offset);

      if (end == -1) {
        end = cookie.length;
      }

      setStr = unescape(cookie.substring(offset, end));
    }
  }

  return setStr;
}

После этого добавим функцию makeid для генерации id для пользователя.

//генерируем  id пользователя
function makeid(length) {
  var result = "";
  var user_id = "abcdefghijklmnopqrstuvwxyz0123456789";
  var user_idLength = user_id.length;
  for (var i = 0; i < length; i++) {
    result += user_id.charAt(Math.floor(Math.random() * user_idLength));
  }
  return result;
}

Теперь создадим функцию для генерации куки, содержащей 33-значный id пользователя.

//генерируем id  пользователя
function generateuser_id() {
  var ct_user_id = makeid(33);
  setcookie("ct_user", ct_user_id, new Date().getTime() + 60 * 60 * 1000); // час
}

Полученная кука ct_user хранится 1 час.

Приступаем к формирования запроса на получение номера через метод get_num_first. Полученный номер от ct-server.ru записываем в куку на 1 час и осуществляем первую подстановку номера на странице по id элемента.

//отправляем запрос на получение номера, после того, как мы первый раз сгенерировали отсутствующий id  пользователя
function getNumberFirstTime() {
  var method = "get_num_first";
  var ct_user = getcookie("ct_user");
  var gid = getcookie("_ga");
  var ref = document.referrer;
  var host = window.location.origin;
  var page = document.location.href;
  var xhr = new XMLHttpRequest();
  var body =
    "&method=" +
    encodeURIComponent(method) +
    "&page=" +
    encodeURIComponent(page) +
    "&ct_user=" +
    encodeURIComponent(ct_user) +
    "&ref=" +
    encodeURIComponent(ref) +
    "&host=" +
    encodeURIComponent(host) +
    "&gid=" +
    encodeURIComponent(gid);

  xhr.open("POST", "http://ct-server.ru", true);
  xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  xhr.withCredentials = true;
  xhr.send(body);
  xhr.onreadystatechange = function() {
    //console.log(xhr.responseText);
    var t = xhr.responseText;
    document.getElementById("calltracking").innerHTML = t;
    setcookie("phone", t, new Date().getTime() + 60 * 60 * 1000); // час
  };
}

Создадим функцию, которая будет периодически отправлять в сторону ct-server.ru значения отображаемого номера, id пользователя, адрес страницы, значение куки google analytics, источник перехода.

function getNumberPeriodically() {
  var method = "get_num";
  var ct_user = getcookie("ct_user");
  var phone = getcookie("phone");
  var gid = getcookie("_ga");
  var ref = document.referrer;
  var page = document.location.href;
  var host = window.location.origin;
  var xhr = new XMLHttpRequest();
  var body =
    "&method=" +
    encodeURIComponent(method) +
    "&page=" +
    encodeURIComponent(page) +
    "&ct_user=" +
    encodeURIComponent(ct_user) +
    "&ref=" +
    encodeURIComponent(ref) +
    "&host=" +
    encodeURIComponent(host) +
    "&phone=" +
    encodeURIComponent(phone) +
    "&gid=" +
    encodeURIComponent(gid);

  xhr.open("POST", "http://ct-server.ru", true);
  xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  xhr.withCredentials = true;
  xhr.send(body);
  xhr.onreadystatechange = function() {
    //console.log(xhr.responseText);
    var t = xhr.responseText;
    //document.getElementById('calltracking').innerHTML = t;
  };
}

В завершении добавляем функцию sendToCalltracking, проверяющую наличие кук номера телефона и id пользователя.

function sendToCalltracking() {
  var ggg = getcookie("ct_user");
  var ccc = getcookie("phone");
  var gac = getcookie("_ga");

  if (
    typeof ggg === "undefined" ||
    ggg === null ||
    ccc === "undefined" ||
    ccc === null ||
    ccc.length < 1 ||
    ggg.length < 1 ||
    ccc === "" ||
    ggg === ""
  ) {
    //console.log('false');
    generateuser_id();
    getNumberFirstTime();
  } else {
    //console.log('true');
    document.getElementById("calltracking").innerHTML = ccc;
    getNumberPeriodically();
  }
}

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

var myTimer = setTimeout(sendToCalltracking, 500);
//вызываем функцию проверки и отправки номера каждую минуту
setInterval(sendToCalltracking, 1 * 60 * 1000);

image

В случае удаления куки при следующем срабатывании функция назначит посетителю новую согласно полученной выборке по хосту и источнику. Помимо этого возможно записывать полученные значения в localStorage браузера.

image

Раз в минуту скрипт будет отправлять значение куки номера и id пользователя с указанием страницы на которой он был применен без её перезагрузки. Подразумевается что скрипт будет размещен на всех страницах домена.

image

В следующей статье мы разберем разработку простого интерфейса для добавления и настройки номеров.
Теги:
Хабы:
Всего голосов 5: ↑5 и ↓0+5
Комментарии5

Публикации

Работа

Ближайшие события