Product-Led Growth Playbook: как построить AI-powered PQL scoring с нуля

Что такое Product Qualified Lead (PQL)?

Product Qualified Lead — это пользователь бесплатного тарифа, который продемонстрировал намерение купить через поведение в продукте: выполнил activation events, достиг лимитов использования или пригласил коллег. PQL scoring переводит этот поведенческий сигнал в числовой скоринг, который показывает sales-команде, кому звонить и почему.

TL;DR

  • -MQL scoring не работает в PLG, потому что демографические и маркетинговые сигналы слабо предсказывают конверсию: пользователь может зарегистрироваться с Gmail, игнорировать все письма и всё равно конвертироваться в платного.
  • -PQL score складывается из трёх компонентов: activation score (40%), engagement score (35%) и firmographic score (25%), каждый из которых основан на продуктовых событиях, аналитике использования и enrichment-данных.
  • -Activation events необходимо определять для каждого продукта отдельно через когортный анализ — сравнение поведения конвертированных и ушедших пользователей в первые 14 дней — их нельзя заимствовать из кейсов.
  • -LLM-обогащение превращает числовой скоринг в sales briefing: гипотеза о use case, сигнал расширения, рекомендуемое начало разговора и фактор риска — всё на основе реальных данных использования.
  • -Калибруйте модель ежемесячно: фиксированные пороги деградируют за 2–3 месяца по мере того, как activation-паттерны меняются с выходом новых фич и сезонными изменениями поведения.

Компании с Product-Led Growth конвертируют free-to-paid эффективнее, чем sales-led. Но только при условии, что sales получает правильных лидов в правильный момент. Большинство команд до сих пор передают в CRM всех, кто зарегистрировался, вместо тех, кто готов покупать.

Product Qualified Lead (PQL) отличается от MQL принципиально. MQL заполнил форму. PQL использовал продукт и показал поведение, предсказывающее конверсию. Статья о том, как построить PQL scoring model с нуля: от определения activation events до автоматической классификации через LLM и синхронизации с CRM.

Что такое PQL scoring и почему MQL scoring не работает в PLG

MQL scoring опирается на демографию и маркетинговые взаимодействия: должность, размер компании, скачал whitepaper, посетил вебинар. В PLG-модели эти сигналы слабые. Пользователь мог зарегистрироваться с gmail-адресом, ни разу не открыть маркетинговое письмо и при этом активно использовать продукт каждый день.

PQL scoring использует product usage data как первичный сигнал. Три категории данных:

Activation signals. Пользователь выполнил ключевые действия, коррелирующие с долгосрочным retention. Для Slack это отправка 2000 сообщений командой. Для Dropbox — загрузка файла с одного устройства и доступ с другого. Для каждого продукта activation events уникальны.

Engagement depth. Частота использования, количество feature adoptions, время в продукте. Не просто “логинился 5 раз”, а “использовал 3+ core features за последние 7 дней”.

Expansion signals. Пользователь приглашает коллег, создаёт команду, упирается в лимиты free-плана, экспортирует данные. Эти действия сигнализируют о растущей ценности продукта для организации.

Определение activation events с помощью LLM

Первый шаг — найти activation events для конкретного продукта. Классический подход: ретроспективный анализ когорт. Берём пользователей, которые конвертировались в платных, и сравниваем их поведение с теми, кто ушёл. Это предполагает чистую event taxonomy - без единых имён событий и свойств когортные сравнения возвращают шум.

SQL-запрос для базовой когортной разбивки (если SQL для вас новый - паттерны ниже разобраны в SQL для продактов):

WITH converted_users AS (
    SELECT user_id, MIN(subscription_start) AS conversion_date
    FROM subscriptions
    WHERE plan != 'free'
    GROUP BY user_id
),
user_events AS (
    SELECT
        e.user_id,
        e.event_name,
        COUNT(*) AS event_count,
        COUNT(DISTINCT DATE(e.created_at)) AS active_days,
        CASE WHEN cu.user_id IS NOT NULL THEN 'converted' ELSE 'churned' END AS cohort
    FROM events e
    LEFT JOIN converted_users cu ON e.user_id = cu.user_id
    WHERE e.created_at <= COALESCE(cu.conversion_date, e.created_at + INTERVAL '30 days')
      AND e.created_at >= e.user_created_at
      AND e.created_at <= e.user_created_at + INTERVAL '14 days'
    GROUP BY e.user_id, e.event_name, cohort
)
SELECT
    event_name,
    cohort,
    AVG(event_count) AS avg_count,
    PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY event_count) AS median_count,
    COUNT(DISTINCT user_id) AS users
FROM user_events
GROUP BY event_name, cohort
ORDER BY event_name, cohort;

Запрос сравнивает поведение конвертированных и ушедших пользователей в первые 14 дней. Результат — таблица, где видно, какие события статистически значимо отличаются между когортами.

Проблема: таблица содержит десятки событий, и не все корреляции означают причинно-следственную связь. LLM помогает интерпретировать результаты и предложить гипотезы.

Промпт для анализа activation events:

Ты — product analyst. Проанализируй данные когортного анализа для SaaS-продукта.

Контекст продукта: [описание продукта, основные use cases, ключевые features]

Данные (event_name | cohort | avg_count | median_count | users):
[вставить результат SQL-запроса]

Задачи:
1. Определи 3-5 событий с наибольшей разницей между когортами converted и churned
2. Для каждого события предложи пороговое значение (threshold), при котором вероятность конверсии значительно возрастает
3. Исключи события, которые являются следствием конверсии, а не её предиктором
4. Предложи комбинации событий (activation milestones), которые формируют "aha moment"

Формат ответа: JSON с полями event_name, threshold, confidence, reasoning

LLM не заменяет статистический анализ. Он ускоряет интерпретацию и генерирует гипотезы, которые дальше валидируются A/B-тестами. Результат промпта — набор activation events с пороговыми значениями.

Архитектура PQL scoring model

PQL score — число от 0 до 100. Складывается из трёх компонентов с разными весами:

КомпонентВесИсточник данных
Activation score40%Product events
Engagement score35%Usage analytics
Firmographic score25%Enrichment data

Activation score

Бинарная проверка: выполнил пользователь activation event или нет. Каждый activation event имеет свой вес внутри компонента.

WITH activation_checks AS (
    SELECT
        u.user_id,
        u.email,
        u.company_domain,
        -- Activation event 1: создал проект
        MAX(CASE WHEN e.event_name = 'project_created' THEN 1 ELSE 0 END) AS created_project,
        -- Activation event 2: пригласил коллегу
        MAX(CASE WHEN e.event_name = 'team_invite_sent' THEN 1 ELSE 0 END) AS invited_teammate,
        -- Activation event 3: использовал core feature 3+ раз
        CASE WHEN COUNT(CASE WHEN e.event_name = 'core_feature_used' THEN 1 END) >= 3
             THEN 1 ELSE 0 END AS used_core_feature,
        -- Activation event 4: настроил интеграцию
        MAX(CASE WHEN e.event_name = 'integration_connected' THEN 1 ELSE 0 END) AS connected_integration
    FROM users u
    LEFT JOIN events e ON u.user_id = e.user_id
        AND e.created_at >= u.created_at
        AND e.created_at <= u.created_at + INTERVAL '14 days'
    GROUP BY u.user_id, u.email, u.company_domain
)
SELECT
    user_id,
    email,
    company_domain,
    ROUND(
        (created_project * 30 +
         invited_teammate * 30 +
         used_core_feature * 25 +
         connected_integration * 15)
    ) AS activation_score
FROM activation_checks;

Веса activation events назначаются на основе корреляции с конверсией из когортного анализа. invited_teammate обычно получает высокий вес, потому что приглашение коллег — сильный предиктор покупки в B2B SaaS.

Engagement score

Измеряет глубину и частоту использования. В отличие от activation score, engagement score непрерывный и пересчитывается ежедневно.

WITH daily_usage AS (
    SELECT
        user_id,
        COUNT(DISTINCT DATE(created_at)) AS active_days_last_14,
        COUNT(DISTINCT event_name) AS unique_features_used,
        COUNT(*) AS total_events,
        MAX(created_at) AS last_active_at
    FROM events
    WHERE created_at >= CURRENT_DATE - INTERVAL '14 days'
    GROUP BY user_id
),
engagement_scored AS (
    SELECT
        user_id,
        -- Frequency: дни активности из 14
        LEAST(active_days_last_14 / 14.0 * 100, 100) AS frequency_score,
        -- Breadth: количество уникальных features (нормализовано к общему числу)
        LEAST(unique_features_used / 8.0 * 100, 100) AS breadth_score,
        -- Recency: штраф за неактивность
        CASE
            WHEN last_active_at >= CURRENT_DATE - INTERVAL '1 day' THEN 100
            WHEN last_active_at >= CURRENT_DATE - INTERVAL '3 days' THEN 75
            WHEN last_active_at >= CURRENT_DATE - INTERVAL '7 days' THEN 40
            ELSE 10
        END AS recency_score
    FROM daily_usage
)
SELECT
    user_id,
    ROUND(frequency_score * 0.4 + breadth_score * 0.35 + recency_score * 0.25) AS engagement_score
FROM engagement_scored;

Нормализация breadth_score зависит от количества core features в продукте. В примере 8 — это число нужно заменить на реальное количество отслеживаемых фич.

Firmographic score

Product usage data даёт основной сигнал. Дополнительные 25% — данные о компании. Размер, индустрия, технологический стек. Эти данные поступают из enrichment-сервисов (Clearbit, Apollo, Clay).

SELECT
    u.user_id,
    CASE
        WHEN c.employee_count > 500 THEN 30
        WHEN c.employee_count > 100 THEN 25
        WHEN c.employee_count > 20 THEN 20
        WHEN c.employee_count > 5 THEN 15
        ELSE 5
    END +
    CASE
        WHEN c.industry IN ('technology', 'saas', 'fintech') THEN 25
        WHEN c.industry IN ('ecommerce', 'media', 'education') THEN 20
        WHEN c.industry IN ('healthcare', 'manufacturing') THEN 15
        ELSE 10
    END +
    CASE
        WHEN c.estimated_revenue > 10000000 THEN 25
        WHEN c.estimated_revenue > 1000000 THEN 20
        WHEN c.estimated_revenue > 100000 THEN 15
        ELSE 5
    END +
    CASE
        WHEN u.email NOT LIKE '%gmail.com'
         AND u.email NOT LIKE '%yahoo.com'
         AND u.email NOT LIKE '%hotmail.com' THEN 20
        ELSE 0
    END AS firmographic_score
FROM users u
LEFT JOIN companies c ON u.company_domain = c.domain;

Корпоративный email даёт +20 баллов. Грубый, но эффективный фильтр: пользователь с рабочим доменом конвертируется в платного значительно чаще, чем с бесплатным почтовым сервисом.

Финальный PQL score и классификация через LLM

Композитный score:

SELECT
    a.user_id,
    a.email,
    ROUND(
        a.activation_score * 0.40 +
        e.engagement_score * 0.35 +
        f.firmographic_score * 0.25
    ) AS pql_score,
    CASE
        WHEN ROUND(a.activation_score * 0.40 + e.engagement_score * 0.35 + f.firmographic_score * 0.25) >= 75 THEN 'hot'
        WHEN ROUND(a.activation_score * 0.40 + e.engagement_score * 0.35 + f.firmographic_score * 0.25) >= 50 THEN 'warm'
        WHEN ROUND(a.activation_score * 0.40 + e.engagement_score * 0.35 + f.firmographic_score * 0.25) >= 25 THEN 'nurture'
        ELSE 'monitor'
    END AS pql_tier
FROM activation_scores a
JOIN engagement_scores e ON a.user_id = e.user_id
JOIN firmographic_scores f ON a.user_id = f.user_id;

Четыре тира:

  • Hot (75+): Передать sales немедленно. Высокая вероятность конверсии.
  • Warm (50-74): In-app upsell triggers. Автоматические подсказки о premium features.
  • Nurture (25-49): Onboarding drip campaigns. Подтолкнуть к activation events.
  • Monitor (0-24): Наблюдение. Не тратить ресурсы sales.

Распределение по тирам - сама по себе метрика, которую стоит трекать. PLG-дашборд с динамикой hot/warm/nurture во времени показывает, улучшается activation или регрессирует, ещё до того как это видно в выручке.

Числовой score решает задачу приоритизации. Но sales-команде нужен контекст: почему этот пользователь горячий, какой use case, о чём говорить на первом звонке. LLM решает эту задачу.

Промпт для генерации sales context:

Ты — sales intelligence assistant. На основе product usage data сгенерируй briefing для sales-менеджера.

Данные пользователя:
- Email: {email}
- Компания: {company_name} ({industry}, {employee_count} сотрудников)
- PQL score: {pql_score} (tier: {pql_tier})
- Activation events выполнены: {completed_activations}
- Activation events не выполнены: {missing_activations}
- Самые используемые features: {top_features}
- Дней активности за 14 дней: {active_days}
- Количество приглашённых коллег: {invited_count}
- Текущий план: {plan}
- Упирается в лимиты: {hit_limits}

Сгенерируй:
1. Use case hypothesis (1 предложение): какую задачу решает пользователь
2. Expansion signal (1 предложение): почему готов к апгрейду
3. Recommended opening (1 предложение): с чего начать разговор
4. Risk factor (1 предложение): что может помешать конверсии

Формат: JSON. Без общих фраз. Только конкретика на основе данных.

Результат — структурированный JSON, который записывается в CRM-запись контакта. Sales-менеджер видит не просто “score: 82”, а конкретный контекст: “Пользователь ежедневно использует feature X для задачи Y, пригласил 4 коллег, упирается в лимит API-запросов. Рекомендация: предложить Enterprise план с фокусом на team collaboration.”

Автоматический pipeline: от events до CRM

Архитектура pipeline состоит из четырёх этапов:

Product Events → Event Store → Score Calculator → CRM Sync
     │                              │                  │
  Segment/                     Scheduled job        HubSpot/
  Amplitude/                   (hourly/daily)       Salesforce
  PostHog                                           API

Этап 1: сбор событий

Product analytics (Segment, Amplitude, PostHog) отправляет события в warehouse. Минимальный набор полей для каждого события:

{
  "user_id": "usr_abc123",
  "event_name": "core_feature_used",
  "properties": {
    "feature": "report_builder",
    "duration_seconds": 340
  },
  "timestamp": "2026-03-25T14:22:00Z",
  "context": {
    "company_domain": "acme.com"
  }
}

Этап 2: расчёт score

Scheduled job (cron, Airflow, dbt) выполняет SQL-запросы из предыдущих разделов. Результат — таблица pql_scores с полями user_id, pql_score, pql_tier, activation_score, engagement_score, firmographic_score, calculated_at.

CREATE TABLE pql_scores AS
SELECT
    a.user_id,
    a.email,
    a.company_domain,
    a.activation_score,
    e.engagement_score,
    f.firmographic_score,
    ROUND(a.activation_score * 0.40 + e.engagement_score * 0.35 + f.firmographic_score * 0.25) AS pql_score,
    CASE
        WHEN ROUND(a.activation_score * 0.40 + e.engagement_score * 0.35 + f.firmographic_score * 0.25) >= 75 THEN 'hot'
        WHEN ROUND(a.activation_score * 0.40 + e.engagement_score * 0.35 + f.firmographic_score * 0.25) >= 50 THEN 'warm'
        WHEN ROUND(a.activation_score * 0.40 + e.engagement_score * 0.35 + f.firmographic_score * 0.25) >= 25 THEN 'nurture'
        ELSE 'monitor'
    END AS pql_tier,
    CURRENT_TIMESTAMP AS calculated_at
FROM activation_scores a
JOIN engagement_scores e ON a.user_id = e.user_id
JOIN firmographic_scores f ON a.user_id = f.user_id;

Этап 3: LLM-обогащение

Для пользователей с pql_tier = 'hot' или при переходе из warm в hot запускается LLM-классификация. Вызов API происходит batch-ом, не в реальном времени. Стоимость: ~$0.01-0.03 за одного пользователя при использовании GPT-5.4-mini (актуальные цены на platform.openai.com).

import json
from openai import OpenAI

client = OpenAI()

def generate_sales_context(user_data: dict) -> dict:
    prompt = f"""Ты — sales intelligence assistant...
    [промпт из предыдущего раздела с подставленными данными]"""

    response = client.chat.completions.create(
        model="gpt-5.4-mini",
        messages=[{"role": "user", "content": prompt}],
        response_format={"type": "json_object"},
        temperature=0.3
    )
    return json.loads(response.choices[0].message.content)

Низкая temperature (0.3) обеспечивает стабильность выводов. JSON response format гарантирует парсинг без ошибок. Если используется мульти-провайдерная архитектура с LiteLLM, вызов проходит через единый прокси с fallback на альтернативные модели. Мониторинг качества промптов — через Langfuse.

Этап 4: синхронизация с CRM

HubSpot и Salesforce поддерживают custom properties через API. Минимальный набор полей для синхронизации:

import hubspot
from hubspot.crm.contacts import SimplePublicObjectInput

client = hubspot.Client.create(access_token="your_token")

def sync_pql_to_hubspot(user_email: str, pql_data: dict, sales_context: dict):
    properties = {
        "pql_score": str(pql_data["pql_score"]),
        "pql_tier": pql_data["pql_tier"],
        "pql_activation_score": str(pql_data["activation_score"]),
        "pql_engagement_score": str(pql_data["engagement_score"]),
        "pql_use_case": sales_context.get("use_case_hypothesis", ""),
        "pql_expansion_signal": sales_context.get("expansion_signal", ""),
        "pql_recommended_opening": sales_context.get("recommended_opening", ""),
        "pql_last_calculated": pql_data["calculated_at"]
    }

    contact = SimplePublicObjectInput(properties=properties)

    client.crm.contacts.basic_api.update(
        contact_id=get_contact_id_by_email(user_email),
        simple_public_object_input=contact
    )

При переходе пользователя в tier hot CRM автоматически создаёт задачу для sales-менеджера. Чем быстрее outreach после PQL-сигнала, тем выше win rate — это хорошо изученная закономерность в B2B продажах.

Калибровка модели и пороговых значений

PQL scoring model требует регулярной калибровки. Два ключевых параметра:

Precision. Какой процент hot PQL реально конвертируется. Целевой показатель: >30%. Если precision ниже 20%, пороги слишком низкие или веса компонентов неправильные.

Recall. Какой процент реальных конверсий модель предсказала как hot/warm. Целевой показатель: >70%. Если recall ниже 50%, модель упускает паттерны поведения.

SQL-запрос для оценки precision и recall:

WITH predictions AS (
    SELECT
        p.user_id,
        p.pql_tier,
        CASE WHEN s.user_id IS NOT NULL THEN 1 ELSE 0 END AS actually_converted
    FROM pql_scores p
    LEFT JOIN subscriptions s ON p.user_id = s.user_id
        AND s.plan != 'free'
        AND s.subscription_start > p.calculated_at
        AND s.subscription_start <= p.calculated_at + INTERVAL '30 days'
    WHERE p.calculated_at >= CURRENT_DATE - INTERVAL '90 days'
)
SELECT
    pql_tier,
    COUNT(*) AS total_users,
    SUM(actually_converted) AS converted,
    ROUND(SUM(actually_converted)::NUMERIC / COUNT(*) * 100, 1) AS precision_pct,
    ROUND(SUM(actually_converted)::NUMERIC /
        (SELECT COUNT(DISTINCT user_id) FROM subscriptions
         WHERE plan != 'free'
         AND subscription_start >= CURRENT_DATE - INTERVAL '90 days') * 100, 1
    ) AS recall_pct
FROM predictions
GROUP BY pql_tier
ORDER BY pql_tier;

Калибровку проводят ежемесячно. Поведение пользователей меняется: новые features сдвигают activation patterns, сезонность влияет на engagement. Фиксированные пороги деградируют за 2-3 месяца.

Автоматизация калибровки: тот же LLM анализирует drift в метриках и предлагает корректировки весов. Финальное решение — за продуктовой командой.

Экономика PQL scoring

Стоимость внедрения зависит от инфраструктуры.

КомпонентСтоимость (месяц)
Event tracking (Segment/PostHog)$0-300 (free tier покрывает до 10K MAU)
Data warehouse (BigQuery/Snowflake)$50-200
LLM API (GPT-5.4-mini для hot leads)~$10-50 (при ~1000 hot PQL/месяц)
CRM (HubSpot/Salesforce)Существующая подписка
Orchestration (Airflow/cron)$0-50

Итого: $60-600/месяц для компании до 50K MAU. Сравнение с готовыми решениями: Pocus, Correlated стоят от $500/месяц при аналогичном MAU. Собственная реализация дешевле, но требует инженерных ресурсов на поддержку.

Типичные ошибки при внедрении PQL scoring

Слишком много activation events. 3-5 событий достаточно. Модель с 15+ событиями переобучается на шум и теряет предсказательную силу.

Игнорирование account-level aggregation. В B2B покупает компания, не пользователь. Если 5 сотрудников одной компании активны, но каждый получает индивидуальный score 30, модель упускает горячий аккаунт. Агрегируйте scores на уровне company_domain.

Статичные пороги. Пороги hot/warm/nurture должны адаптироваться к объёму, который sales-команда может обработать. Если hot PQL — 500 в неделю, а sales-команда из 3 человек, порог нужно поднять. Лучший PQL scoring бесполезен, если leads не обрабатываются вовремя.

Отсутствие feedback loop. Sales-менеджеры должны отмечать качество PQL в CRM (converted, not relevant, bad timing). Без обратной связи модель не улучшается. Минимальный feedback: бинарная оценка “полезный лид / не полезный” после каждого outreach.

Score без контекста. Число “82” ничего не говорит менеджеру. LLM-generated sales context превращает абстрактный score в actionable intelligence. Это не опция, а обязательный элемент.

Что дальше

PQL scoring — отправная точка. Следующие шаги:

  1. Predictive model. Заменить rule-based scoring на ML-модель (logistic regression или gradient boosting), обученную на исторических конверсиях. Rule-based работает на старте, ML масштабируется лучше.
  2. Real-time scoring. Перейти от batch (ежедневного) к stream processing. PQL score обновляется при каждом событии, sales получает уведомление в момент перехода пользователя в hot tier.
  3. In-product actions. Score управляет не только CRM, но и UX: paywall triggers, premium feature hints, персонализированный onboarding.
  4. Multi-touch attribution. Объединение PQL score с маркетинговыми touchpoints для полной картины customer journey.

PQL scoring model с LLM-обогащением собирается за 2-3 спринта. Первые результаты видны через 30 дней после запуска: sales-команда работает с меньшим количеством лидов, но конверсия каждого лида выше. Это суть Product-Led Growth: продукт сам квалифицирует покупателей.


Нужна помощь с PQL scoring? Я помогаю стартапам внедрять AI-решения и строить продукты — belov.works.

FAQ

Как организовать PQL scoring в B2B-продукте, где несколько пользователей от одной компании активны на бесплатном плане?

Агрегируйте на уровне домена компании, а не отдельного пользователя. Суммируйте или усредняйте scores всех пользователей с одного домена и добавляйте множитель за размер команды: пять активных пользователей с acme.com — более сильный сигнал, чем один пользователь с высоким индивидуальным score. SQL-паттерн: GROUP BY company_domain, и аккаунт используется как единица скоринга. Индивидуальные scores пользователей по-прежнему важны для персонализации sales briefing, но назначение тира должно отражать поведение на уровне аккаунта.

Какая минимальная версия PQL scoring, которую команда из двух человек может запустить за неделю?

Начните с одного бинарного правила: если пользователь выполнил не менее двух конкретных activation events за 14 дней И зарегистрирован с корпоративным доменом — флаг как PQL. Без весов, тиров и LLM-обогащения. Раз в неделю экспортируйте список в таблицу и звоните лично. Это даёт 80% ценности полноценной scoring-модели и требует одного дня на внедрение. Переходите к полному SQL-скорингу только после того, как подтвердите, что activation events действительно предсказывают конверсию в вашем продукте.

Как PQL scoring взаимодействует с self-serve и product-led sales — должен ли он применяться к обоим?

Да, но с разными выходными действиями. Для self-serve (пользователь конвертируется без контакта с sales) PQL scoring управляет in-product триггерами: какое upsell-сообщение показать, когда открыть pricing page, какую фичу разблокировать в trial. Для product-led sales (менеджер лично связывается) PQL scoring показывает, кому звонить и что говорить. Один и тот же базовый score управляет обоими сценариями — разница только в том, какое действие срабатывает при пересечении порога.