Skip to content

Data Model

MediaPulse - Base

  • ads is AdConnect's programmatic ad platform: campaigns, their impressions/clicks, and daily spend.
  • news is NewsNow's digital news outlet: articles (versioned per edit), authors, and page-view events.
  • streaming is StreamVault (internally PulseStream), MediaPulse's current streaming platform: catalog, subscriptions, and watch events.
  • podcasts is the PodcastHub's podcast network: shows, episodes, and listen sessions.

MediaPulse - Analytics

  • Streamview Legacy is the archived data from StreamView, the platform MediaPulse migrated off of.
  • The crm domain is from SignalDesk, the third-party CRM AdConnect's ad sales org uses (system of record since a 2021 migration off a legacy platform called PipelinePro).

Entity Relationship Diagram

Want to zoom in? Visit the full ERD here.

erDiagram
    ads.campaigns {
        string campaign_id PK
        string advertiser_id
        string campaign_name
        string campaign_type
        date   start_date
        date   end_date
        int    budget_cents
    }

    ads.impressions {
        string impression_id PK
        string campaign_id   FK
        string content_id    FK
        date   impression_date
        int    impressions_count
        int    clicks
    }

    ads.spend {
        string spend_id    PK
        string campaign_id FK
        date   spend_date
        int    spend_cents
        int    platform_fee_cents
    }

    news.authors {
        string author_id PK
        string name
        string email
        date   joined_at
    }

    news.articles {
        string article_id  PK
        string author_id   FK
        string title
        string category
        date   published_at
        date   updated_at
        string status
        int    word_count
    }

    news.page_views {
        string view_id    PK
        string article_id FK
        string user_id
        date   viewed_at
        string referrer_source
    }

    podcasts.shows {
        string show_id    PK
        string show_name
        string host_name
        string category
        date   launched_at
    }

    podcasts.episodes {
        string episode_id      PK
        string show_id         FK
        string title
        date   published_at
        int    duration_seconds
        string episode_season
        string category
    }

    podcasts.listens {
        string listen_id              PK
        string episode_id             FK
        string user_id
        date   listened_at
        int    listen_duration_seconds
        int    platform_id
    }

    streaming.content_catalog {
        string content_id      PK
        string title
        string genre
        string ctnt_type
        date   release_date
        int    runtime_minutes
    }

    streaming.subscriptions {
        string subscription_id  PK
        string user_id
        string plan_type
        string status
        date   start_date
        string start_time
        date   end_date
        string end_time
        int    monthly_fee_cents
        date   updated_at
    }

    streaming.watch_events {
        string event_id              PK
        string user_id
        string content_id            FK
        date   watched_at
        int    watch_duration_seconds
        string device_type
        date   batched_at
    }

    streamview_legacy.media_catalog_archive {
        string media_id      PK
        string media_title
        string category
        string media_format
        date   release_dt
        int    duration_min
    }

    streamview_legacy.acct_subs_archive {
        string subscriber_ref  PK
        string tier
        string account_status
        date   start_dt
        string start_tm
        date   end_dt
        string end_tm
    }

    streamview_legacy.playback_heartbeats {
        string ping_id                    PK
        string subscriber_ref             FK
        string media_id                   FK
        date   ping_date
        string ping_time
        int    playback_position_seconds
        string device_code
    }

    crm.sales_reps {
        string rep_id      PK
        string rep_name
        string region
        date   hire_date
    }

    crm.advertiser_accounts {
        string advertiser_id  PK
        string advertiser_name
        string industry
        string sales_rep_id   FK
        string contract_tier
        string account_status
        date   signed_at
    }

    crm.contracts {
        string contract_id           PK
        string advertiser_id         FK
        int    contract_value_cents
        date   start_date
        date   end_date
        string renewal_status
    }

    crm.touchpoints {
        string touchpoint_id  PK
        string advertiser_id  FK
        string rep_id         FK
        string touchpoint_type
        date   occurred_at
        string notes
    }

    streaming.content_catalog ||--o{ streaming.watch_events : "watched as"
    crm.sales_reps            ||--o{ crm.advertiser_accounts : "manages"
    crm.advertiser_accounts   ||--o{ crm.contracts            : "signs"
    crm.advertiser_accounts   ||--o{ crm.touchpoints          : "receives"
    crm.sales_reps            ||--o{ crm.touchpoints          : "logs"
    crm.advertiser_accounts   ||--o{ ads.campaigns            : "runs"
    streamview_legacy.media_catalog_archive ||--o{ streamview_legacy.playback_heartbeats : "pinged as"
    streamview_legacy.acct_subs_archive      ||--o{ streamview_legacy.playback_heartbeats : "pinged by"
    ads.campaigns        ||--o{ ads.impressions           : "generates"
    ads.campaigns        ||--o{ ads.spend                 : "incurs"
    streaming.content_catalog ||--o{ ads.impressions      : "appears in"
    news.authors         ||--o{ news.articles             : "writes"
    news.articles        ||--o{ news.page_views           : "receives"
    podcasts.shows       ||--o{ podcasts.episodes         : "publishes"
    podcasts.episodes    ||--o{ podcasts.listens          : "recorded as"

Domains

Ads

Table Description
ads.campaigns Advertiser campaigns with budget and date range
ads.impressions Impressions and clicks per campaign and content item
ads.spend Daily spend and platform fees per campaign

News

Table Description
news.authors Author profiles
news.articles Articles with author, category, and status
news.page_views Page view events per article and user

Podcasts

Table Description
podcasts.shows Podcast show metadata
podcasts.episodes Episodes with season, category, and duration
podcasts.listens Listen events per episode and user, with a numeric platform_id

Streaming

Table Description
streaming.content_catalog Video content with genre and runtime
streaming.subscriptions User subscription plans and status
streaming.watch_events Watch events per content item and user

Streamview Legacy

Table Description
streamview_legacy.media_catalog_archive Legacy content catalog, some items re-catalogued under a new content_id
streamview_legacy.acct_subs_archive Legacy subscriber accounts, some migrated to a new user_id
streamview_legacy.playback_heartbeats Playback heartbeat pings, roughly one per minute of playback (not one row per completed watch, unlike streaming.watch_events)

CRM

Table Description
crm.sales_reps AdConnect sales rep profiles
crm.advertiser_accounts Advertiser accounts, tier, and status, one row per advertiser
crm.contracts Advertiser contract terms and value
crm.touchpoints Sales activity (calls, emails, meetings, demos) per advertiser and rep

Cross-domain Relationships

ads.impressions links to streaming.content_catalog via content_id, meaning ad impressions are served against streaming content items.

crm.advertiser_accounts links to ads.campaigns via advertiser_id - the same advertiser identifier is shared across the CRM and ads domains, even though the two are otherwise unconnected.

Streamview Legacy migration

streamview_legacy has no direct FK into streaming - the two are reconciled through a separate mapping seed (map_streaming_legacy_fields) that isn't raw source data, so it isn't drawn here. Not every legacy subscriber or content item has been migrated yet.

Users

user_id appears in news.page_views, podcasts.listens, streaming.subscriptions, and streaming.watch_events but there is no users table in the raw data. A unified users table may exist upstream.