S2S ping/ru: Difference between revisions

From Wiki Kaminari Click
No edit summary
No edit summary
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
<languages/>
<languages/>
<div class="mw-translate-fuzzy">
Подробнее о настройке S2S ping — в коротком видео:
https://www.loom.com/share/a6cc760c91c94520a024e6b3891720ff
= Общий алгоритм работы =
= Общий алгоритм работы =
# Пользователь приходит на ваш сайт. Вы генерируете уникальный <code>kmnrId</code> и отстукиваетесь с ним на сервер Kaminari на URL /ping, мы сохраняем данные в кэш.
# Пользователь приходит на ваш сайт. Вы генерируете уникальный <code>kmnrId</code> и отстукиваетесь с ним на сервер Kaminari на URL /ping, мы сохраняем данные в кэш.
Line 8: Line 12:
## Если записи с таким <code>kmnrId</code> нет, мы ждём пять минут. Если вторая запись так и не приходит, мы пишем в статистику то, что есть.
## Если записи с таким <code>kmnrId</code> нет, мы ждём пять минут. Если вторая запись так и не приходит, мы пишем в статистику то, что есть.
## Так же мы периодически проверяем кэш и ищем просроченные клики, пришедшие на /ping, но так и оставшиеся без пары. Если нам не удалось никак их проверить, мы пишем их в стату со статусом «Технические потери».
## Так же мы периодически проверяем кэш и ищем просроченные клики, пришедшие на /ping, но так и оставшиеся без пары. Если нам не удалось никак их проверить, мы пишем их в стату со статусом «Технические потери».
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
= General workflow =
# The user arrives at your website. You generate a unique <code>kmnrId</code> and send it to Kaminari server via /ping URL, and we save the data in the cache.
# Then you show the user a page with our JavaScript script, adding the same <code>kmnrId</code> to the script call.
# We collect user data and send it to the server.
# On the server, we check in the cache:
## If there is a record with a similar <code>kmnrId</code> (coming from /ping), we combine the data from the cache with the results of the check and write them to the statistics.
## If there is no record with such an <code>kmnrId</code>, we wait up to five minutes. If the second record still does not arrive, we write what we have in the statistics.
## We also periodically check the cache and look for expired clicks that came to /ping but remained unpaired. If we couldn't verify them in any way, we write them to statistics with the status "Technical Losses."
</div>


<span id="Client-side_configuration"></span>
<span id="Client-side_configuration"></span>
Line 51: Line 67:
! Название !! Описание
! Название !! Описание
|-
|-
| user-agent || user agent пользователя
| user-agent || user agent пользователя || yes
|-
| referer || страница, с которой пришёл пользователь || no
|-
|-
| referer || страница, с которой пришёл пользователь
| accept-language || язык интерфейса браузера || yes
|-
|-
| accept-language || язык интерфейса браузера
| x-original-ip || реальный IP пользователя || yes
|-
|-
| x-original-ip || реальный IP пользователя
| x-forwarded-for || IP || yes
|-
|-
| x-forwarded-for || IP
| x-real-ip || IP || no
|-
|-
| x-requested-with || IP || no
| x-requested-with || || no
|-
|-
| sec-ch-ua-arch ||  
| sec-ch-ua-arch || || no
|-
|-
| sec-ch-ua ||  
| sec-ch-ua || || no
|-
|-
| sec-ch-ua-full-version ||  
| sec-ch-ua-full-version || || no
|-
|-
| device-memory ||  
| device-memory || || no
|-
|-
| dpr ||  
| dpr || || no
|-
|-
| sec-ch-ua-mobile ||  
| sec-ch-ua-mobile || || no
|-
|-
| sec-ch-ua-model ||  
| sec-ch-ua-model || || no
|-
|-
| sec-ch-ua-platform ||  
| sec-ch-ua-platform || || no
|-
|-
| sec-ch-ua-platform-version ||  
| sec-ch-ua-platform-version || || no
|-
|-
| viewport-width ||  
| viewport-width || || no
|}
|}


Line 260: Line 278:


const options = {
const options = {
     host: 'kaminari.click',
     host: 'kaminari.systems',
     port: 443,
     port: 443,
     path: '/v1/pingtest',
     path: '/v1/pingtest',

Latest revision as of 07:59, 17 September 2026

Other languages:

Подробнее о настройке S2S ping — в коротком видео: https://www.loom.com/share/a6cc760c91c94520a024e6b3891720ff

Общий алгоритм работы

  1. Пользователь приходит на ваш сайт. Вы генерируете уникальный kmnrId и отстукиваетесь с ним на сервер Kaminari на URL /ping, мы сохраняем данные в кэш.
  2. Затем вы показываете пользователю страницу с нашим JS-скриптом, добавив в вызов скрипта тот же самый kmnrId.
  3. Мы собираем данные о пользователе и шлём их на сервер Kaminari.
  4. На сервере мы проверяем в кэше:
    1. Если там есть запись с аналогичным kmnrId (пришедшая на /ping), мы склеиваем данные из кеша с результатами проверки и пишем их в статистику.
    2. Если записи с таким kmnrId нет, мы ждём пять минут. Если вторая запись так и не приходит, мы пишем в статистику то, что есть.
    3. Так же мы периодически проверяем кэш и ищем просроченные клики, пришедшие на /ping, но так и оставшиеся без пары. Если нам не удалось никак их проверить, мы пишем их в стату со статусом «Технические потери».

General workflow

  1. The user arrives at your website. You generate a unique kmnrId and send it to Kaminari server via /ping URL, and we save the data in the cache.
  2. Then you show the user a page with our JavaScript script, adding the same kmnrId to the script call.
  3. We collect user data and send it to the server.
  4. On the server, we check in the cache:
    1. If there is a record with a similar kmnrId (coming from /ping), we combine the data from the cache with the results of the check and write them to the statistics.
    2. If there is no record with such an kmnrId, we wait up to five minutes. If the second record still does not arrive, we write what we have in the statistics.
    3. We also periodically check the cache and look for expired clicks that came to /ping but remained unpaired. If we couldn't verify them in any way, we write them to statistics with the status "Technical Losses."

Настройка на стороне клиента

Отправка данных на https://kaminari.systems/v2/ping

Когда пользователь приходит на страницу, необходимо на бэкенде сгенерировать kmnrId — уникальный идентификатор показа.

Затем с помощью PHP, Python, NodeJS — в зависимости от того, на чём у вас написан сайт — послать на URL https://kaminari.systems/v2/ping инициализирующую информацию.

Запрос может не быть принят с первого раз (в таком случае сервер пришлёт статус 204), мы советуем слать запрос в цикле до получения ответа со статусом 200.

Данные должны слаться методом POST в формате JSON.

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

Название Описание параметра Обязательный или нет
kmnrId Рандомный идентификатор показа. Генерируется на стороне клиента. Это может быть всё, что угодно — UUID, случайное число, случайная текстовая строка. Должна слаться в виде строки. да
kmnrKey Идентификатор интеграции, в рамках которой анализируется показ. да
sub1 Заполенные суб-метки. Если какие-то метки вы не используете, их слать не обязательно. нет
sub2 ... нет
sub3 ... нет
sub4 ... нет
sub5 ... нет
sub6 ... нет
sub7 ... нет

Также в этот запрос должны быть добавлены следующие заголовки, полученные от пользователя:

Название Описание
user-agent user agent пользователя yes
referer страница, с которой пришёл пользователь no
accept-language язык интерфейса браузера yes
x-original-ip реальный IP пользователя yes
x-forwarded-for IP yes
x-real-ip IP no
x-requested-with no
sec-ch-ua-arch no
sec-ch-ua no
sec-ch-ua-full-version no
device-memory no
dpr no
sec-ch-ua-mobile no
sec-ch-ua-model no
sec-ch-ua-platform no
sec-ch-ua-platform-version no
viewport-width no

Пример curl-запроса:

curl 'https://kaminari.systems/v2/ping' \
  -H 'accept: application/json' \
  -H 'accept-language: en-US,en;q=0.9,uk;q=0.8' \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json;charset=UTF-8' \
  -H 'origin: https://test.com' \
  -H 'pragma: no-cache' \
  -H 'referer: https://test.com/' \
  -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36' \
  -H 'x-original-ip: 127.0.0.1' \
  -H 'x-forwarded-for: 192.168.0.1' \
  -H 'sec-ch-ua-arch: "x86"' \
  -H 'sec-ch-ua: "Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"' \
  -H 'sec-ch-ua-full-version: "129.0.6668.100"' \
  -H 'device-memory: 8' \
  -H 'dpr: 2' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-model: ""' \
  -H 'sec-ch-ua-platform: "macOS"' \
  -H 'sec-ch-ua-platform-version: "14.5.0"' \
  -H 'viewport-width: 981' \
  --data-raw '{"kmnrKey":"XXXXXXXX","kmnrId":"1125570260","sub1":"test","sub2":"1001","sub3":"10","sub4":"1385282124113622","sub5":"222","sub6":"555666","sub7":"8833705265931305"}' 
  --compressed

Пример на PHP:

$url = 'https://kaminari.systems/v2/ping';
$ch = curl_init( $url );
$payload = json_encode([
    'kmnrKey' => 'XXXXXXXX',
    'kmnrId' => '1125570260',
    'sub1' => 'test',
    'sub2' => '1001',
    'sub3' => '10',
    'sub4' => '1385282124113622',
    'sub5' => '222',
    'sub6' => '555666',
    'sub7' => '8833705265931305',
]);

curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload );
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
    'Content-Type:application/json;charset=UTF-8',
    'Accept-Language:' . $_SERVER['HTTP_ACCEPT_LANGUAGE'],
    'User-Agent:' . $_SERVER['HTTP_USER_AGENT'],
    isset($_SERVER['HTTP_REFERER']) ? 'Referer:' . $_SERVER['HTTP_REFERER'] : '',
    'X-Original-Ip:' . $_SERVER['REMOTE_ADDR'],
    isset($_SERVER['X_FORWARDED_FOR']) ? 'X-Forwarded-For:' . $_SERVER['X_FORWARDED_FOR'] : '',
    isset($_SERVER['X_REQUESTED_WITH']) ? 'X-Requested-With:' . $_SERVER['X_REQUESTED_WITH'] : '',
    isset($_SERVER['HTTP_SEC_CH_UA_ARCH']) ? 'Sec-CH-UA-Arch:' . $_SERVER['HTTP_SEC_CH_UA_ARCH'] : '',
    isset($_SERVER['HTTP_SEC_CH_UA']) ? 'Sec-CH-UA:' . $_SERVER['HTTP_SEC_CH_UA'] : '',
    isset($_SERVER['HTTP_SEC_CH_UA_FULL_VERSION']) ? 'Sec-CH-UA-Full-Version:' . $_SERVER['HTTP_SEC_CH_UA_FULL_VERSION'] : '',
    isset($_SERVER['HTTP_DEVICE_MEMORY']) ? 'Device-Memory:' . $_SERVER['HTTP_DEVICE_MEMORY'] : '',
    isset($_SERVER['HTTP_DPR']) ? 'DPR:' . $_SERVER['HTTP_DPR'] : '',
    isset($_SERVER['HTTP_SEC_CH_UA_MOBILE']) ? 'Sec-CH-UA-Mobile:' . $_SERVER['HTTP_SEC_CH_UA_MOBILE'] : '',
    isset($_SERVER['HTTP_SEC_CH_UA_MODEL']) ? 'Sec-CH-UA-Model:' . $_SERVER['HTTP_SEC_CH_UA_MODEL'] : '',
    isset($_SERVER['HTTP_SEC_CH_UA_PLATFORM']) ? 'Sec-CH-UA-Platform:' . $_SERVER['HTTP_SEC_CH_UA_PLATFORM'] : '',
    isset($_SERVER['HTTP_SEC_CH_UA_PLATFORM_VERSION']) ? 'Sec-CH-UA-Platform-Version:' . $_SERVER['HTTP_SEC_CH_UA_PLATFORM_VERSION'] : '',
    isset($_SERVER['HTTP_VIEWPORT_WIDTH']) ? 'Viewport-Width:' . $_SERVER['HTTP_VIEWPORT_WIDTH'] : '',
]);
curl_exec($ch);
curl_close($ch);

Добавление kmnrId в скрипт

Сгенерированный kmnrId, а так же kmnrKey и субки затем нужно прокинуть в вызов JS-скрипта на странице.

<script>
    window.kmnr = {
        kmnrKey: 'XXXXXXXX',
        kmnrId: '1125570260',
        sub1: 'test',
        sub2: '1001',
        sub3: '10',
        sub4: '1385282124113622',
        sub5: '222',
        sub6: '555666',
        sub7: '8833705265931305',
    };

    var kmnrSc = document.createElement('script');
    var kmnrPrnt = document.getElementsByTagName('head')[0] || document.body;
    kmnrSc.setAttribute('async', true);
    kmnrSc.setAttribute('charset', 'utf-8');
    kmnrSc.src = '//kaminari.systems/v1/script.js?kmnrKey=' + window.kmnr.kmnrKey;
    kmnrPrnt && kmnrPrnt.appendChild(kmnrSc);
</script>

Тестирование

Для тестирования отправления данных и соответствия их API можно воспользоваться URL https://kaminari.systems/v1/pingtest

Пример на PHP:

$url = 'https://kaminari.systems/v1/pingtest';
try {
    $ch = curl_init( $url );
    $payload = json_encode([
        'kmnrKey' => 'XXXXXXXX',
        'kmnrId' => (string)mt_rand(),
        'sub1' => 'test',
        'sub2' => '1001',
        'sub3' => '10',
        'sub4' => '40',
        'sub5' => '555',
        'sub6' => '6',
        'sub7' => '77777',
    ]);

    curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload );
    curl_setopt( $ch, CURLOPT_HTTPHEADER, [
        'Content-Type:application/json',
        'Accept-Language:' . $_SERVER['HTTP_ACCEPT_LANGUAGE'],
        'User-Agent:' . $_SERVER['HTTP_USER_AGENT'],
        'DPR:2',
        isset($_SERVER['HTTP_REFERER']) ? 'Referer:' . $_SERVER['HTTP_REFERER'] : 'Referer:""',
    ]);
    curl_setopt( $ch, CURLOPT_HEADER, true);
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
    
    $response = curl_exec($ch);
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $header = substr($response, 0, $header_size);
    $body = substr($response, $header_size);
    $body = str_replace('", "', '",<br />    "', $body);
    $body = str_replace('{ "', '{<br />    "', $body);
    echo "<pre>1. Response length: $header_size</pre>";
    echo "<pre>2. Response body: $body</pre>";

    'curl error: ' . curl_error($ch);
    curl_close($ch);
} catch (Exception $e) {
    echo "Error register User: {$e->getMessage()}";
}

Response :

1. Response length: 287
2. Response body: {"errors": {
    "X-Forwarded-For":"recommended to add in request headers",
    "X-Real-IP":"recommended to add in request headers",
    "sec-ch-ua-arch":"recommended to add in request headers",
    "sec-ch-ua":"recommended to add in request headers",
    "sec-ch-ua-full-version":"recommended to add in request headers",
    "device-memory":"recommended to add in request headers",
    "sec-ch-ua-mobile":"recommended to add in request headers",
    "sec-ch-ua-model":"recommended to add in request headers",
    "sec-ch-ua-platform":"recommended to add in request headers",
    "sec-ch-ua-platform-version":"recommended to add in request headers",
    "viewport-width":"recommended to add in request headers"}}

Пример на Node.js:

const https = require('https');

const payload = JSON.stringify({
    'kmnrKey': 'XXXXXXXX',
    'kmnrId': (Math.random() + 1).toString(36).substring(9),
    'sub1': 'test',
    'sub2': '1001',
    'sub3': '10',
    'sub4': '40',
    'sub5': '555',
    'sub6': '6',
    'sub7': '77777',
});

const options = {
    host: 'kaminari.systems',
    port: 443,
    path: '/v1/pingtest',
    method: 'POST',
    headers: { 
        'Content-Type': 'application/json',
        'Content-Length': Buffer.byteLength(payload),
        'Accept-Language': 'en-US,en;q=0.5',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0',
        'DPR': '2',
        'Referer': '""',
    }
};

const req = https
    .request(options, (res) => {
        let data = '';

        res.on('data', (chunk) => {
            data += chunk;
        });
        
        res.on('end', () => {
            try {
                data = JSON.parse(data);
                console.log(data);
            } catch {
                console.log(data);
            }
        });
    });

req.on('error', (err) => {
    console.log("Error: " + err.message);
});
req.write(payload);
req.end();

Ответ:

{
  errors: {
    'X-Forwarded-For': 'recommended to add in request headers',
    'X-Real-IP': 'recommended to add in request headers',
    'sec-ch-ua-arch': 'recommended to add in request headers',
    'sec-ch-ua': 'recommended to add in request headers',
    'sec-ch-ua-full-version': 'recommended to add in request headers',
    'device-memory': 'recommended to add in request headers',
    'sec-ch-ua-mobile': 'recommended to add in request headers',
    'sec-ch-ua-model': 'recommended to add in request headers',
    'sec-ch-ua-platform': 'recommended to add in request headers',
    'sec-ch-ua-platform-version': 'recommended to add in request headers',
    'viewport-width': 'recommended to add in request headers'
  }
}