S2S ping
General workflow
- The user arrives at your website. You generate a unique
kmnrIdand 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
kmnrIdto 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
kmnrId(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
kmnrId, 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."
- If there is a record with a similar
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'
}
}