VAST validator for Ruby and Rails
Short answer: install the vastlint gem and call Vastlint.validate(xml). It validates VAST XML in-process and returns a stable result you can hand straight to your frontend.
The gem wraps the same Rust core used by the CLI, Go binding, and web validator through an FFI C API. No subprocess to manage, no network hop, a good fit for a DSP, SSP, ad server, or trafficking backend that validates creatives and renders structured results in a React UI.
Why use the Ruby gem
- In-process validation, with no subprocess or external service
- Same core rule coverage as the CLI, web app, and other bindings
- Stable JSON result shape for backend-to-frontend responses
- Per-call
rule_overridesand wrapper-depth options
Install
# Gemfile: published to GitHub Packages
source "https://rubygems.org"
source "https://rubygems.pkg.github.com/aleksUIX" do
gem "vastlint"
endThe gem expects a platform-matched libvastlint shared library; release builds are vendored under lib/vastlint/native/, or point at one with VASTLINT_LIB_PATH.
Minimal example
require "vastlint"
result = Vastlint.validate(vast_xml)
if result.valid?
puts "clean tag"
else
puts result.summary.errors
puts result.issues.first.message
end
puts result.to_jsonRails controller
class VastValidationsController < ApplicationController
def create
result = Vastlint.validate(
params.require(:xml),
max_wrapper_depth: params[:max_wrapper_depth].presence&.to_i || 5,
rule_overrides: params[:rule_overrides]
)
render json: result.as_json
rescue ArgumentError, Vastlint::Error => error
render json: { error: error.message }, status: :unprocessable_entity
end
endThe response shape is stable and frontend-friendly: version, an issues array (each with id, severity, message, path, spec_ref, line, col), and a summary with error, warning, and info counts.
Why validate VAST in-process
A malformed VAST tag is a billed impression that never renders: the player loads, the auction clears, the publisher is charged, and the viewer sees a blank slot. The failure shows up in the player, not your Rails logs, so a bad tag can sit in rotation until someone traces a revenue dip back to it.
The gem calls the same Rust core the rest of the pipeline uses, in-process through FFI. No subprocess to spawn per request, no validation microservice to keep alive, and the XML never leaves your app. Because the result serialises to a stable JSON shape, the same call that gates a creative on the backend also feeds the reviewer's screen: the trafficker sees exactly what the system enforced.
Where it lands in an SSP, DSP, or ad server
Ruby and Rails tend to run the ad-ops and trafficking side of the stack rather than the microsecond bid path, so validation lands where humans and creatives meet the system.
- Creative ingestion / upload: validate in the controller when a tag is submitted, and reject it with the specific issues before it is ever trafficked.
- Trafficking and admin review: back a creative-QA screen so an ad-ops reviewer sees errors and warnings inline as they approve a tag.
- Batch QA jobs: a nightly Sidekiq or rake task that re-validates every active tag and flags drift after upstream changes.
- Demand-partner intake: validate sample
admpayloads from a new SSP or DSP partner during onboarding and report error rates back as part of the SLA.
When not to use the Ruby gem
If you just want a quick manual answer, use the web validator. If you only have a live tag URL, use the tester. If the real problem is wrapper depth or redirect chains, jump to the inspector.