mirror of
https://github.com/discourse/discourse.git
synced 2026-08-06 13:08:40 +08:00
This commit adds two new cards to the redesigned admin dashboard's Site
Traffic section: top countries and top referrers, both sourced from
`browser_pageview_events`.
Key technical decisions:
1. Gate the cards on the `persist_browser_pageview_events` site setting.
The cards have no data source unless browser pageview events are being
persisted, so they are omitted from the dashboard.
2. Normalize referrers at write time. A new `normalized_referrer` column
on `browser_pageview_events` is populated by
`BrowserPageviewReferrerInspector`, which strips scheme, `www.`, port,
fragment, trailing slashes, and common tracking query params. Doing this
at insert time avoids per-row string operations at query time.
3. Count browser pageviews by country and by referrer in two new report
concerns. `Reports::TopCountriesByBrowserPageviews` groups by
`country_code` and `Reports::TopReferrersByBrowserPageviews` groups by
`normalized_referrer`. Both compute share of total browser pageviews and
rank the top 5 in SQL. The country report drops MaxMind reserved codes
(unknown, anonymous proxy, satellite). The referrer report drops
same-host referrals. Both also exclude anonymous browser pageviews
(`user_id IS NULL`) when the `login_required` site setting is enabled,
since only logged-in browser pageviews are meaningful on a closed forum.
4. Fetch each report through the existing dashboard service.
`AdminDashboardSiteTraffic#build` returns one entry per card with a `{
rows:, error: }` shape, e.g.:
```ruby
{
top_countries: {
rows: [
{ country_code: "US", count: 142, percent: 35 },
{ country_code: "GB", count: 89, percent: 22 }
],
error: nil
},
top_referrers: {
rows: [
{ normalized_referrer: "news.ycombinator.com/item?id=1", count: 47,
percent: 12 },
{ normalized_referrer: "reddit.com/r/discourse", count: 31, percent: 8 }
],
error: nil
}
}
```
On report failure, `rows: []` and `error: :timeout` (or another symbol).
This lets the UI render rows, error, or empty state independently.
Healthy responses are cached via `Report.find_cached`.
`SiteSetting.login_required` and `Discourse.current_hostname` flow into
`opts[:filters]` so toggling either invalidates the cache. Timeouts skip
the cache so the next request retries.
5. Use `Intl.DisplayNames` for country names instead of locale files.
`Intl.DisplayNames` is a built-in browser API that returns a localized
country name for an ISO 3166-1 alpha-2 code, avoiding ~250 translation
strings per locale.
|
||
|---|---|---|
| .. | ||
| admin_notice_fabricator.rb | ||
| allowed_pm_users.rb | ||
| api_key_fabricator.rb | ||
| api_key_scope_fabricator.rb | ||
| application_request_fabricator.rb | ||
| associated_group_fabricator.rb | ||
| badge_fabricator.rb | ||
| bookmark_fabricator.rb | ||
| browser_pageview_event_fabricator.rb | ||
| category_fabricator.rb | ||
| category_group_fabricator.rb | ||
| category_localization_fabricator.rb | ||
| category_moderation_group_fabricator.rb | ||
| color_scheme_color_fabricator.rb | ||
| color_scheme_fabricator.rb | ||
| custom_emoji_fabricator.rb | ||
| dimissed_topic_user.rb | ||
| do_not_disturb_fabricator.rb | ||
| draft_fabricator.rb | ||
| email_change_request_fabricator.rb | ||
| email_log_fabricator.rb | ||
| email_token_fabricator.rb | ||
| embeddable_host_fabricator.rb | ||
| embeddable_host_tag_fabricator.rb | ||
| external_upload_stub_fabricator.rb | ||
| flag_fabricator.rb | ||
| flag_post_action_fabricator.rb | ||
| form_template_fabricator.rb | ||
| group_fabricator.rb | ||
| group_history_fabricator.rb | ||
| group_request_fabricator.rb | ||
| group_user_fabricator.rb | ||
| ignored_user_fabricator.rb | ||
| incoming_email_fabricator.rb | ||
| incoming_link_fabricator.rb | ||
| invite_fabricator.rb | ||
| invited_user_fabricator.rb | ||
| like_fabricator.rb | ||
| moved_post_fabricator.rb | ||
| muted_user.rb | ||
| nested_topic_fabricator.rb | ||
| notification_fabricator.rb | ||
| optimized_image_fabricator.rb | ||
| optimized_video_fabricator.rb | ||
| permalink_fabricator.rb | ||
| post_action_fabricator.rb | ||
| post_custom_field_fabricator.rb | ||
| post_detail_fabricator.rb | ||
| post_fabricator.rb | ||
| post_localization_fabricator.rb | ||
| post_reply_key_fabricator.rb | ||
| post_revision_fabricator.rb | ||
| problem_check_tracker_fabricator.rb | ||
| published_page_fabricator.rb | ||
| push_subscription_fabricator.rb | ||
| redelivering_webhook_event_fabricator.rb | ||
| reviewable_claimed_topic_fabricator.rb | ||
| reviewable_fabricator.rb | ||
| reviewable_note_fabricator.rb | ||
| reviewable_score_fabricator.rb | ||
| screened_email_fabricator.rb | ||
| screened_ip_address_fabricator.rb | ||
| screened_url_fabricator.rb | ||
| search_log_fabricator.rb | ||
| shared_draft_fabricator.rb | ||
| sidebar_section_fabricator.rb | ||
| sidebar_section_link_fabricator.rb | ||
| sidebar_url_fabricator.rb | ||
| single_sign_on_record_fabricator.rb | ||
| site_setting_group_fabricator.rb | ||
| skipped_email_log_fabricator.rb | ||
| tag_fabricator.rb | ||
| tag_group_fabricator.rb | ||
| tag_group_permission_fabricator.rb | ||
| tag_localization_fabricator.rb | ||
| tag_user_fabricator.rb | ||
| theme_fabricator.rb | ||
| theme_field_fabricator.rb | ||
| theme_settings_migration_fabricator.rb | ||
| theme_site_setting_fabricator.rb | ||
| topic_allowed_group_fabricator.rb | ||
| topic_allowed_user_fabricator.rb | ||
| topic_embed_fabricator.rb | ||
| topic_fabricator.rb | ||
| topic_link_click_fabricator.rb | ||
| topic_link_fabricator.rb | ||
| topic_localization_fabricator.rb | ||
| topic_tag_fabricator.rb | ||
| topic_timer_fabricator.rb | ||
| topic_user_fabricator.rb | ||
| topic_view_stat_fabricator.rb | ||
| translation_override_fabricator.rb | ||
| upload_fabricator.rb | ||
| user_action_fabricator.rb | ||
| user_api_key_fabricator.rb | ||
| user_associated_account_fabricator.rb | ||
| user_avatar_fabricator.rb | ||
| user_badge_fabricator.rb | ||
| user_custom_field_fabricator.rb | ||
| user_email_fabricator.rb | ||
| user_fabricator.rb | ||
| user_field_fabricator.rb | ||
| user_field_option_fabricator.rb.rb | ||
| user_history_fabricator.rb | ||
| user_option_fabricator.rb | ||
| user_password_fabricator.rb | ||
| user_profile_fabricator.rb | ||
| user_second_factor_fabricator.rb | ||
| user_security_key_fabricator.rb | ||
| user_status_fabricator.rb | ||
| user_visit_fabricator.rb | ||
| watched_word_fabricator.rb | ||
| watched_word_group_fabricator.rb | ||
| web_crawler_request_fabricator.rb | ||
| web_hook_event_fabricator.rb | ||
| web_hook_fabricator.rb | ||