chore(facebook): migrate to *_media_view metrics (Meta deprecation 2026-06-30)
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions

Meta deprecates page_impressions, post_impressions, page_video_views et al.
on 2026-06-30. Replaced by *_media_view family. Both old and new metrics
are requested during the transition window so historical data and fresh
data coexist without UI gaps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-04-14 12:59:45 +02:00
parent dc54f50605
commit 599e4bde83
2 changed files with 34 additions and 18 deletions

View File

@ -128,20 +128,25 @@ class FacebookGraphService:
since = int((datetime.now() - timedelta(days=days)).timestamp())
until = int(datetime.now().timestamp())
# Meta deprecated impressions/views metrics on 2026-06-30.
# Migrated to *_media_view family. Old keys kept temporarily for
# transition (Meta serves both until cutoff).
all_metrics = [
'page_views_total',
'page_post_engagements',
'page_actions_post_reactions_total',
'page_posts_impressions',
'page_video_views',
'page_media_view',
'page_total_media_view_unique',
'page_daily_follows',
'page_daily_unfollows',
# These may be deprecated or require additional permissions:
'page_impressions',
'page_engaged_users',
'page_fans',
'page_fan_adds',
'page_fan_removes',
# Deprecated 2026-06-30 — keep until migration verified end-to-end:
'page_posts_impressions',
'page_video_views',
'page_impressions',
'page_engaged_users',
]
result = {}
@ -444,7 +449,12 @@ class FacebookGraphService:
Returns:
Dict with impressions, reach, engaged_users, clicks or None
"""
metrics = 'post_impressions,post_impressions_unique,post_engaged_users,post_clicks'
# post_impressions/post_impressions_unique deprecated 2026-06-30.
# Replaced by post_media_view / post_total_media_view_unique.
# Both old and new requested during transition window.
metrics = ('post_media_view,post_total_media_view_unique,'
'post_impressions,post_impressions_unique,'
'post_engaged_users,post_clicks')
result = self._get(f'{post_id}/insights', {'metric': metrics})
if not result:
return None
@ -454,11 +464,10 @@ class FacebookGraphService:
name = metric.get('name', '')
values = metric.get('values', [])
if values:
# Lifetime metrics have a single value
value = values[0].get('value', 0)
if name == 'post_impressions':
if name in ('post_media_view', 'post_impressions'):
insights['impressions'] = value
elif name == 'post_impressions_unique':
elif name in ('post_total_media_view_unique', 'post_impressions_unique'):
insights['reach'] = value
elif name == 'post_engaged_users':
insights['engaged_users'] = value
@ -659,10 +668,14 @@ def sync_facebook_to_social_media(db, company_id: int) -> dict:
if post_stats.get('recent_posts'):
extra['recent_posts'] = post_stats['recent_posts']
# Insights
for key in ('page_impressions', 'page_engaged_users', 'page_views_total',
'page_post_engagements', 'page_fan_adds', 'page_fan_removes',
'page_actions_post_reactions_total', 'page_posts_impressions',
'page_video_views', 'page_daily_follows', 'page_daily_unfollows'):
for key in ('page_media_view', 'page_total_media_view_unique',
'page_views_total', 'page_post_engagements',
'page_fan_adds', 'page_fan_removes',
'page_actions_post_reactions_total',
'page_daily_follows', 'page_daily_unfollows',
# Deprecated 2026-06-30, kept for backward compat:
'page_impressions', 'page_engaged_users',
'page_posts_impressions', 'page_video_views'):
if insights.get(key):
extra[f'insights_{key}'] = insights[key]
csm.content_types = extra

View File

@ -799,17 +799,20 @@
</div>
{% endif %}
<!-- Insights -->
{% set has_insights = ct.get('insights_page_impressions') or ct.get('insights_page_views_total') or ct.get('insights_page_post_engagements') or ct.get('insights_page_posts_impressions') or ct.get('insights_page_daily_follows') %}
{# Meta deprecated impressions metrics on 2026-06-30. New: page_media_view, page_total_media_view_unique. Fallback to old keys for historical data. #}
{% set page_views_metric = ct.get('insights_page_total_media_view_unique') or ct.get('insights_page_impressions') %}
{% set page_video_metric = ct.get('insights_page_media_view') or ct.get('insights_page_video_views') %}
{% set page_reach_metric = ct.get('insights_page_posts_impressions') %}
{% set has_insights = page_views_metric or ct.get('insights_page_views_total') or ct.get('insights_page_post_engagements') or page_reach_metric or ct.get('insights_page_daily_follows') %}
{% if has_insights %}
<div style="margin-top: var(--spacing-sm); padding: var(--spacing-sm) var(--spacing-md); background: #f0f9ff; border-radius: var(--radius); border: 1px solid #bae6fd;">
<div style="font-size: 11px; font-weight: 600; color: #0369a1; margin-bottom: 4px;">📊 Insights (28 dni)</div>
<div style="display: flex; gap: var(--spacing-md); flex-wrap: wrap; font-size: var(--font-size-sm); color: #0c4a6e;">
{% if ct.get('insights_page_posts_impressions') %}<span>{{ "{:,}".format(ct.insights_page_posts_impressions).replace(",", " ") }} zasięg postów</span>{% endif %}
{% if ct.get('insights_page_impressions') %}<span>{{ "{:,}".format(ct.insights_page_impressions).replace(",", " ") }} wyświetleń strony</span>{% endif %}
{% if page_reach_metric %}<span>{{ "{:,}".format(page_reach_metric).replace(",", " ") }} zasięg postów</span>{% endif %}
{% if page_views_metric %}<span>{{ "{:,}".format(page_views_metric).replace(",", " ") }} wyświetleń strony</span>{% endif %}
{% if ct.get('insights_page_views_total') %}<span>{{ "{:,}".format(ct.insights_page_views_total).replace(",", " ") }} odsłon strony</span>{% endif %}
{% if ct.get('insights_page_post_engagements') %}<span>{{ "{:,}".format(ct.insights_page_post_engagements).replace(",", " ") }} interakcji</span>{% endif %}
{% if ct.get('insights_page_video_views') %}<span>{{ "{:,}".format(ct.insights_page_video_views).replace(",", " ") }} odsłon wideo</span>{% endif %}
{% if page_video_metric %}<span>{{ "{:,}".format(page_video_metric).replace(",", " ") }} odsłon wideo</span>{% endif %}
{% if ct.get('insights_page_daily_follows') %}<span>+{{ ct.insights_page_daily_follows }} nowych obserwujących</span>{% endif %}
{% if ct.get('insights_page_daily_unfollows') %}<span>-{{ ct.insights_page_daily_unfollows }} utraconych</span>{% endif %}
{% if ct.get('insights_page_fan_adds') %}<span>+{{ ct.insights_page_fan_adds }} nowych fanów</span>{% endif %}