Skip to Content
Swift SDKCore Concepts

Core Concepts

Vio brings live engagement to sports streaming. Polls, contests, and shoppable products are configured in the Dashboard and delivered in real-time via WebSocket to the SDK.

Architecture Overview

Dashboard Backend SDK ───────── ─────── ─── Create Campaign → Campaign API → CampaignManager ├── Broadcast ├── /v1/sdk/broadcast ├── discoverCampaigns() │ └── externalId │ (by contentId) │ ├── Polls (scheduled) └── WebSocket /ws/:id → EngagementManager ├── Contests ├── poll event ├── polls ├── Sponsor (logo, color) ├── contest event ├── contests ├── Sponsor Moments ├── sponsor event ├── sponsorSlots │ └── product/lead/link └── lineup_show → LineupTimelineHandler └── Lineup (auto at -10min) └── MatchLineupView

Key principle: Everything is configured in the Dashboard. The SDK receives it via API and WebSocket — no hardcoded campaign IDs in your app code.

CampaignManager

The central manager. Use as a singleton via CampaignManager.shared.

import VioCore // Connect to a broadcast (call when user opens a stream) await VioSDK.setContent(id: "real-madrid-vs-barcelona-2025-01-24") // Read state let campaign = CampaignManager.shared.currentCampaign let isConnected = CampaignManager.shared.isConnected // Disconnect (call when user exits the stream) VioSDK.disconnect()

What setContent(id:) does

  1. Clears components from the previous broadcast
  2. Calls the backend to find the active campaign for this broadcastId (matches externalId in Dashboard)
  3. Loads engagement config for the broadcast
  4. Opens a WebSocket connection
  5. Backend sends current polls/contests immediately on connect
  6. New polls/contests arrive in real-time as they trigger during the match

BroadcastContext

The identifier that links your app to a broadcast configured in the Dashboard.

let context = BroadcastContext( broadcastId: "real-madrid-vs-barcelona-2025-01-24", // Required — matches Dashboard externalId broadcastName: "Real Madrid vs Barcelona", // Optional — display name channelId: nil, // Optional metadata: nil // Optional )

The broadcastId you pass must match the externalId field of the broadcast in the Dashboard exactly.

EngagementManager

Manages the state of polls and contests for the current broadcast. Updated automatically via WebSocket.

import VioEngagementSystem // Observe polls @StateObject var engagement = EngagementManager.shared // In your view ForEach(engagement.activePollsForCurrentBroadcast) { poll in PollCard(poll: poll) }

Polls and contests arrive from the WebSocket and are stored here. The VioCastingUI components observe this automatically — you don’t need to manage state manually when using the pre-built overlays.

Sponsor Moments are timed product placements that appear at specific match minutes (e.g., minute 35, 45, 70). They’re configured in the Dashboard under each broadcast — the SDK receives them via WebSocket and renders them automatically.

Slot types: product · lead · poll_cta · contest_cta · link

The public name is Sponsor Moments. In the API and backend they’re sponsor_slots — both terms refer to the same thing.

Lineup

Match lineups are delivered via the lineup_show WebSocket event. The backend triggers this automatically 10 minutes before kickoff. The MatchLineupView component listens for this event and renders both teams’ formations — no manual data fetching required.

// Just pass the broadcastId — the lineup arrives automatically MatchLineupView(broadcastId: "real-madrid-vs-mancity-2026-03-11")

SponsorAssets

Sponsor identity comes from the backend — no hardcoding needed. Colors, logos, and avatar URLs are delivered via the campaign API.

import VioDesignSystem // Access sponsor assets (available after discoverCampaigns) let sponsor = CampaignManager.shared.currentCampaign?.sponsor let logoUrl = sponsor?.logoUrl let primaryColor = sponsor?.primaryColor // e.g. "#F5153B" for Viaplay let avatarUrl = sponsor?.avatarUrl

ViaCastingUI components use SponsorAssets automatically — sponsor branding is applied without any code changes.

Module Overview

ModuleKey ClassesUse When
VioCoreVioConfiguration, CampaignManager, ConfigurationLoaderAlways
VioEngagementSystemEngagementManager, CampaignWebSocketManagerLive engagement
VioEngagementUIVioEngagementPollOverlay, VioEngagementProductOverlayEngagement UI
VioCastingUITimelinePollCard, SponsorBadge, ContestCardSports casting UI
VioUIProductService, CartManager, VioProductCardShoppable products
VioDesignSystemVioColors, VioSpacing, VioTypographyCustom UI

Configuration Flow

@main struct MyApp: App { init() { // 1. Configure with API key — fetches runtime config from backend VioSDK.configure(apiKey: "your-api-key") // 2. CampaignManager initializes — waits for setContent(id:) } } // Later, when user opens a stream: // 3. setContent → discoverCampaigns → WebSocket connects → polls/contests arrive await VioSDK.setContent(id: "real-madrid-vs-mancity-2026-03-11")

Market Availability

The SDK checks market availability using the user’s country code. If the streaming service isn’t available in that market, the SDK disables itself silently.

// After loadConfiguration: let available = VioConfiguration.shared.isMarketAvailable let shouldShow = VioConfiguration.shared.shouldUseSDK // isConfigured && isMarketAvailable

Design System

Access design tokens from VioDesignSystem:

import VioDesignSystem Text("Live") .foregroundColor(VioColors.primary.toColor()) VStack(spacing: VioSpacing.md) { VioButton(title: "Add to Cart", style: .primary) { } }

Next Steps

Last updated on