Оформление
Передача конверсий (runtime)
Этот метод позволяет программно сообщить Sales Ninja, что клиент достиг цели. Применяется в случаях, когда достижение цели происходит не на сайте: в мобильном приложении, в CRM, в backend-сценарии, при импорте исторических данных и т.п.
Функционал — аналог офлайн-конверсий в Яндекс.Метрике.
Описание метода
http
POST https://api.sales-ninja.me/public/{source}/v1.0/goals/reach
Headers:
X-SN-TOKEN: <ваш токен проекта>
Content-Type: application/jsonПараметр {source} — mobile или backend (см. начало работы). Любое другое значение → 400.
Тело запроса
json
{
"goalId": "299837db-9b51-45a4-996b-844d3fd05bbd",
"customerId": "user-42-from-your-system",
"createdOn": "2026-04-15T12:23:25.367Z",
"ip": "185.237.80.128",
"params": {
"revenue": "12350",
"netProfit": "900"
}
}Примеры тела
Полный вариант:
json
{
"goalId": "299837db-9b51-45a4-996b-844d3fd05bbd",
"customerId": "2eccd743-4164-4892-a416-dc5c16f44971",
"createdOn": "2026-04-15T12:23:25.367Z",
"ip": "185.237.80.128",
"params": {
"revenue": "12350",
"netProfit": "900"
}
}Минимально достаточный вариант:
json
{
"goalId": "299837db-9b51-45a4-996b-844d3fd05bbd",
"customerId": "2eccd743-4164-4892-a416-dc5c16f44971"
}Поля
goalId (обязательно)
Уникальный идентификатор цели в системе Sales Ninja (не в вашей CRM/аналитике). Это GUID, например 299837db-9b51-45a4-996b-844d3fd05bbd. Получить его можно из адресной строки редактора цели:
text
https://app.sales-ninja.me/goal/<id будет тут>/editioncustomerId (обязательно)
Тот же строковый идентификатор, который вы передаёте в personalizations/apply и ab-tests/apply.
На сайте с бандлом:
js
const customerId = await ninja('getCustomerIdAsync')Для серверной интеграции — сохраняйте свой стабильный id рядом с записью о клиенте.
createdOn (опционально)
Время совершения конверсии в UTC (ISO 8601). Поле на проводе — createdOn, не createdOnUtc. Если не передано — берётся текущее серверное время.
ip (опционально)
IP пользователя, совершившего конверсию. Для {source}=mobile при отсутствии ip в теле подставляется IP из заголовков соединения; для backend — только из тела.
params (опционально)
Плоский словарь строк для обогащения конверсии (выручка, прибыль, UTM-подобные метки и т.п.).
Значения обязательно строки:
"12350", не12350. Максимум 48 ключей.
Поля customUserScopeParams, customPageScopeParams, sessionId не поддерживаются — передайте нужные ключи через params.
Ответ
При успехе — 200 OK с пустым телом. Конверсия принимается асинхронно и появится в аналитике через короткое время (обычно секунды; на большом потоке — минуты).
При ошибке — см. Runtime-ошибки.
Примеры кода
bash
curl -X POST "https://api.sales-ninja.me/public/backend/v1.0/goals/reach" \
-H "X-SN-TOKEN: $SN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"goalId": "299837db-9b51-45a4-996b-844d3fd05bbd",
"customerId": "2eccd743-4164-4892-a416-dc5c16f44971",
"createdOn": "2026-04-15T12:23:25Z",
"params": {"revenue": "12350", "netProfit": "900"}
}'js
async function reachGoal({ goalId, customerId, revenue, netProfit }) {
const res = await fetch(
`https://api.sales-ninja.me/public/backend/v1.0/goals/reach`,
{
method: 'POST',
headers: {
'X-SN-TOKEN': process.env.SN_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
goalId,
customerId,
createdOn: new Date().toISOString(),
params: {
revenue: String(revenue),
netProfit: String(netProfit),
},
}),
}
);
if (!res.ok) {
throw new Error(`reachGoal failed: ${res.status} ${await res.text()}`);
}
}python
import os, requests
from datetime import datetime, timezone
def reach_goal(goal_id: str, customer_id: str, revenue: float, net_profit: float) -> None:
r = requests.post(
"https://api.sales-ninja.me/public/backend/v1.0/goals/reach",
headers={"X-SN-TOKEN": os.environ["SN_TOKEN"]},
json={
"goalId": goal_id,
"customerId": customer_id,
"createdOn": datetime.now(timezone.utc).isoformat(),
"params": {
"revenue": str(revenue),
"netProfit": str(net_profit),
},
},
timeout=15,
)
r.raise_for_status()Идемпотентность и дубли
API не дедуплицирует одинаковые конверсии автоматически. Если интегратор может ретраить запрос — сохраняйте, какие конверсии уже отправлены. Дубликат с тем же customerId/goalId будет принят как ещё одна конверсия.