#CRM-аналитика: воронка
📊 Сложность: beginner | Скоупы: crm | Стек: Python, requests
#Что делаем
Пишем Python-скрипт, который выгружает все сделки из CRM через Вайбкод Entity API, группирует их по стадиям воронки и рассчитывает конверсию между этапами и средний чек. Результат выводится в консоль в виде наглядной таблицы. Полезно для быстрого анализа эффективности продаж без сторонних BI-инструментов.
#Необходимо
- API-ключ Вайбкод с правами
crm - Python 3.8+
- Пакет:
requests
#Полный код
# crm_analytics.py
# Анализ воронки продаж: конверсия по стадиям и средний чек
import os
import requests
from collections import defaultdict
API_KEY = os.environ["VIBE_API_KEY"]
BASE_URL = os.environ["VIBE_BASE_URL"] # например https://vibecode.bitrix24.tech
HEADERS = {
"X-Api-Key": API_KEY,
}
# Названия стадий воронки (стандартные для Bitrix24)
# Примечание: на порталах с несколькими воронками стадии имеют C-префикс:
# C2:WON, C4:NEW и т.д. Функция get_stage_name() обрабатывает оба формата.
STAGE_NAMES = {
"NEW": "Новая",
"PREPARATION": "Подготовка",
"PREPAYMENT_INVOICE": "Счёт на предоплату",
"EXECUTING": "В работе",
"FINAL_INVOICE": "Финальный счёт",
"WON": "Успешная",
"LOSE": "Проигранная",
}
def get_stage_name(stage_id):
"""Получает название стадии, обрабатывая C-префиксы множественных воронок"""
# C2:WON → WON, C4:NEW → NEW
base = stage_id.split(":")[-1] if ":" in stage_id else stage_id
return STAGE_NAMES.get(base, stage_id)
def fetch_all_deals():
"""Загружаем все сделки через Entity API с авто-пагинацией"""
all_deals = []
offset = 0
limit = 200
while True:
response = requests.get(
f"{BASE_URL}/v1/deals",
headers=HEADERS,
params={
"select": "id,stageId,amount,currency",
"limit": limit,
"offset": offset,
},
)
data = response.json()
deals = data.get("data", [])
all_deals.extend(deals)
# Если вернулось меньше limit — всё загружено
if len(deals) < limit:
break
offset += limit
return all_deals
def analyze_funnel(deals):
"""Группируем сделки по стадиям и считаем метрики"""
stages = defaultdict(lambda: {"count": 0, "total_amount": 0})
for deal in deals:
stage = deal.get("stageId", "UNKNOWN")
amount = float(deal.get("amount", 0) or 0)
stages[stage]["count"] += 1
stages[stage]["total_amount"] += amount
return stages
def print_funnel_report(stages, total_deals):
"""Выводим отчёт по воронке"""
print("\n" + "=" * 65)
print(" АНАЛИЗ ВОРОНКИ ПРОДАЖ")
print("=" * 65)
print(f"\n Всего сделок: {total_deals}\n")
# Порядок стадий для отображения
stage_order = [
"NEW", "PREPARATION", "PREPAYMENT_INVOICE",
"EXECUTING", "FINAL_INVOICE", "WON", "LOSE",
]
print(f" {'Стадия':<25} {'Кол-во':>8} {'Конверсия':>10} {'Ср. чек':>12}")
print(" " + "-" * 58)
for stage_id in stage_order:
if stage_id not in stages:
continue
info = stages[stage_id]
count = info["count"]
name = get_stage_name(stage_id)
# Конверсия относительно общего количества
conversion = (count / total_deals * 100) if total_deals > 0 else 0
# Средний чек
avg_check = info["total_amount"] / count if count > 0 else 0
# Визуальная шкала
bar = "█" * int(conversion / 3)
print(f" {name:<25} {count:>8} {conversion:>9.1f}% {avg_check:>11,.0f}₽")
print(f" {bar}")
# Итоговые метрики (суммируем все WON/LOSE стадии, включая C-префиксы)
won = {"count": 0, "total_amount": 0}
lost = {"count": 0, "total_amount": 0}
for sid, info in stages.items():
base = sid.split(":")[-1] if ":" in sid else sid
if base == "WON":
won["count"] += info["count"]
won["total_amount"] += info["total_amount"]
elif base == "LOSE":
lost["count"] += info["count"]
lost["total_amount"] += info["total_amount"]
closed = won["count"] + lost["count"]
print("\n" + "-" * 65)
print(f" Общая выручка (WON): {won['total_amount']:>15,.0f}₽")
if closed > 0:
win_rate = won["count"] / closed * 100
print(f" Win Rate: {win_rate:>14.1f}%")
if won["count"] > 0:
avg_won = won["total_amount"] / won["count"]
print(f" Средний чек (WON): {avg_won:>15,.0f}₽")
print("=" * 65)
def main():
print("📊 Загружаем сделки из CRM...")
deals = fetch_all_deals()
print(f" Загружено: {len(deals)} сделок")
stages = analyze_funnel(deals)
print_funnel_report(stages, len(deals))
if __name__ == "__main__":
main()
#Как это работает
- Скрипт загружает все сделки из CRM через Entity API (
GET /v1/deals) с авто-пагинацией через limit/offset. - Каждая сделка группируется по стадии (
stageId), подсчитывается количество и суммируется бюджет. - Для каждой стадии рассчитывается конверсия относительно общего числа сделок и средний чек.
- Результаты выводятся в виде текстовой таблицы с визуальными шкалами.
- Отдельно рассчитываются итоговые метрики: общая выручка, Win Rate и средний чек успешных сделок.
#Что можно улучшить
- Использовать
POST /v1/deals/aggregateсgroupBy: ["stageId"]вместо загрузки всех записей — быстрее и экономнее - Добавить фильтрацию по периоду (месяц, квартал, год) для сравнения динамики
- Экспортировать результат в CSV или Excel для дальнейшей работы
- Визуализировать воронку с помощью matplotlib или plotly