Python-скрипт: автоматизация BI-дашбордов и KPI-отчётов
Коротко: Python-скрипт для автоматизации BI-дашбордов подключается к API Яндекс.Метрики, Google Analytics и другим источникам, собирает данные о конверсиях и KPI, обрабатывает их и отправляет в дашборды. Экономит до 15 часов в неделю на ручную работу аналитика и снижает ошибки на 85%.
Содержание
- Зачем автоматизировать BI-дашборды с помощью Python?
- Как настроить Python-окружение для работы с аналитикой?
- Как подключить Python к Яндекс.Метрике и Google Analytics?
- Обработка данных и расчёт KPI в Python
- Автоматизация A/B тестов и отчётности
- Интеграция с BI-системами и дашбордами
- Как оптимизировать производительность и обработку ошибок?
Зачем автоматизировать BI-дашборды с помощью Python?
Каждый понедельник одно и то же — аналитик два часа собирает данные из разных систем, проверяет конверсии, считает KPI, обновляет дашборды. К среде накапливается куча мелких ошибок, к пятнице — полный хаос в цифрах.
Мы в DS495 столкнулись с этой проблемой у клиента из ритейла. Их команда тратила 15 часов в неделю на ручное обновление отчётов. Python-скрипт сократил это время до 30 минут в неделю — просто на проверку автоматически сгенерированных дашбордов.
Вот что даёт автоматизация аналитики через Python:
- Скорость: вместо 2-3 часов на сбор данных — 5 минут на автоматическое обновление
- Точность: исключаете человеческий фактор при копировании цифр между системами
- Свежесть данных: дашборды обновляются каждые 15 минут, а не раз в день
- Масштабируемость: один скрипт может обрабатывать десятки проектов
Python идеально подходит для аналитики благодаря богатой экосистеме библиотек: pandas для обработки данных, requests для API, plotly для визуализации. Плюс простой синтаксис — даже маркетологи осваивают базовые скрипты за неделю.
Как настроить Python-окружение для работы с аналитикой?
Начинаем с установки нужных библиотек. Я рекомендую создать отдельное виртуальное окружение — так избежите конфликтов версий:
# Создаём виртуальное окружение
python -m venv analytics_env
source analytics_env/bin/activate # для Linux/Mac
# или analytics_env\Scripts\activate для Windows
# Устанавливаем необходимые пакеты
pip install pandas numpy requests google-analytics-data google-auth plotly dash
Основные библиотеки для аналитики:
| Библиотека | Назначение | Почему важна |
|---|---|---|
| pandas | Обработка данных | Основа для работы с таблицами и временными рядами |
| requests | HTTP-запросы к API | Подключение к Яндекс.Метрике, CRM, другим системам |
| google-analytics-data | Google Analytics 4 | Официальная библиотека для GA4 Reporting API |
| plotly + dash | Интерактивные дашборды | Создание веб-дашбордов без фронтенд-разработки |
Структура проекта, которую мы используем:
analytics_project/
├── config/
│ ├── credentials.json
│ └── settings.py
├── data/
│ ├── raw/
│ └── processed/
├── scripts/
│ ├── connectors/
│ ├── processors/
│ └── dashboards/
└── main.py
В settings.py храним все настройки:
# settings.py
import os
from datetime import datetime, timedelta
# API настройки
YANDEX_METRIKA_TOKEN = os.getenv('YANDEX_TOKEN')
GOOGLE_ANALYTICS_CREDENTIALS = 'config/ga_credentials.json'
# Временные интервалы
DEFAULT_DATE_RANGE = 30 # дней назад
UPDATE_FREQUENCY = 15 # минут
# KPI пороги
CONVERSION_TARGET = 3.5 # %
BOUNCE_RATE_MAX = 65 # %
Как подключить Python к Яндекс.Метрике и Google Analytics?
Подключение к аналитическим системам — основа любого BI-скрипта. Начнём с Яндекс.Метрики, там API проще.
Подключение к Яндекс.Метрике
Сначала получаем OAuth-токен в интерфейсе Яндекс.Метрики. Затем создаём класс для работы с API:
import requests
import pandas as pd
from datetime import datetime, timedelta
class YandexMetrikaConnector:
def __init__(self, token, counter_id):
self.token = token
self.counter_id = counter_id
self.base_url = "https://api-metrika.yandex.net/stat/v1/data"
def get_traffic_data(self, start_date, end_date):
params = {
'id': self.counter_id,
'date1': start_date.strftime('%Y-%m-%d'),
'date2': end_date.strftime('%Y-%m-%d'),
'metrics': 'ym:s:visits,ym:s:pageviews,ym:s:users',
'dimensions': 'ym:s:date',
'oauth_token': self.token
}
response = requests.get(self.base_url, params=params)
data = response.json()
return self._process_response(data)
def _process_response(self, data):
rows = []
for item in data['data']:
date = item['dimensions'][0]['name']
metrics = item['metrics']
rows.append({
'date': pd.to_datetime(date),
'visits': metrics[0],
'pageviews': metrics[1],
'users': metrics[2]
})
return pd.DataFrame(rows)
Подключение к Google Analytics 4
GA4 сложнее — нужна аутентификация через сервисный аккаунт:
from google.analytics.data_v1beta import BetaAnalyticsDataClient
from google.analytics.data_v1beta.types import DateRange, Dimension, Metric, RunReportRequest
class GoogleAnalyticsConnector:
def __init__(self, property_id, credentials_path):
self.property_id = property_id
self.client = BetaAnalyticsDataClient.from_service_account_file(credentials_path)
def get_conversion_data(self, start_date, end_date):
request = RunReportRequest(
property=f"properties/{self.property_id}",
dimensions=[
Dimension(name="date"),
Dimension(name="source")
],
metrics=[
Metric(name="sessions"),
Metric(name="conversions"),
Metric(name="totalRevenue")
],
date_ranges=[DateRange(
start_date=start_date.strftime('%Y-%m-%d'),
end_date=end_date.strftime('%Y-%m-%d')
)]
)
response = self.client.run_report(request=request)
return self._process_ga_response(response)
Пошаговая инструкция для настройки Google Analytics API:
- Идите в Google Cloud Console и создайте новый проект
- Включите Google Analytics Reporting API
- Создайте сервисный аккаунт и скачайте JSON с ключами
- В Google Analytics добавьте email сервисного аккаунта как пользователя
- Скопируйте Property ID из настроек GA4
Нужна помощь с этой задачей? Команда DS495 решит её под ключ. Обсудить проект →
Обработка данных и расчёт KPI в Python
Когда данные из всех источников собраны, начинается самое интересное — их обработка и расчёт KPI. Тут pandas показывает себя во всей красе.
Объединение данных из разных источников
Обычная задача — совместить данные из Яндекс.Метрики, Google Analytics и CRM по датам:
def merge_analytics_data(ym_data, ga_data, crm_data):
# Приводим все даты к единому формату
ym_data['date'] = pd.to_datetime(ym_data['date'])
ga_data['date'] = pd.to_datetime(ga_data['date'])
crm_data['date'] = pd.to_datetime(crm_data['date'])
# Объединяем по дате
merged = ym_data.merge(ga_data, on='date', how='outer', suffixes=('_ym', '_ga'))
merged = merged.merge(crm_data, on='date', how='outer')
# Заполняем пропуски нулями
merged = merged.fillna(0)
return merged
def calculate_kpi(df):
# Конверсия из трафика в лиды
df['traffic_to_lead_conversion'] = (df['leads'] / df['visits_ym']) * 100
# Конверсия из лидов в продажи
df['lead_to_sale_conversion'] = (df['sales'] / df['leads']) * 100
# CAC (Customer Acquisition Cost)
df['cac'] = df['ad_spend'] / df['sales']
# LTV/CAC ratio
df['ltv_cac_ratio'] = df['average_ltv'] / df['cac']
# Средний чек
df['average_order_value'] = df['revenue'] / df['sales']
return df
Расчёт продвинутых метрик
Для e-commerce часто нужны когортный анализ и RFM-сегментация:
| Метрика | Формула | Норма |
|---|---|---|
| Retention Rate | Вернувшиеся пользователи / Новые пользователи | 20-40% |
| Churn Rate | 100% - Retention Rate | 60-80% |
| ARPU | Общая выручка / Количество пользователей | Зависит от ниши |
| ROAS | Выручка от рекламы / Затраты на рекламу | 4:1 и выше |
def cohort_analysis(df):
# Группируем пользователей по месяцу первой покупки
df['order_period'] = df['order_date'].dt.to_period('M')
df['cohort_group'] = df.groupby('user_id')['order_date'].transform('min').dt.to_period('M')
# Рассчитываем период относительно первой покупки
df['period_number'] = (df['order_period'] - df['cohort_group']).apply(attrgetter('n'))
# Строим таблицу когорт
cohort_data = df.groupby(['cohort_group', 'period_number'])['user_id'].nunique().reset_index()
cohort_counts = cohort_data.pivot(index='cohort_group', columns='period_number', values='user_id')
# Рассчитываем retention rates
cohort_sizes = cohort_counts.iloc[:, 0]
retention_rates = cohort_counts.divide(cohort_sizes, axis=0)
return retention_rates
Выявление аномалий в данных
Автоматическое выявление аномалий экономит кучу времени:
def detect_anomalies(df, column, threshold=2):
# Используем z-score для выявления выбросов
z_scores = np.abs(stats.zscore(df[column]))
anomalies = df[z_scores > threshold]
# Или более продвинутый метод — Isolation Forest
from sklearn.ensemble import IsolationForest
clf = IsolationForest(contamination=0.1, random_state=42)
anomaly_labels = clf.fit_predict(df[[column]].values)
df['is_anomaly'] = anomaly_labels == -1
return df
Автоматизация A/B тестов и отчётности
A/B тесты — головная боль любого аналитика. Постоянно нужно проверять статистическую значимость, следить за sample size, считать lift. Python автоматизирует всё это.
Автоматический мониторинг A/B тестов
import scipy.stats as stats
from math import sqrt
class ABTestMonitor:
def __init__(self, test_name, control_group, test_group):
self.test_name = test_name
self.control_group = control_group
self.test_group = test_group
def calculate_significance(self, control_conversions, control_visitors,
test_conversions, test_visitors):
# Рассчитываем конверсии
control_rate = control_conversions / control_visitors
test_rate = test_conversions / test_visitors
# Z-test для двух пропорций
pooled_prob = (control_conversions + test_conversions) / (control_visitors + test_visitors)
pooled_se = sqrt(pooled_prob * (1 - pooled_prob) * (1/control_visitors + 1/test_visitors))
z_score = (test_rate - control_rate) / pooled_se
p_value = 2 * (1 - stats.norm.cdf(abs(z_score)))
# Lift
lift = ((test_rate - control_rate) / control_rate) * 100
return {
'control_rate': control_rate,
'test_rate': test_rate,
'lift': lift,
'p_value': p_value,
'is_significant': p_value < 0.05,
'confidence_level': (1 - p_value) * 100
}
def sample_size_calculation(self, baseline_rate, min_detectable_effect, power=0.8, alpha=0.05):
# Рассчитываем нужный размер выборки
effect_size = min_detectable_effect / 100
from statsmodels.stats.power import ttest_power
# Это упрощённый расчёт, в реальности используйте специализированные библиотеки
n_per_group = stats.norm.ppf(1 - alpha/2)**2 * 2 * baseline_rate * (1 - baseline_rate) / effect_size**2
return int(n_per_group)
Автоматическая отчётность
Создаём систему, которая каждую неделю отправляет отчёт о результатах тестов:
def generate_weekly_report(ab_tests, email_list):
report = []
for test in ab_tests:
if test.is_active():
results = test.get_current_results()
status = "🟢 Winning" if results['lift'] > 5 and results['is_significant'] else "🟡 Monitoring"
if results['p_value'] > 0.8:
status = "🔴 Losing"
report.append({
'test_name': test.name,
'status': status,
'lift': f"{results['lift']:.1f}%",
'confidence': f"{results['confidence_level']:.0f}%",
'sample_size': test.get_sample_size()
})
# Отправляем email через SMTP
send_email_report(report, email_list)
def send_email_report(report_data, recipients):
# Здесь код для отправки email с таблицей результатов
pass
Интеграция с BI-системами и дашбордами
Самая крутая часть — когда все данные автоматически попадают в красивые дашборды. Можно интегрироваться с Tableau, Power BI, или создать собственный дашборд на Dash.
Создание интерактивного дашборда с Plotly Dash
import dash
from dash import dcc, html, Input, Output
import plotly.graph_objs as go
import plotly.express as px
app = dash.Dash(__name__)
app.layout = html.Div([
html.H1("Marketing Analytics Dashboard"),
# Фильтры
html.Div([
dcc.DatePickerRange(
id='date-picker-range',
start_date=datetime.now() - timedelta(days=30),
end_date=datetime.now()
),
dcc.Dropdown(
id='channel-dropdown',
options=[
{'label': 'Google Ads', 'value': 'google'},
{'label': 'Facebook Ads', 'value': 'facebook'},
{'label': 'Yandex Direct', 'value': 'yandex'}
],
value=['google', 'facebook'],
multi=True
)
], style={'margin': '20px'}),
# KPI карточки
html.Div([
html.Div([
html.H3(id='total-conversions'),
html.P("Total Conversions")
], className='kpi-card'),
html.Div([
html.H3(id='conversion-rate'),
html.P("Conversion Rate")
], className='kpi-card'),
html.Div([
html.H3(id='cac'),
html.P("CAC")
], className='kpi-card'),
], style={'display': 'flex'}),
# Графики
dcc.Graph(id='conversion-trend'),
dcc.Graph(id='channel-performance'),
# Автообновление каждые 15 минут
dcc.Interval(
id='interval-component',
interval=15*60*1000, # в миллисекундах
n_intervals=0
)
])
@app.callback(
[Output('total-conversions', 'children'),
Output('conversion-rate', 'children'),
Output('cac', 'children'),
Output('conversion-trend', 'figure'),
Output('channel-performance', 'figure')],
[Input('date-picker-range', 'start_date'),
Input('date-picker-range', 'end_date'),
Input('channel-dropdown', 'value'),
Input('interval-component', 'n_intervals')]
)
def update_dashboard(start_date, end_date, selected_channels, n):
# Загружаем свежие данные
df = load_analytics_data(start_date, end_date, selected_channels)
# KPI
total_conversions = f"{df['conversions'].sum():,}"
conversion_rate = f"{(df['conversions'].sum() / df['visits'].sum() * 100):.1f}%"
cac = f"${df['ad_spend'].sum() / df['conversions'].sum():.0f}"
# Тренд конверсий
daily_data = df.groupby('date').agg({
'conversions': 'sum',
'visits': 'sum'
}).reset_index()
daily_data['conversion_rate'] = daily_data['conversions'] / daily_data['visits'] * 100
trend_fig = px.line(daily_data, x='date', y='conversion_rate',
title='Conversion Rate Trend')
# Производительность каналов
channel_data = df.groupby('channel').agg({
'conversions': 'sum',
'ad_spend': 'sum'
}).reset_index()
channel_data['cac'] = channel_data['ad_spend'] / channel_data['conversions']
channel_fig = px.bar(channel_data, x='channel', y='cac',
title='CAC by Channel')
return total_conversions, conversion_rate, cac, trend_fig, channel_fig
if __name__ == '__main__':
app.run_server(debug=True)
Интеграция с существующими BI-системами
Для интеграции с Tableau или Power BI обычно используем промежуточную базу данных:
- PostgreSQL — для структурированных данных и сложных запросов
- ClickHouse — для больших объёмов аналитических данных
- Google BigQuery — облачное решение с хорошей интеграцией с GA4
import psycopg2
from sqlalchemy import create_engine
def save_to_database(df, table_name):
# Подключение к PostgreSQL
engine = create_engine('postgresql://user:password@localhost:5432/analytics')
# Сохраняем DataFrame в базу
df.to_sql(table_name, engine, if_exists='replace', index=False)
print(f"Данные сохранены в таблицу {table_name}")
# Автоматическое обновление каждые 15 минут
import schedule
def update_analytics_data():
# Загружаем данные из всех источников
ym_data = yandex_connector.get_traffic_data(start_date, end_date)
ga_data = google_connector.get_conversion_data(start_date, end_date)
# Обрабатываем и рассчитываем KPI
processed_data = process_analytics_data(ym_data, ga_data)
# Сохраняем в базу для BI-систем
save_to_database(processed_data, 'daily_analytics')
# Запускаем каждые 15 минут
schedule.every(15).minutes.do(update_analytics_data)
Как оптимизировать производительность и обработку ошибок?
Когда скрипт работает с десятками API и обрабатывает миллионы строк данных, производительность становится критической. Вот проверенные методы оптимизации.
Кеширование и инкрементальная загрузка
Не загружайте каждый раз все данные с начала времён. Используйте инкрементальную загрузку:
import pickle
from datetime import datetime, timedelta
class DataCache:
def __init__(self, cache_dir='cache/'):
self.cache_dir = cache_dir
os.makedirs(cache_dir, exist_ok=True)
def get_last_update_date(self, source_name):
cache_file = f"{self.cache_dir}/{source_name}_last_update.pickle"
if os.path.exists(cache_file):
with open(cache_file, 'rb') as f:
return pickle.load(f)
return datetime.now() - timedelta(days=90) # По умолчанию 90 дней назад
def save_last_update_date(self, source_name, date):
cache_file = f"{self.cache_dir}/{source_name}_last_update.pickle"
with open(cache_file, 'wb') as f:
pickle.dump(date, f)
def load_cached_data(self, cache_key):
cache_file = f"{self.cache_dir}/{cache_key}.pickle"
if os.path.exists(cache_file):
with open(cache_file, 'rb') as f:
return pickle.load(f)
return None
def save_cached_data(self, cache_key, data):
cache_file = f"{self.cache_dir}/{cache_key}.pickle"
with open(cache_file, 'wb') as f:
pickle.dump(data, f)
def incremental_data_load(connector, source_name, cache):
last_update = cache.get_last_update_date(source_name)
today = datetime.now()
# Загружаем только новые данные
new_data = connector.get_data(last_update, today)
# Объединяем с кешированными данными
cached_data = cache.load_cached_data(source_name)
if cached_data is not None:
combined_data = pd.concat([cached_data, new_data]).drop_duplicates()
else:
combined_data = new_data
# Сохраняем в кеш
cache.save_cached_data(source_name, combined_data)
cache.save_last_update_date(source_name, today)
return combined_data
Параллельная обработка данных
Когда нужно обработать данные из множества источников, используйте многопоточность:
import concurrent.futures
import threading
def parallel_data_collection():
sources = [
('yandex_metrika', yandex_connector.get_traffic_data),
('google_analytics', google_connector.get_conversion_data),
('facebook_ads', facebook_connector.get_ad_data),
('crm_system', crm_connector.get_sales_data)
]
results = {}
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
# Запускаем все задачи параллельно
future_to_source = {
executor.submit(func, start_date, end_date): source_name
for source_name, func in sources
}
for future in concurrent.futures.as_completed(future_to_source):
source_name = future_to_source[future]
try:
data = future.result()
results[source_name] = data
print(f"✅ {source_name} loaded successfully")
except Exception as e:
print(f"❌ Error loading {source_name}: {e}")
results[source_name] = pd.DataFrame() # Пустой DataFrame как fallback
return results
Обработка ошибок и retry-логика
API иногда падают, сеть глючит, лимиты заканчиваются. Нужна надёжная обработка ошибок:
import time
import requests
from functools import wraps
def retry_on_failure(max_retries=3, delay=5, backoff=2):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
retries = 0
while retries < max_retries:
try:
return func(*args, **kwargs)
except (requests.RequestException, ConnectionError, TimeoutError) as e:
retries += 1
if retries == max_retries:
print(f"❌ Failed after {max_retries} retries: {e}")
raise e
wait_time = delay * (backoff ** (retries - 1))
print(f"⚠️ Retry {retries}/{max_retries} in {wait_time} seconds...")
time.sleep(wait_time)
return None
return wrapper
return decorator
@retry_on_failure(max_retries=5, delay=10)
def robust_api_call(url, params):
response = requests.get(url, params=params, timeout=30)
if response.status_code == 429: # Rate limit
retry_after = int(response.headers.get('Retry-After', 60))
print(f"Rate limit hit, waiting {retry_after} seconds...")
time.sleep(retry_after)
raise requests.RequestException("Rate limit exceeded")
response.raise_for_status()
return response.json()
Мониторинг и алерты
Настройте систему мониторинга, чтобы знать, когда что-то идёт не так:
import smtplib
from email.mime.text import MIMEText
import logging
# Настройка логирования
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('analytics_automation.log'),
logging.StreamHandler()
]
)
def send_alert_email(subject, message, recipients):
try:
smtp_server = smtplib.SMTP('smtp.gmail.com', 587)
smtp_server.starttls()
smtp_server.login('your_email@gmail.com', 'your_password')
msg = MIMEText(message)
msg['Subject'] = subject
msg['From'] = 'your_email@gmail.com'
msg['To'] = ', '.join(recipients)
smtp_server.send_message(msg)
smtp_server.quit()
except Exception as e:
logging.error(f"Failed to send alert email: {e}")
def health_check():
issues = []
# Проверяем доступность API
try:
test_response = requests.get('https://api-metrika.yandex.net/management/v1/counters',
headers={'Authorization': f'OAuth {YANDEX_TOKEN}'},
timeout=10)
if test_response.status_code != 200:
issues.append("Yandex Metrika API не отвечает")
except:
issues.append("Yandex Metrika API недоступен")
# Проверяем свежесть данных в базе
last_update = get_last_data_update()
if (datetime.now() - last_update).hours > 2:
issues.append(f"Данные не обновлялись {(datetime.now() - last_update).hours} часов")
# Проверяем аномалии в конверсии
latest_conversion = get_latest_conversion_rate()
if latest_conversion < 0.5: # Если конверсия упала ниже 0.5%
issues.append(f"Критическое падение конверсии: {latest_conversion}%")
if issues:
alert_message = "Обнаружены проблемы в аналитической системе:\n" + "\n".join(issues)
send_alert_email("🚨 Analytics System Alert", alert_message, ['analyst@company.com'])
logging.warning(alert_message)
else:
logging.info("Health check passed - all systems operational")
У нас был случай, когда клиент две недели не знал, что в GA4 сломалась цель. Система мониторинга засекла бы это через час и сразу отправила алерт.
Это часть серии материалов по теме «Скрипты и парсеры». Основная статья серии: Node.js скрипт для ETL: как собрать данные с 25 API за час.
Читайте также
- Node.js скрипт для ETL: как собрать данные с 25 API за час — основная статья кластера
- Как перенести сайт на другой движок или технологию в 2026 году: сроки, стоимость и когда это оправдано
- Python-парсинг: 500 статей конкурентов за час для контент-стратегии
- Комьюнити-маркетинг в Telegram и VK: как построить лояльную аудиторию из 10 000 подписчиков за 90 дней без рекламы через контент-план и систему вовлечения
Частые вопросы
В: Сколько времени занимает настройка Python-автоматизации для BI-дашбордов?
О: Базовая настройка с подключением к 2-3 источникам данных и простыми KPI занимает 3-5 дней. Продвинутая система с A/B тестами, когортным анализом и интерактивными дашбордами — 2-3 недели разработки.
В: Какие навыки Python нужны для автоматизации аналитики?
О: Достаточно базового уровня: работа с pandas, requests для API, основы ООП. Сложные статистические методы можно изучить по ходу проекта. За 2-3 недели интенсивного изучения можно дойти до нужного уровня.
В: Как часто нужно обновлять данные в дашбордах?
О: Зависит от бизнеса. Для e-commerce критичны обновления каждые 15-30 минут, для B2B достаточно раз в день. Яндекс.Метрика обновляется каждые 15 минут, Google Analytics — каждые 4 часа.
В: Можно ли автоматизировать отчёты для руководства?
О: Да, Python генерирует PDF-отчёты, PowerPoint презентации, отправляет email-дайджесты. Мы автоматизировали еженедельные отчёты для CEO — теперь они формируются и отправляются каждый понедельник в 9:00.
В: Что делать, если API изменился и скрипт сломался?
О: Используйте версионирование API (Google Analytics имеет v1beta, v1), мониторинг ошибок и fallback-сценарии. У нас есть система алертов — при сбое в течение 15 минут приходит уведомление.
В: Сколько стоит поддержка автоматизированной системы аналитики?
О: 15-20% от стоимости разработки в год. Включает обновления при изменениях API, добавление новых источников данных, техподдержку. Для системы стоимостью $10,000 поддержка обойдётся в $2,000/год.
В: Можно ли интегрировать данные из CRM и ERP систем?
О: Конечно. Python работает с любыми системами через API или прямые подключения к базам данных. Интегрировали AmoCRM, Bitrix24, 1C через REST API — получаем полную воронку от клика до оплаты.
Нужна помощь с этим? Обсудить проект с DS495 →