Перейти к содержанию

Интеграция M1.TOP с Keitaro: API и постбэк

Как подключить M1.TOP (бывший M1-shop) к Keitaro: отправка лидов по API send_order, subid в метке W, глобальный постбэк, статусы new, approved, declined…

Интеграция M1.TOP с Keitaro: API и постбэк

M1.TOP (раньше M1-shop) работает и в 2026 году: на сайте сеть описывает себя как CPA-сеть в нутре и прямого рекламодателя в ЛатАме и ЕС. Чтобы лить на её офферы со своего лендинга через Keitaro, нужны три вещи: обработчик формы, который отправляет заявку на https://m1.top/send_order/, метка с subid клика и глобальный постбэк из M1 в трекер.

Ниже рабочая схема на октябрь 2026 года: какие ID взять в кабинете, готовый api.php, ссылка постбэка, таблица статусов и разбор ошибок.

Что даёт интеграция по API

  • Лендинг лежит у вас или в Keitaro, заявка уходит в M1 напрямую. Формы, прелендинги и тексты можно менять без кабинета сети.
  • Keitaro получает лид, апрув и отмену по каждому клику. ROI считается по креативу, площадке и ключу, а не по офферу в целом.
  • Причину отмены видно в кабинете M1 на вкладке «Заказы», а сам факт отмены приходит в трекер тем же постбэком.

Что взять в кабинете M1

Параметр APIЧто этоГде найти
refID вебмастеракабинет M1, данные профиля
api_keyAPI-ключ вебмастеракабинет M1, данные профиля
product_idID товара (оффера) для APIкарточка оффера
s, w, tметки для своих данныхзаполняете сами, одна из них под subid
Таблица прокручивается вбок

Проще всего сверить ref и ключ по лендингу, скачанному из кабинета: в документации Keitaro по передаче конверсий в партнёрские сети по API сказано, что в таком архиве уже прописаны API key и ID вебмастера. Если поля не нашли, спросите поддержку @M1_Supp, её контакт указан в FAQ сети.

Сервер M1 сразу сообщает, какого параметра не хватает. При проверке 1 октября 2026 года запрос без product_id вернул {"result":"error","message":"No Product ID"}, а запрос с пустым ID вебмастера получил HTTP 400 и "No Webmaster ID".

Форма на лендинге

В форме нужны поля name и phone и скрытое поле с subid клика. Если лендинг загружен в Keitaro архивом, трекер сам подставит значение вместо {subid}, так работает локальный лендинг.

<form action="api.php" method="post">
  <input type="text" name="name" placeholder="Nombre" required>
  <input type="tel" name="phone" placeholder="Teléfono" required>
  <input type="hidden" name="subid" value="{subid}">
  <button type="submit">Pedir</button>
</form>

Если лендинг лежит на своём хостинге, добавьте к его адресу в Keitaro ?subid={subid}, а в форме выведите значение так: value="<?= htmlspecialchars($_GET['subid'] ?? '', ENT_QUOTES) ?>". Тогда файл лендинга должен быть index.php.

Обработчик api.php для M1

Положите файл рядом с index.html или index.php и заполните три константы в начале.

<?php
// api.php: принимает заявку с лендинга и отправляет её в M1.TOP
const API_URL    = 'https://m1.top/send_order/';
const REF        = 'ВАШ_ID_ВЕБМАСТЕРА';  // ID вебмастера (ref) из профиля M1
const API_KEY    = 'ВАШ_API_KEY';        // API-ключ из профиля M1
const PRODUCT_ID = 'ID_ТОВАРА_API';      // «ID товара (API)» из карточки оффера
const BEHIND_CF  = false;                // true, если домен лендинга за Cloudflare
const TIMEOUT    = 3;                    // секунды: лимит Keitaro для локальных лендингов
const LOG_FILE   = __DIR__ . '/m1-leads.log';

if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
    http_response_code(405);
    exit;
}

$name  = trim((string)($_POST['name'] ?? ''));
$phone = preg_replace('/\D+/', '', (string)($_POST['phone'] ?? ''));
$subid = preg_replace('/[^A-Za-z0-9_-]/', '', (string)($_POST['subid'] ?? ''));

if ($name === '' || strlen($phone) < 7) {
    header('Location: error.php');
    exit;
}

$ip = $_SERVER['REMOTE_ADDR'] ?? '';
if (BEHIND_CF && !empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
    $ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
}

$order = [
    'ref'        => REF,
    'api_key'    => API_KEY,
    'product_id' => PRODUCT_ID,
    'name'       => $name,
    'phone'      => $phone,
    'ip'         => $ip,
    'w'          => $subid,   // метка W: subid клика Keitaro, как в шаблоне трекера
    's'          => (string)($_POST['s'] ?? ''),  // метки S и T свободны
    't'          => (string)($_POST['t'] ?? ''),
];

$ch = curl_init(API_URL);
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => http_build_query($order),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => TIMEOUT,
    CURLOPT_TIMEOUT        => TIMEOUT,
]);
$body = curl_exec($ch);
$code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
$resp = is_string($body) ? json_decode($body, true) : null;

// Ошибка у M1 приходит в виде {"result":"error","message":"..."}
$ok = $code === 200 && is_array($resp) && ($resp['result'] ?? '') !== 'error';

file_put_contents(LOG_FILE, date('c') . " http=$code subid=$subid "
    . substr((string)$body, 0, 300) . "\n", FILE_APPEND | LOCK_EX);

header('Location: ' . ($ok ? 'success.php' : 'error.php'));
exit;

Что важно в коде:

  • subid клика уходит в метку w. Её же использует встроенный шаблон M1 в Keitaro, поэтому в постбэке она вернётся как {w}.
  • Телефон очищается до цифр, пустое имя или короткий номер сразу ведут на error.php, запрос в сеть не уходит.
  • IP берётся из REMOTE_ADDR. Заголовку CF-Connecting-IP скрипт верит только при BEHIND_CF = true: без Cloudflare перед сайтом этот заголовок может подделать кто угодно.
  • В исправленном примере нужны HTTP 200, корректный JSON-массив и отсутствие явной ошибки. Это упрощённая проверка: она ещё не подтверждает создание заказа по позитивному контракту API. Перед рабочим запуском сверяйте положительный ответ и идентификатор заказа с актуальным API сети. Код проверяет, что в ответе нет "result":"error". В m1-leads.log пишется фрагмент ответа сети. Имя и телефон не добавляются отдельными полями, но могут оказаться в самом ответе. Маскируйте персональные данные и секреты до записи.
  • Таймаут 3 секунды. Такой лимит Keitaro ставит PHP-лендингам, загруженным в трекер. На своём хостинге его можно поднять до 10 секунд.

Страницы success.php и error.php нужны обязательно. Готовые шаблоны есть в статьях про мультиязычную страницу «Спасибо за заказ» и мультиязычную страницу ошибки. Закройте доступ к файлу лога из браузера или вынесите его за пределы папки сайта.

Постбэк M1 в Keitaro

Шаг 1. Партнёрская сеть в Keitaro

  1. Откройте «Партнерские сети», нажмите «Создать» и выберите шаблон M1-shop.ru: в трекере он до сих пор назван по старому домену.
  2. В поле «Параметры для оффера» оставьте w={subid}. Оно нужно, если оффер M1 стоит в потоке редиректом. При отправке по API subid передаёт api.php.
  3. Скопируйте Postback URL. Адрес трекера и ключ берутся из раздела «Настройки» → «Postback URL».
Настройка постбеков в кейтаро и m1.top

Готовая ссылка с обучением статусов по документации Keitaro о postback:

https://ВАШ_ТРЕКЕР/POSTBACK_KEY/postback?subid={w}&status={status}&lead_status=new&sale_status=approved&rejected_status=declined&payout={web_total}&currency={currency}&tid={order_id}&from=m1.top

Параметр tid с номером заказа нужен на случай, если с одного клика пришло два заказа: без него вторая конверсия перезапишет первую.

Шаг 2. Глобальный постбэк в кабинете M1

  1. Откройте раздел «Глобальный Postback» (в кабинете он лежит в «Инструментах»).
  2. Вставьте ссылку из Keitaro в поле Postback URL. Лимит поля 2000 символов.
  3. Отметьте «Создание заказа», «Подтверждение заказа» и «Отмена заказа». Без первой галочки трекер не увидит лиды, без третьей не увидит отмены.
  4. Метод передачи: GET.
  5. Нажмите «Сохранить». Постбэк, заданный в потоке, главнее глобального: если в потоке стоит своя ссылка, глобальная для него не сработает.
настройка постбеков для партнерки m1.top и keitaro

Макросы, которые M1 подставляет в ссылку (список со страницы «Глобальный Postback»):

МакросЧто передаёт
{s}, {w}, {t}метки S, W, T из заказа
{order_id}номер заказа
{status}статус: new, approved, declined
{trash}флаг треша: 1 или 0
{web_total}размер выплаты за заказ, передаётся в любом статусе
{lead_profit}прибыль вебмастера, если заказ подтверждён
{currency}валюта: rub или usd
{uip}, {lead_time}, {lead_date}IP пользователя, время заказа в unix и в формате Y-m-d H:i:s
Таблица прокручивается вбок

Статусы M1 и типы конверсий Keitaro

Статус M1Что значитТип в KeitaroОбучение в ссылке
newзаказ создан, колл-центр обзванивает клиентаLeadlead_status=new
approvedзаказ подтверждёнSalesale_status=approved
declinedотказ или трешRejectedrejected_status=declined
Таблица прокручивается вбок

Треш M1 тоже отдаёт статусом declined, отличить его можно по {trash}=1. Если хотите видеть треш отдельно, допишите в ссылку &sub_id_20={trash} и стройте отчёт по этому параметру. По FAQ M1 в треш уходят заказы с некорректными данными, с ГЕО вне условий оффера, с неработающим или городским номером и с ответом «не заказывал». В отклонённые попадают дубли, недозвоны после лимита звонков и отказы клиента.

Отсекать повторные заявки до отправки в сеть помогает фильтр из статьи про дубли лидов.

Ошибки и где их искать

Где видноСообщениеПричина и решение
m1-leads.logNo Webmaster ID (HTTP 400)пустой или неверный ref, проверьте константу REF
m1-leads.logNo Product IDне передан product_id, возьмите его в карточке оффера
m1-leads.logno refсеть не приняла пару ID вебмастера и ключа, сверьте оба значения
m1-leads.loghttp=0запрос не дошёл или упёрся в таймаут, проверьте исходящие соединения хостинга
Keitaro: «Обслуживание» → «Логи» → «Postbacks»Click for subid REPLACE not foundв постбэке не та метка или subid не дошёл до M1: сверьте w в api.php и subid={w} в ссылке
Keitaro, логи постбэковPostback status is not setв ссылке нет status={status}
Keitaro, логи постбэковConversion type not foundстатус без обучения: добавьте lead_status, sale_status, rejected_status
Keitaro, логи постбэковIncorrect postback codeв ссылке устаревший ключ, скопируйте его заново в «Настройки» → «Postback URL»
Таблица прокручивается вбок

Расшифровка ошибок трекера взята из раздела Keitaro про устранение проблем с postback. Если в логе Keitaro пусто, а в M1 заказы есть, проверьте галочку «Создание заказа» и нет ли в потоке своего постбэка.

Частые вопросы

M1.TOP и M1-shop это одна сеть?

Да. Старый домен m1-shop.ru сейчас отвечает ошибкой 403, кабинет и API работают на m1.top. В Keitaro шаблон по-прежнему называется M1-shop.ru.

Какую метку выбрать под subid: s, w или t?

Любую, но одну и ту же в обработчике и в ссылке постбэка. Мы используем w, потому что её ждёт шаблон Keitaro.

Можно ли отправлять заказы со своего лендинга?

Да. В FAQ M1 прямо сказано, что заказы со своих лендингов и сайтов принимаются через iframe-форму или API.

Почему тестовый постбэк не создаёт конверсию в Keitaro?

По документации Keitaro партнёрские сети в тестовых постбэках не передают реальный subid клика. Проверяйте связку реальной заявкой по ссылке кампании.

Где посмотреть, почему заказ отклонён?

В кабинете M1 на вкладке «Заказы». Там же можно прослушать записи разговоров по отклонённым лидам на колл-центре M1.

Редакция BoostClicks

Материалы о настройке рекламы, трекинге и автоматизации: инструкции, примеры кода и расчёты с указанием условий проверки.