Module: VistarClient::API::UnifiedServing

Includes:
Base
Included in:
Client
Defined in:
lib/vistar_client/api/unified_serving.rb

Overview

Unified Ad Serving API for loop-based content scheduling.

This module implements the Vistar Media Unified Ad Serving API which provides scheduled loops of content for digital signage playlists. It combines direct scheduled content, programmatic ad opportunities, and loop-based content into a unified sequence.

The API returns a loop of slots (typically 24 hours) that can be played repeatedly. Each slot has a type: advertisement, content, or programmatic.

Instance Method Summary collapse

Instance Method Details

#get_loop(venue_id:, display_time: nil, with_metadata: false) ⇒ Hash

Get scheduled loop of content slots for digital signage playlist.

Returns a sequence of slots (advertisement, content, programmatic) that form a repeating loop until end_time. The response includes both slots[] and assets[] for efficient pre-caching.

Recommended: Request new loops at least every 30 minutes, even if end_time is far in the future.

Examples:

Basic loop request

loop_data = client.get_loop(venue_id: 'venue-123')

loop_data['slots'].each do |slot|
  case slot['type']
  when 'advertisement', 'content'
    play_asset(slot['asset_url'])
    client.submit_loop_tracking(
      tracking_url: slot['tracking_url'],
      display_time: Time.now.to_i
    )
  when 'programmatic'
    ad = client.request_ad(...)
    # handle programmatic ad request
  end
end

Loop with metadata for reporting

loop_data = client.get_loop(
  venue_id: 'venue-123',
  with_metadata: true
)

loop_data['slots'].each do |slot|
  if slot['metadata']
    puts "Advertiser: #{slot['metadata']['advertiser_name']}"
  end
end

Future loop scheduling (up to 10 days)

tomorrow = Time.now.to_i + 86400
future_loop = client.get_loop(
  venue_id: 'venue-123',
  display_time: tomorrow
)

Parameters:

  • venue_id (String)

    venue identifier making the request (required)

  • display_time (Integer, nil) (defaults to: nil)

    loop start time in UTC epoch seconds (optional, defaults to now)

  • with_metadata (Boolean) (defaults to: false)

    include order/advertiser metadata in response (optional, default: false)

Returns:

  • (Hash)

    response containing slots[], assets[], start_time, end_time

    • slots: Array of slot objects with type, tracking_url, asset_url, length_in_seconds

    • assets: Array of unique assets referenced by slots for pre-caching

    • start_time: Loop start time (epoch seconds)

    • end_time: Loop end time (epoch seconds, typically +24 hours)

Raises:

  • (ArgumentError)

    if required parameters are missing or invalid

  • (AuthenticationError)

    if API key is invalid (401)

  • (APIError)

    for other API errors (4xx/5xx)

  • (ConnectionError)

    for network failures



80
81
82
83
84
85
86
87
# File 'lib/vistar_client/api/unified_serving.rb', line 80

def get_loop(venue_id:, display_time: nil, with_metadata: false)
  validate_get_loop_params!(venue_id, display_time, )

  payload = build_get_loop_payload(venue_id, display_time, )

  response = connection.post('/v1beta2/loop', payload)
  response.body
end

#submit_loop_tracking(tracking_url:, display_time: nil) ⇒ Faraday::Response

Submit tracking URL for loop slot completion.

Convenience method to hit tracking URLs with proper display_time appending. Always appends display_time query parameter for accurate tracking, even if the slot was displayed at a different time than scheduled.

Tracking URLs don’t expire, making this suitable for offline devices that may submit tracking data later (up to 30 days in the past).

Examples:

Submit tracking after slot completion

slot = loop_data['slots'].first
play_asset(slot['asset_url'])

client.submit_loop_tracking(
  tracking_url: slot['tracking_url'],
  display_time: Time.now.to_i
)

Submit tracking with different display time (offline scenario)

actual_play_time = Time.now.to_i - 3600 # 1 hour ago
client.submit_loop_tracking(
  tracking_url: slot['tracking_url'],
  display_time: actual_play_time
)

Parameters:

  • tracking_url (String)

    the tracking URL from slot (required)

  • display_time (Integer, nil) (defaults to: nil)

    when slot was actually displayed in UTC epoch seconds (optional, defaults to current time)

Returns:

  • (Faraday::Response)

    tracking response

Raises:

  • (ArgumentError)

    if tracking_url is missing or empty

  • (ConnectionError)

    for network failures



122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/vistar_client/api/unified_serving.rb', line 122

def submit_loop_tracking(tracking_url:, display_time: nil)
  raise ArgumentError, 'tracking_url is required' if tracking_url.nil? || tracking_url.to_s.empty?

  display_time ||= Time.now.to_i

  # Append display_time query parameter
  separator = tracking_url.include?('?') ? '&' : '?'
  url = "#{tracking_url}#{separator}display_time=#{display_time}"

  # Use Connection#get_request for tracking URLs
  connection.get_request(url)
end