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

Какие данные получить и как читать ответ

Далее описан фактически наблюдавшийся ответ от 18 октября 2026. Наличие данных зависит от аккаунта, ролика, периода и доступа к аналитике. Примеры требуют уже созданный client = EditsClient.from_env() и свою ссылку reel_url.

QueryResult.get_data(*fields) начинает с payload["data"], разрешает имена вида 1$xig_fetch_media(id:$media_id) и числовые 1fvalue. Возвращает исходное значение без пересчёта единиц. Отсутствующий/неоднозначный путь — ошибка; явно вернувшийся null — None. Для анализа новых полей есть response.payload.

1. Подробная статистика и удержание — BaselReelDetailsQuery

reel = client.reel_insights(reel_url)
plays = reel.metrics.get("play_count")
skip = reel.metrics.get("skip_rate")
skip_value = skip.get("value") if isinstance(skip, dict) else None
retention = [{"index": p.index, "percent": p.percent} for p in reel.retention] \
    if reel.retention_available else None

Наблюдались:

Поля Содержимое
play_count, like_count, comment_count, repost_count, save_count, reshare_count Счётчики воспроизведений и взаимодействий
skip_rate, reshares_rate, likes_rate, comments_rate, reposts_rate, saves_rate Объекты метрик: value, delta, type, subtitle, delta_trend в зависимости от поля
average_watch_time Среднее время просмотра; SDK оставляет единицы ответа, не объявляет их секундами
follow_count_from_media, reach_count, viewer_count Объекты количества подписок, охвата и зрителей
views_over_time Временные ряды просмотров в исходной вложенной структуре
content_view_source_breakdown, viewer_distribution, top_ten_badge Источники просмотров, распределение зрителей, дополнительный бейдж
reels_retentions Массив удержания; SDK отдельно возвращает reel.retention

metrics нормализует верхний уровень metric-объектов 1fvalue/1fdelta в value/delta. Вложенные структуры сохраняются. Доля удержания 1 = 100%; None не равен нулю. Отсутствующий график не уничтожает статистику. Подробнее.

2. Сокращённая статистика — BaselPublicInsightsQuery

response = client.public_insights(reel_url)
metrics = response.get_data("xig_fetch_media", "basel_media_public_insights")

Вернулись счётчики и коэффициенты взаимодействий. Графика удержания в этом блоке нет. Слово Public в имени не означает работу без авторизации или подтверждённый доступ к чужим роликам: проверка выполнена только на собственном Reel.

3. Список Reels — BaselAccountLevelReelsQuery

page = client.reels_page(first=3, timeframe="LIFETIME", order_by="BY_DATE",
                         sort_direction="DESCENDING")
for reel in page.items:
    reel_id = reel["id"]
    metrics = reel.get("basel_media_level_insights")
if page.has_next_page:
    next_page = client.reels_page(first=3, after=page.next_cursor)

Путь: xig_user_by_igid_v2 → basel_insights → user_reel_dicts → edges[].node. Узлы содержали id, permalink, taken_at, caption, image_versions2, clips_metadata, is_promoted, is_active_trial, coauthor_producers и basel_media_level_insights. Пагинация — page_info.has_next_page/end_cursor. Проверены две страницы по три ролика без пересечений. account_reels() возвращает тот же ответ без разбора страницы.

Значения из APK:

  • timeframe: LIFETIME, ONE_WEEK, TWO_WEEKS, ONE_MONTH, ONE_YEAR.
  • order_by: BY_DATE, BY_VIEWS, BY_LIKES, BY_COMMENTS, BY_REPOSTS, BY_SHARES, BY_SAVES, BY_FOLLOWERS, BY_SKIP_RATE.
  • sort_direction: ASCENDING, DESCENDING, None.

Живой тест: LIFETIME/BY_DATE/DESCENDING, skip_follow_count=False. Остальные комбинации восстановлены статически, а не проверены перебором.

4. Аналитика аккаунта — BaselAccountLevelInsightsQuery

response = client.account_insights(period="LAST_30_DAYS", include_time_series=True)
metrics = response.get_data("xig_user_by_igid_v2", "basel_insights")
views = response.get_data("xig_user_by_igid_v2", "basel_insights", "reels_views")
views_value = response.get_data("xig_user_by_igid_v2", "basel_insights", "reels_views", "value")

Наблюдались reels_views, total_reach, followers_net_growth, like_count, comment_count, repost_count, reshare_count, save_count, viewer_count. Объекты метрик содержат значение, изменение и time_series при запрошенной серии. Доступны флаги has_access_to_audience_insights, has_access_to_demographic_insights; can_see_organic_insights находится в узле пользователя.

Периоды: LAST_7_DAYS, LAST_14_DAYS, LAST_30_DAYS, LAST_60_DAYS, LAST_90_DAYS, LAST_180_DAYS. Проверен LAST_30_DAYS, остальные найдены в APK.

5. Аудитория — BaselAudienceInsightsQuery

response = client.audience_insights(period="LAST_30_DAYS", client_timezone="Europe/Moscow")
metrics = response.get_data("xig_user_by_igid_v2", "basel_insights")
ages = response.get_data("xig_user_by_igid_v2", "basel_insights", "audience_age_distribution")
countries = response.get_data("xig_user_by_igid_v2", "basel_insights",
                             'audience_top_locations(breakdown_type:"COUNTRY")')

Наблюдались семь возрастных групп, пять стран, пять городов, две группы пола, общее число подписчиков, прирост/подписки/отписки с временными рядами, наиболее активное время подписчиков. popular_topics_preview был пуст. Эти количества — размеры ответа конкретной проверки, не ограничения API. Периоды как выше.

6. Обновление метрик по ID — XIGBaselAccountLevelReelsDataDeltaQuery

response = client.reels_delta(["NUMERIC_MEDIA_ID"])
items = response.get_data("xig_basel_multi_media_insights_query")

Ответ — список узлов id/basel_media_level_insights: media_id, счётчики просмотров/комментариев/лайков/репостов/отправок/сохранений, follow_count_from_media(should_include_delta:false), top_ten_badge. В реальном запросе был один ID. Размер пакета и многоэлементный ответ не проверены.

7. Комментарии — XIGBaselInsightsCommentsQuery

response = client.comment_insights(reel_url, sort_order="recent")
analysis = response.get_data("xig_fetch_media", "ai_comment_insights")
if analysis is None:
    # Функция недоступна или данных нет; это не список из нуля комментариев.
    pass

sort_order из APK: recent, popular. Проверен recent, HTTP 200, ai_comment_insights=null. Структура заполненного анализа живым ответом не проверена.

8. Kits — BaselKitsQuery

response = client.kits(after=None)
connection = response.get_data("xig_basel_kits", "kits")
edges = connection["edges"]
page_info = connection["page_info"]

В запросе скрытый в persisted query first:50; SDK меняет только after. Проверено: HTTP 200, edges=[], has_next_page=false. Заполненные элементы и следующая страница Kits не проверены. Никакие Kits не создавались ради теста.

9. Альтернативная аналитика — ReelInsightsQuery

response = client.extended_reel_insights(
    reel_url,
    bloks_versioning_id="8dc50e9193c9b70a3f9dbcc25fc5f444bbac27bb56a8c1359ede836b8069c4b8",
)
insights = response.get_data("ig_reel_insights")
curve = insights["retention"]["retention_curve"]

Реальный ответ был NDJSON. SDK собирает его в payload. В кривой используются timestamp_seconds и 1fpercentage; здесь 1 соответствует 100%. Демография также содержит percentage, но у стран наблюдались уже проценты, а не доли. Нельзя умножать все percentage в ответе на 100.

bloksVersioningId найден в APK и передаётся явно: версия может измениться. Кривая этой ветки и BaselReelDetailsQuery может отличаться; нельзя подменять одну другой без учёта этого различия. Связь именно этой ветки с UI Edits не доказана. Готовый скрипт.

Полный каталог

Методы содержат ID, variables и источники. 15 контрактов подробно разобраны, но только девять операций чтения имеют живую проверку. Оставшиеся операции и mutations — статические находки. Область доказательств.