Feature Matrix Template: как AI превращает скриншоты конкурентов в actionable insights
Что такое AI-пайплайн для конкурентной feature matrix?
AI-пайплайн для конкурентной feature matrix — это структурированная таблица функций продуктов конкурентов, построенная путём прогона скриншотов через Vision API для извлечения функций, нормализации в единую таксономию и анализа процентов покрытия, что заменяет 40–60 часов ручной аналитической работы на автоматизированный процесс стоимостью $20–33 за 5–6 часов.
TL;DR
- -Пайплайн состоит из пяти верифицируемых этапов: сбор скриншотов по конкурентам → извлечение через Vision API → нормализация в единую таксономию → сборка матрицы → анализ инсайтов; каждый этап сохраняет промежуточный файл, который можно проверить и перезапустить отдельно.
- -Coverage выше 80% означает table stakes — отсутствие любой из этих функций является dealbreaker для покупателей при выходе на рынок.
- -Промпт нормализации критичен: сырые данные Vision API содержат синонимы типа dark_mode/night_theme/dark_theme; без канонического словаря матрица неанализируема.
- -Анализ 50 конкурентов стоит $20–33 в API-вызовах и 5–6 часов суммарно против $2 000–3 000 и полной рабочей недели аналитика за ту же работу вручную.
- -Квартальный запуск пайплайна и сравнение последовательных матриц показывает, куда движутся конкуренты — какие функции масштабируются (тренды) и какие исчезают (отмирающие паттерны).
Конкурентный анализ вручную занимает 40–60 часов на одну итерацию. 50 продуктов, у каждого 10–15 экранов, у каждого экрана 5–20 функций — это 2 500–15 000 точек данных. Аналитик тратит неделю, результат устаревает через месяц.
AI-пайплайн делает то же самое за 5–6 часов, из которых бо́льшая часть уходит на сбор скриншотов. Скриншоты конкурентов проходят через Vision API, превращаются в структурированные данные, заполняют матрицу автоматически. Статья разбирает каждый шаг этого процесса.
Что такое feature matrix и зачем она нужна
Feature matrix — таблица, где строки — функции продукта, столбцы — конкуренты. Каждая ячейка содержит статус: есть/нет/частично, плюс детали реализации.
Три сценария использования:
Продуктовая стратегия. Матрица показывает, какие функции стали table stakes (есть у всех), а какие остаются дифференциаторами. Если 48 из 50 конкурентов предлагают SSO, это не конкурентное преимущество. Это минимальное требование.
Позиционирование. Когда видно всё поле целиком, проще найти незанятую нишу. Пример: все конкуренты предлагают email-интеграцию, но только два поддерживают Telegram. Это сигнал.
Приоритизация бэклога. Вместо гадания на кофейной гуще — данные. Функция X есть у 80% конкурентов, пользователи просят, а у вас её нет. Это не “nice to have”. Это пробел.
Архитектура пайплайна: от скриншота до инсайта
Пайплайн состоит из пяти этапов. Каждый выполняет одну задачу и передаёт результат следующему.
Screenshots (PNG/JPG)
│
▼
[1. Collection] → Организация по конкурентам и экранам
│
▼
[2. Vision API] → Извлечение UI-элементов, текстов, функций
│
▼
[3. Normalization] → Единая таксономия, дедупликация
│
▼
[4. Matrix Assembly] → Заполнение матрицы данными
│
▼
[5. Analysis] → Паттерны, gaps, рекомендации
Главный принцип: каждый этап производит проверяемый промежуточный результат. Не чёрный ящик “скриншот вошёл, инсайт вышел”. Каждый шаг можно проверить, скорректировать, перезапустить отдельно.
Этап 1: сбор и организация скриншотов
Структура папок определяет качество всего анализа. Плоская папка с 500 файлами превращает пайплайн в хаос. Иерархическая структура сохраняет контекст.
competitors/
├── competitor-a/
│ ├── 01-dashboard.png
│ ├── 02-settings.png
│ ├── 03-billing.png
│ └── metadata.json
├── competitor-b/
│ ├── 01-dashboard.png
│ ├── 02-onboarding.png
│ └── metadata.json
└── competitor-c/
└── ...
Файл metadata.json содержит контекст, который Vision API не извлечет из скриншота:
{
"name": "Competitor A",
"url": "https://competitor-a.com",
"pricing_tier": "Pro ($49/mo)",
"capture_date": "2026-03-25",
"platform": "web",
"notes": "Captured on 1920x1080, Chrome, English locale"
}
Источники скриншотов: собственные аккаунты (trial/freemium), демо-видео на YouTube (покадровый экспорт), маркетинговые страницы, обзоры на G2/Capterra (часто содержат скриншоты реального UI).
Для покадрового экспорта из видео подходит ffmpeg:
ffmpeg -i demo-video.mp4 -vf "fps=1/5,select='gt(scene,0.3)'" \
-vsync vfr competitor-a/frame_%04d.png
Команда извлекает кадр каждые 5 секунд, но только если сцена изменилась более чем на 30%. Это отсекает статичные моменты и дубликаты.
Этап 2: извлечение данных через Vision API
Claude Vision обрабатывает скриншоты и извлекает структурированную информацию. Ключевой момент: промпт определяет качество извлечения. Общий промпт “опиши что видишь” даёт мусор. Структурированный промпт даёт данные.
Промпт для извлечения функций из UI-скриншота
Analyze this product screenshot. Extract ALL visible features,
UI elements and capabilities.
For each feature found, provide:
1. feature_name: Short, standardized name (e.g., "dark_mode",
"two_factor_auth", "csv_export")
2. category: One of [navigation, data_display, data_input,
user_management, integrations, analytics, collaboration,
settings, billing, notifications, onboarding]
3. implementation_detail: How exactly it's implemented
(e.g., "Toggle in top-right corner", "Dropdown with 5 options")
4. ui_pattern: The UI pattern used (e.g., "modal", "sidebar",
"inline_edit", "wizard", "tab_panel")
5. confidence: high/medium/low — how certain you are this
feature exists based on the screenshot
Return ONLY valid JSON array. No commentary.
Example output:
[
{
"feature_name": "dark_mode",
"category": "settings",
"implementation_detail": "Toggle switch in header, currently OFF",
"ui_pattern": "toggle",
"confidence": "high"
}
]
Этот промпт работает хорошо по трём причинам. Задаёт жёсткую схему вывода. Ограничивает категории фиксированным списком (это критично для нормализации на следующем этапе). Требует confidence level, что позволяет фильтровать ненадёжные результаты.
Промпт для извлечения текстового контента (OCR-задача)
Extract ALL visible text from this screenshot.
Organize by UI region.
Return JSON:
{
"header": ["text items in header area"],
"navigation": ["menu items, tabs"],
"main_content": ["headings, body text, labels"],
"sidebar": ["sidebar text if present"],
"footer": ["footer text"],
"buttons": ["all button labels"],
"tooltips": ["any visible tooltip text"],
"errors_warnings": ["error messages, warnings, notices"]
}
Include placeholder text (e.g., "Enter your email...")
and microcopy. These reveal UX decisions.
Microcopy в продукте конкурента — источник инсайтов, который аналитики обычно игнорируют. Placeholder “Search across 10,000+ integrations” сообщает больше о позиционировании, чем маркетинговая страница.
Батчевая обработка через API
import anthropic
import json
import base64
from pathlib import Path
client = anthropic.Anthropic()
FEATURE_EXTRACTION_PROMPT = """...""" # промпт выше
def extract_features(image_path: str, competitor: str, screen: str):
with open(image_path, "rb") as f:
image_data = base64.standard_b64encode(f.read()).decode("utf-8")
ext = Path(image_path).suffix.lstrip(".")
media_type = f"image/{'jpeg' if ext == 'jpg' else ext}"
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=4096,
messages=[{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": media_type,
"data": image_data,
},
},
{"type": "text", "text": FEATURE_EXTRACTION_PROMPT}
],
}],
)
features = json.loads(response.content[0].text)
for feat in features:
feat["competitor"] = competitor
feat["screen"] = screen
feat["source_image"] = image_path
return features
def process_all_competitors(base_dir: str):
all_features = []
base = Path(base_dir)
for competitor_dir in sorted(base.iterdir()):
if not competitor_dir.is_dir():
continue
competitor = competitor_dir.name
for img in sorted(competitor_dir.glob("*.png")):
screen = img.stem
print(f"Processing {competitor}/{screen}...")
features = extract_features(str(img), competitor, screen)
all_features.extend(features)
return all_features
results = process_all_competitors("./competitors")
with open("raw_features.json", "w") as f:
json.dump(results, f, indent=2)
print(f"Extracted {len(results)} features from all competitors")
При 50 конкурентах и 10 скриншотах на каждого — 500 вызовов API. На Claude Sonnet это примерно ~$15-25 (зависит от размера изображений). Обработка занимает 30-45 минут при параллельной отправке.
Для ускорения можно добавить asyncio и ограничить concurrency до 10 запросов одновременно, чтобы не упереться в rate limits.
Этап 3: нормализация и создание таксономии
Сырые данные из Vision API содержат дубликаты и разночтения. “dark_mode”, “night_theme”, “dark_theme” — одна и та же функция с тремя названиями. Нормализация приводит всё к единому словарю.
Промпт для нормализации
You are a product analyst normalizing feature names from
competitive analysis data.
Input: Array of raw features extracted from competitor screenshots.
Tasks:
1. Merge duplicates: features that describe the same capability
but use different names → single canonical name
2. Standardize naming: snake_case, English, descriptive
(e.g., "Dark Mode toggle" → "dark_mode")
3. Assign to taxonomy categories (2-level hierarchy):
- authentication: [sso, mfa, password_policy, social_login, ...]
- collaboration: [real_time_editing, comments, mentions, sharing, ...]
- analytics: [dashboard, custom_reports, export, scheduled_reports, ...]
- integrations: [api, webhooks, zapier, native_integrations, ...]
- ... (extend as needed based on the data)
4. Flag conflicts: if same feature appears differently across
competitors, note it
Return JSON:
{
"taxonomy": {
"category_name": {
"feature_canonical_name": {
"aliases": ["all names this was called in raw data"],
"description": "one sentence",
"competitors": {
"competitor-a": {
"status": "full|partial|absent",
"detail": "implementation notes",
"confidence": "high|medium|low"
}
}
}
}
},
"conflicts": [...],
"stats": {
"total_unique_features": N,
"total_categories": N,
"duplicates_merged": N
}
}
Этот этап можно запустить одним вызовом на весь набор данных, если он помещается в контекстное окно. Для 50 конкурентов с 10 экранами получается ~2500-5000 записей. Это около 500K-1M токенов. Актуальные модели Claude с контекстом 1M токенов примут такой объём целиком, но узким местом становится лимит выходных токенов: таксономия на тысячи записей в один ответ не поместится. Решение то же: разбить на батчи по категориям и мержить результаты.
def normalize_in_batches(raw_features, batch_size=200):
batches = [
raw_features[i:i+batch_size]
for i in range(0, len(raw_features), batch_size)
]
normalized_batches = []
for batch in batches:
result = call_claude_normalize(batch) # вызов с промптом выше
normalized_batches.append(result)
return merge_taxonomies(normalized_batches)
Этап 4: сборка feature matrix
Нормализованные данные превращаются в матрицу. Формат зависит от аудитории: CSV/Excel для аналитиков, JSON для автоматизации, Markdown/HTML для презентаций.
Шаблон матрицы (Markdown)
| Feature | Cat. | Comp. A | Comp. B | Comp. C | Coverage |
|---------|------|---------|---------|---------|----------|
| SSO (SAML) | Auth | ✅ Full | ✅ Full | ❌ | 67% |
| MFA | Auth | ✅ TOTP | ✅ TOTP+SMS | ✅ TOTP | 100% |
| Dark mode | UI | ✅ | ❌ | ✅ | 67% |
| CSV export | Data | ✅ | ✅ | ✅ Limited | 100% |
| Real-time collab | Collab | ❌ | ✅ | ❌ | 33% |
| API (REST) | Integ. | ✅ v2 | ✅ v3 | ✅ v1 | 100% |
| Webhooks | Integ. | ✅ | ❌ | ✅ | 67% |
| Custom reports | Analytics | ✅ | ✅ Drag&drop | ❌ | 67% |
Колонка Coverage — процент конкурентов, у которых есть функция. Это ключевая метрика. Coverage 80%+ означает table stakes. Coverage ниже 20% — потенциальный дифференциатор или нишевая функция.
Генерация матрицы из нормализованных данных
import csv
from collections import defaultdict
def build_matrix(taxonomy: dict, competitors: list[str]):
rows = []
for category, features in taxonomy["taxonomy"].items():
for feature_name, feature_data in features.items():
row = {
"feature": feature_name,
"category": category,
}
present_count = 0
for comp in competitors:
comp_data = feature_data["competitors"].get(comp, {})
status = comp_data.get("status", "absent")
detail = comp_data.get("detail", "")
if status == "full":
row[comp] = f"Yes: {detail}" if detail else "Yes"
present_count += 1
elif status == "partial":
row[comp] = f"Partial: {detail}" if detail else "Partial"
present_count += 0.5
else:
row[comp] = "No"
row["coverage"] = f"{present_count / len(competitors) * 100:.0f}%"
rows.append(row)
rows.sort(key=lambda r: r["coverage"], reverse=True)
return rows
def export_csv(rows, competitors, output_path):
fieldnames = ["feature", "category"] + competitors + ["coverage"]
with open(output_path, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)
Этап 5: анализ и извлечение инсайтов
Матрица сама по себе — данные. Инсайты требуют интерпретации. AI делает и это, но с правильным промптом.
Промпт для анализа feature matrix
You are a product strategist analyzing a competitive
feature matrix.
Input: Feature matrix with {N} competitors and {M} features.
Perform the following analyses:
1. TABLE STAKES (coverage >= 80%)
List features every competitor has. These are non-negotiable.
Missing any = dealbreaker for buyers.
2. DIFFERENTIATORS (coverage 20-50%)
Features only some competitors offer. These create
competitive advantage. Rank by strategic value.
3. WHITE SPACES (coverage < 20% or 0%)
Features almost nobody offers. Evaluate:
- Is this a missed opportunity or deliberately ignored?
- What user problem would it solve?
- Effort estimate: low/medium/high
4. IMPLEMENTATION PATTERNS
For features present across competitors, compare
implementation approaches. Which UX patterns dominate?
Which are unique?
5. COMPETITIVE CLUSTERS
Group competitors by feature similarity. Which competitors
are direct substitutes? Which serve different segments?
6. RECOMMENDATIONS
Based on the analysis, provide 5 actionable recommendations
for a product team entering this market. Each must include:
- What to build
- Why (data from matrix)
- Priority: must-have / should-have / nice-to-have
Return structured JSON with all 6 sections.
Пример выходных инсайтов
Модельный пример результата анализа матрицы из 50 конкурентов в категории project management (цифры иллюстративные):
Table stakes (coverage 80%+): Kanban board, task assignments, due dates, file attachments, email notifications, mobile app, Slack integration, CSV export. Эти функции пользователи считают стандартом. Выход на рынок без них невозможен.
Дифференциаторы (coverage 20-50%): Time tracking (38%), resource planning (26%), custom workflows (34%), client portal (22%). Каждый из них закрывает потребность конкретного сегмента. Time tracking нужен агентствам. Client portal — фрилансерам и аутсорсерам.
White spaces (coverage < 20%): AI-assisted task prioritization (8%), automatic dependency detection (4%), burnout risk alerts (2%). Здесь или innovation, или причина, по которой этого не делают. Нужна валидация с пользователями.
Автоматизация и повторяемость
Конкурентный анализ не разовое мероприятие. Рынок меняется каждый квартал. Пайплайн, построенный один раз, запускается повторно с минимальными усилиями.
Скрипт полного цикла
def run_pipeline(competitors_dir: str, output_dir: str):
# Этап 1: валидация структуры
validate_directory_structure(competitors_dir)
# Этап 2: извлечение через Vision API
raw_features = process_all_competitors(competitors_dir)
save_json(raw_features, f"{output_dir}/01_raw_features.json")
# Этап 3: нормализация
taxonomy = normalize_in_batches(raw_features)
save_json(taxonomy, f"{output_dir}/02_taxonomy.json")
# Этап 4: матрица
competitors = list_competitor_names(competitors_dir)
matrix = build_matrix(taxonomy, competitors)
export_csv(matrix, competitors, f"{output_dir}/03_matrix.csv")
# Этап 5: анализ
insights = analyze_matrix(matrix, competitors)
save_json(insights, f"{output_dir}/04_insights.json")
# Генерация отчёта
report = generate_report(matrix, insights)
save_markdown(report, f"{output_dir}/05_report.md")
print(f"Pipeline complete. {len(raw_features)} features extracted.")
print(f"Results in {output_dir}/")
Каждый промежуточный результат сохраняется в файл. Если Vision API упал на 30-м конкуренте, не нужно перезапускать с нуля. Достаточно дообработать оставшиеся 20 и смержить с предыдущими результатами.
Стоимость и временные затраты
Оценочные цифры для анализа 50 конкурентов:
| Этап | Время | Стоимость API |
|---|---|---|
| Сбор скриншотов | 3-5 часов (руками) | $0 |
| Vision API extraction | 30-45 мин | $15-25 |
| Нормализация | 10-15 мин | $3-5 |
| Сборка матрицы | < 1 мин (скрипт) | $0 |
| Анализ и инсайты | 5-10 мин | $2-3 |
| Итого | ~5-6 часов | $20-33 |
Для сравнения: аналитик тратит 40-60 часов на ту же работу. При средней ставке $50/час это $2000-3000. Разница в 60-100 раз по стоимости и в 8-10 раз по времени.
Самый затратный этап — сбор скриншотов. Его тоже можно частично автоматизировать через Playwright:
from playwright.async_api import async_playwright
async def capture_competitor(url: str, output_dir: str):
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page(viewport={"width": 1920, "height": 1080})
await page.goto(url)
# Скриншот главной
await page.screenshot(path=f"{output_dir}/01-landing.png",
full_page=True)
# Навигация по основным разделам
nav_links = await page.query_selector_all("nav a")
for i, link in enumerate(nav_links[:10]):
text = await link.inner_text()
await link.click()
await page.wait_for_load_state("networkidle")
await page.screenshot(
path=f"{output_dir}/{i+2:02d}-{text.lower().replace(' ', '-')}.png"
)
await browser.close()
Работает для маркетинговых страниц и демо. Для залогиненных разделов нужен trial-аккаунт и ручной capture.
Типичные ошибки и как их избежать
Ошибка 1: слишком мелкая гранулярность. “Кнопка синяя” — это не feature. “Поддержка bulk actions” — feature. Vision API извлекает всё подряд. Промпт должен задавать уровень абстракции.
Ошибка 2: нет контекста pricing tier. Feature доступна на Enterprise-плане за $500/мес или на Free? Это принципиально разные ситуации. Metadata файл для каждого конкурента содержит pricing tier. Каждая feature привязана к тарифу.
Ошибка 3: одноразовый анализ. Матрица, сделанная один раз, устаревает за 2-3 месяца. Пайплайн нужно запускать ежеквартально. Diff между двумя матрицами показывает, куда движутся конкуренты.
Ошибка 4: анализ без действия. 300 строк в матрице без приоритизации — информационный шум. Этап 5 (анализ) не опционален. Он переводит данные в решения.
Расширения пайплайна
Базовый пайплайн покрывает ядро. Несколько расширений делают его мощнее.
Pricing intelligence. Параллельно с feature matrix собирать данные о ценах: tier names, лимиты, стоимость. Это позволяет строить price-to-feature ratio и находить overpriced/underpriced позиции на рынке.
UX pattern library. Помимо функций, Vision API извлекает UI-паттерны. Собранные в библиотеку, они показывают доминирующие UX-решения в индустрии. Полезно для дизайнеров: не изобретать велосипед, когда пользователи привыкли к определённым паттернам.
Temporal analysis. Запуск пайплайна раз в квартал создаёт временной ряд. Видно, какие функции конкуренты добавляют массово (тренды), а какие убирают (отмирающие паттерны).
Связка с context engineering. Feature matrix — идеальный контекст для AI-ассистента в продуктовых задачах. Загруженная в систему промптов, она позволяет генерировать PRD, user stories и технические спецификации с учётом конкурентного ландшафта.
Итоги
Feature matrix — не документ. Это инструмент принятия решений. AI-пайплайн устраняет главное препятствие: трудоёмкость сбора и структурирования данных.
Пять шагов: собрать скриншоты, извлечь функции через Vision API, нормализовать, собрать матрицу, проанализировать. Каждый шаг производит проверяемый результат. Весь цикл — 5-6 часов и $20-33 вместо недели работы аналитика.
Матрица отвечает на три вопроса. Что строить обязательно (table stakes). Что даст конкурентное преимущество (дифференциаторы). Где возможность, которую все пропустили (white spaces). Этого достаточно для обоснованных продуктовых решений.
Нужна помощь с конкурентным анализом? Я помогаю стартапам внедрять AI-решения и строить продукты — belov.works.
FAQ
Как обрабатывать конкурентов, чей продукт скрыт за авторизацией и не захватывается Playwright?
Практическое решение — комбинация trial-аккаунтов и структурированного ручного захвата. Создавайте trial-аккаунты там, где это возможно, логиньтесь и делайте скриншоты по стандартному набору экранов: дашборд, настройки, основные рабочие флоу, страница биллинга. Сохраняйте их в той же структуре директорий и с тем же соглашением об именовании — пайплайн Vision API не различает, как были получены скриншоты. Для конкурентов без trial: скриншоты из G2, Capterra и Trustpilot (рецензенты часто прикладывают снимки экрана), ключевые кадры из публичных демо-видео, документация по продукту (почти всегда содержит скриншоты каждой функции).
Как часто обновлять матрицу и как правильно сравнивать две версии по времени?
Раз в квартал — практический минимум для быстро меняющихся SaaS-рынков; раз в полгода достаточно для enterprise-сегмента с длинными циклами релизов. Diff удобно делать на уровне данных: сравниваем taxonomy JSON двух запусков и ищем новые canonical feature names (конкурент добавил функцию), изменения статуса с «absent» на «partial» или «full» (конкурент выпустил), сдвиги coverage по категориям. Простой Python-скрипт, загружающий два taxonomy файла и выдающий отчёт о diff, надёжнее визуального сравнения. Квартальный diff как артефакт — «изменения Q1 vs Q2 2025» — даёт продуктовым командам структурированный вход для ревью роадмапа.
Как определить правильный уровень гранулярности при написании промпта для Vision API?
Гранулярность должна соответствовать уровню продуктовых решений. Если вы определяете, строить ли функцию вообще — нужна крупная гранулярность: «командная коллаборация», а не «треды комментариев с @mentions и emoji-реакциями». Если вы решаете, как реализовать функцию, уже включённую в роадмап — важна мелкая гранулярность: «real-time co-editing vs. locked-document vs. async commenting». Часто оптимальный подход — два прохода с разным уровнем абстракции по одному набору скриншотов: крупный заполняет матрицу для стратегического анализа, мелкий по конкретным категориям даёт исследование реализации для команды разработки.