Back to Portfolio
Business Intelligence Power BI Editorial Analytics · GA4 · Website Performance

Editorial Insights
Power BI Report

A comprehensive Power BI report built for the Editorial Team to monitor website performance, content engagement, audience growth, and newsletter analytics across all company brands. Powered by GA4 and Omeda data via Databricks SQL, with 8 report pages, dual-view layouts, drill-down navigation, and a low-performing articles monitor.

8Report pages
16.6MTotal users tracked
37.8MEmails delivered
10+Brands monitored

Editorial Insights is a multi-page Power BI report designed for the Editorial Team to track and analyse website and content performance across all company brands. It consolidates data from Google Analytics 4 (GA4) and Omeda — ingested via Databricks SQL — into a single, interactive reporting suite.

The report covers the full editorial performance lifecycle: from high-level website traffic and content engagement, to audience growth trends, newsletter click performance, email deployment metrics, and a dedicated page flagging low-performing articles between 30–60 days after publishing.

01

Website Performance Overview

High-level KPIs (Total Users, New Users, Event Count, Page Views, Avg Engagement Duration) with WoW and YTD comparisons, monthly page views trend, total vs new users trend, event count trend, and avg engagement duration trend.

Main
02

Website Performance Breakdown

Drill-down page showing page-level data — brand, link, total users, new users, total events, page views, and user engagement duration per URL.

Drill-Down
03

Content Engagement Analysis

Dual-view page toggling between top and bottom performers. Shows highest/lowest performing brands and content types by page view, plus top/bottom 50 tables by company, author, and tag.

Dual View
04

Content Engagement Detail

Drill-down page showing content-level detail — brand, content type, company, author, tag, link, and page views per article.

Drill-Down
05

Audience Growth Summary

Year-over-Year and Last 30 Days growth charts for brands, content types, and tags — giving the editorial team a clear view of audience trajectory across all dimensions.

Main
06

Newsletter Analytics

Dual-view page showing top and bottom performing brands, deployment types, and deployment names by unique clicks, plus a top/bottom 50 clicked URLs table with click and engagement metrics.

Dual View
07

Deployment Analytics

High-level deployment KPIs (Total Delivered, Open Rate, Click Rate, Click-to-Open Rate, Total Unsubscribe, Unsubscribe Rate) with monthly trend lines for each metric over time.

Main
08

Low Performing Articles (30–60 Days After Publishing)

Flags articles in the bottom 20% by page views, published 30–60 days ago, with at least 1 page view and a valid content type. Includes a daily article views trend and an "Articles Needing Attention" table with direct links.

Monitor

Slicers are displayed directly below each page title for quick access. Common slicers apply across most pages; additional slicers are available on content-specific pages.

Common slicers

Date Range Brand

Content pages exclusive

Content Type Author Company

Newsletter pages exclusive

Deployment Type Deployment Name
🏢

Power BI App

Published as a dedicated Power BI App for the Editorial Team with controlled access. Users must request access from the report owner to ensure only authorised team members can view the data.

🔐

Row-Level Security (RLS)

RLS applied at the app level to restrict data visibility per user role, preventing unauthorised data exposure across teams.

🔗

OAuth2 + Databricks Connection

Connected to Databricks SQL Warehouse via OAuth2 authentication — secure, token-based access without storing credentials.

🔄

Daily Scheduled Refresh

Configured for automated daily refresh at 8:30 PM PHT — ensuring the Editorial Team always works with the latest GA4 and Omeda data.

BI & Visualisation

Power BI DAX Power Query

Data Sources

Databricks SQL GA4 Omeda SQL

Security & Access

Row-Level Security OAuth2 Power BI App Scheduled Refresh

Report Features

Drill-Down Dual View Toggle Dynamic Slicers Low Perf. Monitor

The data model connects four fact tables — Pages Path Report, Custom Event Report, Deployment Details, and Newsletter Details — all joined to a shared Dates Table. Supporting tables include Tags Exploded, Authors Exploded, a Mapping Table for brand resolution, and a Measures Table centralising all DAX calculations.

Editorial Insights Data Model

Power BI model view showing all fact tables joined to a shared Dates Table with supporting dimension and helper tables.

Four SQL scripts power the Editorial Insights datasets, pulling data from GA4 custom dimensions, Omeda email data, and internal brand mapping tables in Databricks.

newsletter_details.sqlSQL · Databricks
SELECT DISTINCT
  CAST(ond.sent_date_pt AS Date)                                AS sent_date
  , ond.brand
  , ond.deployment_name
  , oot.type_name                                               AS deployment_type
  , ond.email_subject                                           AS title
  , ond.content_title
  , ond.link_url
  , ond.delivered_total                                         AS delivered_total
  , ond.opens_total                                             AS opens_total
  , ond.opens_unique                                            AS opens_unique
  , ond.clicks_total                                            AS clicks_total
  , ond.clicks_unique                                           AS clicks_unique
FROM
  schema.bi_analytics.v_newsletter_details          AS ond
JOIN schema.virtual_db.omail_deployment     AS ood
  ON ond.deployment_name = ood.NAME
JOIN schema.virtual_db.omail_type           AS oot
  ON ood.DEPLOYMENT_TYPE_ID = oot.DEPLOYMENT_TYPE_ID
deployment_details.sqlSQL · Databricks
SELECT DISTINCT
    CAST(sent_date_pt AS DATE)                                          AS sent_date
    , odd.brand
    , odd.email_subject                                                 AS title
    , odd.deployment_name
    , oot.type_name                                                     AS deployment_type
    , oot.DESIGNATION_NAME                                              AS designation
    , odd.delivered_total
    , odd.opens_total
    , odd.opens_unique
    , odd.opens_rate
    , odd.clicks_total
    , odd.clicks_unique
    , odd.clicks_rate
    , odd.optouts_total
    , odd.optouts_rate
FROM
    schema.bi_analytics.v_deployment_details                AS odd
    INNER JOIN schema.virtual_db.omail_deployment   AS ood
        ON odd.deployment_name = ood.NAME
    INNER JOIN schema.virtual_db.omail_type         AS oot
        ON ood.DEPLOYMENT_TYPE_ID = oot.DEPLOYMENT_TYPE_ID
ORDER BY
  sent_date DESC
pages_path_report.sqlSQL · Databricks
WITH brand_map AS
(
    SELECT DISTINCT
        Blank                                                                     AS property_id
        , Brand                                                                   AS brand
        , CASE
            WHEN NULLIF(NULLIF(Domain, '(not set)'), '') IS NOT NULL THEN
                CONCAT(
                    'https://www.'
                    , REGEXP_REPLACE(
                        REGEXP_REPLACE(LOWER(TRIM(Domain)), '^https?://', '')
                        , '^www\\.'
                        , ''
                    )
                )
            ELSE NULL
        END                                                                       AS host_name
    FROM
        schema.silver.brand_mapping
)

SELECT DISTINCT
    p.date
    , m.brand                                                                     AS brand
    , CASE
        WHEN NULLIF(NULLIF(p.page_path, '(not set)'), '') IS NULL
            AND NULLIF(NULLIF(m.host_name, '(not set)'), '') IS NULL THEN ''

        WHEN LOWER(TRIM(p.page_path)) LIKE 'http%' THEN
            REGEXP_REPLACE(
                LOWER(TRIM(p.page_path))
                , '^(https?://)?(www\\.)?'
                , 'https://www.'
            )

        WHEN NULLIF(NULLIF(m.host_name, '(not set)'), '') IS NULL THEN p.page_path

        WHEN LEFT(p.page_path, 1) = '/' THEN CONCAT(m.host_name, p.page_path)

        ELSE CONCAT(m.host_name, '/', p.page_path)
    END                                                                           AS link
    , SUM(p.total_users)                                                          AS total_users
    , SUM(p.new_users)                                                            AS new_users
    , SUM(p.event_count)                                                          AS event_count
    , SUM(p.screen_page_views)                                                    AS screen_page_views
    , SUM(p.user_engagement_duration)                                             AS user_engagement_duration
FROM
    schema.google_analytics.pages_path_report p
    LEFT JOIN brand_map m
        ON SPLIT_PART(p.property, '/', 2) = CAST(m.property_id AS STRING)
WHERE
    p.date >= '2025-01-01'
GROUP BY
    1, 2, 3
custom_event_report.sqlSQL · Databricks
SELECT DISTINCT
    c.date
    , m.Brand                                                                           AS brand
    , CASE
        WHEN NULLIF(NULLIF(c.host_name, '(not set)'), '') IS NULL
            AND NULLIF(NULLIF(c.page_path, '(not set)'), '') IS NULL THEN NULL
        WHEN NULLIF(NULLIF(c.host_name, '(not set)'), '') IS NULL THEN c.page_path
        WHEN NULLIF(NULLIF(c.page_path, '(not set)'), '') IS NULL THEN c.host_name
        ELSE CONCAT('https://', c.host_name, c.page_path)
    END                                                                                 AS link
    , CASE  
        WHEN c.custom_event_content_type = '(not set)' THEN NULL
        ELSE c.custom_event_content_type
    END                                                                                 AS content_type
    , CASE
        WHEN c.custom_event_content_tag = '(not set)' THEN NULL
        ELSE c.custom_event_content_tag
    END                                                                                 AS tag
    , CASE
        WHEN c.custom_event_content_author = '(not set)' THEN NULL
        ELSE c.custom_event_content_author
    END                                                                                 AS author
    , CASE
        WHEN c.custom_event_content_company = '(not set)' THEN NULL
        ELSE c.custom_event_content_company
    END                                                                                 AS company
    , SUM(c.event_count)                                                                AS event_count
    , SUM(c.screen_page_views)                                                          AS page_views
FROM
    schema.ga4_custom_dimensions.custom_event_content c
    LEFT JOIN schema.silver.brand_mapping m
        ON SPLIT_PART(c.property, '/', 2) = CAST(m.Blank AS STRING)
WHERE
    date >= '2025-01-01'
GROUP BY
    1, 2, 3, 4, 5, 6, 7

Website Performance Overview

Website Performance Overview

KPI cards with WoW/YTD comparisons, monthly page views trend with MoM %, and user/event/engagement trend charts.

Website Performance Breakdown — Drill-Down

Website Performance Breakdown

Page-level breakdown by brand and URL showing total users, new users, events, page views, and engagement duration.

Content Engagement Analysis — Top Performing View

Content Engagement Top

Highest performing brands and content types by page view, with top 50 tables by company, author, and tag.

Content Engagement Analysis — Bottom Performing View

Content Engagement Bottom

Lowest performing brands and content types, toggled via the Change View button — same page, different perspective.

Content Engagement Detail — Drill-Down

Content Engagement Detail

Article-level detail with brand, content type, company, author, tag, clickable link, and page views.

Audience Growth Summary

Audience Growth Summary

YoY and Last 30 Days growth charts for brands, content types, and tags — identifying growth leaders and declining areas.

Newsletter Analytics — Top Performing View

Newsletter Analytics Top

Highest clicked brands, deployment types, and deployment names with top 50 clicked URLs and engagement metrics.

Newsletter Analytics — Bottom Performing View

Newsletter Analytics Bottom

Lowest clicked deployments toggled via Change View, with bottom 50 URLs for content optimisation insights.

Deployment Analytics

Deployment Analytics

High-level email deployment KPIs with 6 monthly trend charts covering delivery, clicks, opens, and unsubscribes.

Low Performing Articles (30–60 Days After Publishing)

Low Performing Articles

Bottom 20% articles by page views, 30–60 days post-publish, with daily trend and direct article links for editorial action.

Editorial performance, end to end

Editorial Insights brings together GA4 website analytics, Omeda email data, and internal brand mappings into a single Power BI report — giving the Editorial Team full visibility into what content performs, which audiences are growing, and which articles need attention, all without manual data wrangling.

← Back to Portfolio