S2S ping

From Wiki Kaminari Click
This page contains changes which are not marked for translation.
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 ... no
sub3 ... no
sub4 ... no
sub5 ... no
sub6 ... no
sub7 ... no

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

Parameter Name Parameter Description Mandatory?
user-agent User agent yes
referer Page the user came from no
accept-language Browser interface language yes
x-original-ip Real user IP yes
x-forwarded-for IP yes
x-real-ip IP 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

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

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;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['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);

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