S2S ping: Difference between revisions

From Wiki Kaminari Click
No edit summary
No edit summary
Line 1: Line 1:
[[S2S ping en|English version]]
<languages/>
<translate>
= 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."


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


= Настройка на стороне клиента =
== Sending data to https://kaminari.systems/v2/ping ==
When a user visits the page, it is necessary to generate a unique display <code>kmnrId</code> on the client-side backend.


== Отправка данных на https://kaminari.systems/v2/ping ==
Then, using PHP, Python, NodeJS, depending on the technology your website is built on, send initializing information to the https://kaminari.systems/v2/ping in the background.
Когда пользователь приходит на страницу, необходимо на бэкенде сгенерировать <code>kmnrId</code> — уникальный идентификатор показа.  


Затем с помощью PHP, Python, NodeJS — в зависимости от того, на чём у вас написан сайт — послать на URL https://kaminari.systems/v2/ping инициализирующую информацию.
The request may not be accepted on the first attempt (in which case, the server will respond with a 204 status), so we recommend sending the request in a loop until you receive a response with a 200 status.


Запрос может не быть принят с первого раз (в таком случае сервер пришлёт статус 204), мы советуем слать запрос в цикле до получения ответа со статусом 200.
The data should be sent using the POST method in JSON format.


Данные должны слаться методом POST в формате JSON.
List of parameters:
 
Список параметров:


{| class="wikitable"
{| class="wikitable"
|-
|-
! Название !! Описание параметра !! Обязательный?
! Parameter Name !! Parameter Description !! Mandatory?
|-
|-
| kmnrId || Рандомный идентификатор показа. Генерируется на стороне клиента. Это может быть всё, что угодно — UUID, случайное число, случайная текстовая строка. '''Должна слаться в виде строки.''' || да
| kmnrId || Random impression identifier. Generated on the client side. It can be anything - UUID, random number, random string of text. '''Must be sent as a string.''' || yes
|-
|-
| kmnrKey || Идентификатор интеграции, в рамках которой анализируется показ. || да
| kmnrKey || Integration identifier within which the impression is analyzed. || yes
|-
|-
| sub1 || Заполенные суб-метки. Если какие-то метки вы не используете, их слать не обязательно. || нет
| sub1 || Filled sub-tags. If you do not use certain tags, there is no need to send them. || no
|-
|-
| sub2 || ... || нет
| sub2 || ... || нет
Line 46: Line 46:
|}
|}


Также в этот запрос должны быть добавлены следующие заголовки, полученные от пользователя:
In addition, the following headers obtained from the user should be added to this request:
{| class="wikitable"
{| class="wikitable"
|-
|-
! Название !! Описание
! Parameter Name !! Parameter Description
|-
|-
| user-agent || user agent пользователя
| user-agent || User agent
|-
|-
| referer || страница, с которой пришёл пользователь
| referer || Page the user came from
|-
|-
| accept-language || язык интерфейса браузера
| accept-language || Browser interface language
|-
|-
| x-original-ip || реальный IP пользователя
| x-original-ip || Real user IP
|-
|-
| x-forwarded-for || IP
| x-forwarded-for || IP
Line 84: Line 84:
|}
|}


Пример curl-запроса:
Example in CURL:
<pre>
<pre>
curl 'https://kaminari.systems/v2/ping' \
curl 'https://kaminari.systems/v2/ping' \
Line 99: Line 99:
</pre>
</pre>


Пример на PHP:
Example in PHP:
<pre>
<pre>
$url = 'https://kaminari.systems/v2/ping';
$url = 'https://kaminari.systems/v2/ping';
Line 126: Line 126:
</pre>
</pre>


== Добавление kmnrId в скрипт ==
== Adding kmnrId to the script ==
Сгенерированный <code>kmnrId</code>, а так же <code>kmnrKey</code> и субки затем нужно прокинуть в вызов JS-скрипта на странице.
The generated <code>kmnrId</code>, as well as the <code>kmnrKey</code> and sub-tags, should then be passed into the call of the JavaScript script on the page.


<pre>
<pre>
Line 152: Line 152:
</pre>
</pre>


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


Для тестирования отправления данных и соответствия их API можно воспользоваться URL https://kaminari.systems/v1/pingtest
For testing data transmission and ensuring their compatibility with the API, you can use the following URL: https://kaminari.systems/v1/pingtest


=== Пример на PHP: ===
=== Example in PHP: ===
<pre>
<pre>
$url = 'https://kaminari.systems/v1/pingtest';
$url = 'https://kaminari.systems/v1/pingtest';
Line 200: Line 200:
</pre>
</pre>


Ответ:
Response :
<pre>
<pre>
1. Response length: 287
1. Response length: 287
Line 217: Line 217:
</pre>
</pre>


=== Пример на Node.js: ===
=== Example in Node.js: ===
<pre>
<pre>
const https = require('https');
const https = require('https');
Line 273: Line 273:
</pre>
</pre>


Ответ:
Response:
<pre>
<pre>
{
{
Line 292: Line 292:
</pre>
</pre>
[[Category:Features]]
[[Category:Features]]
</translate>

Revision as of 02:11, 19 September 2023

Other languages:

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."

Client-side configuration

Sending data to https://kaminari.systems/v2/ping

When a user visits the page, it is necessary to generate a unique display kmnrId on the client-side backend.

Then, using PHP, Python, NodeJS, depending on the technology your website is built on, send initializing information to the https://kaminari.systems/v2/ping in the background.

The request may not be accepted on the first attempt (in which case, the server will respond with a 204 status), so we recommend sending the request in a loop until you receive a response with a 200 status.

The data should be sent using the POST method in JSON format.

List of parameters:

Parameter Name Parameter Description Mandatory?
kmnrId Random impression identifier. Generated on the client side. It can be anything - UUID, random number, random string of text. Must be sent as a string. yes
kmnrKey Integration identifier within which the impression is analyzed. yes
sub1 Filled sub-tags. If you do not use certain tags, there is no need to send them. no
sub2 ... нет
sub3 ... нет
sub4 ... нет
sub5 ... нет
sub6 ... нет
sub7 ... нет

In addition, the following headers obtained from the user should be added to this request:

Parameter Name Parameter Description
user-agent User agent
referer Page the user came from
accept-language Browser interface language
x-original-ip Real user IP
x-forwarded-for IP
x-real-ip IP
sec-ch-ua-arch
sec-ch-ua
sec-ch-ua-full-version
device-memory
dpr
sec-ch-ua-mobile
sec-ch-ua-model
sec-ch-ua-platform
sec-ch-ua-platform-version
viewport-width

Example in CURL:

curl 'https://kaminari.systems/v2/ping' \
  -H 'accept: application/json' \ 
  -H 'accept-language: en-US,en;q=0.9' \ 
  -H 'cache-control: no-cache' \ 
  -H 'content-type: text/plain;charset=UTF-8' \
  -H 'origin: https://test.com' \ 
  -H 'pragma: no-cache' \ 
  -H 'referer: https://test.com/' \ 
  -H 'user-agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36' 
  --data-raw '{"kmnrKey":"XXXXXXXX","kmnrId":"1125570260","sub1":"test","sub2":"1001","sub3":"10","sub4":"1385282124113622","sub5":"222","sub6":"555666","sub7":"8833705265931305"}' 
  --compressed

Example in 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',
    'Accept-Language:' . $_SERVER['HTTP_ACCEPT_LANGUAGE'],
    'User-Agent:' . $_SERVER['HTTP_USER_AGENT'],
    isset($_SERVER['HTTP_REFERER']) ? 'Referer:' . $_SERVER['HTTP_REFERER'] : '',
]);
curl_exec($ch);
curl_close($ch);

Adding kmnrId to the script

The generated kmnrId, as well as the kmnrKey and sub-tags, should then be passed into the call of the JavaScript script on the page.

<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>

Testing

For testing data transmission and ensuring their compatibility with the API, you can use the following URL: https://kaminari.systems/v1/pingtest

Example in 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"}}

Example in 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.click',
    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();

Response:

{
  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'
  }
}