├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── duration.go ├── duration_test.go ├── event_type.go ├── extension.go ├── extension_test.go ├── go.mod ├── go.sum ├── offset.go ├── offset_test.go ├── testdata ├── creative_extensions.xml ├── extraspaces_vpaid.xml ├── iab │ └── vast_4.2_samples │ │ ├── Ad_Verification-test.xml │ │ ├── Category-test.xml │ │ ├── Closed_Caption_Test.xml │ │ ├── Event_Tracking-test.xml │ │ ├── IconClickFallbacks.xml │ │ ├── Inline_Companion_Tag-test.xml │ │ ├── Inline_Linear_Tag-test.xml │ │ ├── Inline_Non-Linear_Tag-test.xml │ │ ├── Inline_Simple.xml │ │ ├── LICENSE │ │ ├── No_Wrapper_Tag-test.xml │ │ ├── Ready_to_serve_Media_Files_check-test.xml │ │ ├── Universal_Ad_ID-multi-test.xml │ │ ├── Video_Clicks_and_click_tracking-Inline-test.xml │ │ ├── Viewable_Impression-test.xml │ │ └── Wrapper_Tag-test.xml ├── inline_extensions.xml ├── liverail-vast2-linear-companion.xml ├── liverail-vast2-nonlinear.xml ├── spotx_adparameters.txt ├── spotx_html_resource.html ├── spotx_vpaid.xml ├── vast4_universal_ad_id.xml ├── vast_adaptv_attempt_attr.xml ├── vast_inline_linear-duration_undefined.xml ├── vast_inline_linear.xml ├── vast_inline_nonlinear.xml ├── vast_wrapper_linear_1.xml ├── vast_wrapper_linear_2.xml ├── vast_wrapper_nonlinear_1.xml └── vast_wrapper_nonlinear_2.xml ├── vast.go ├── vast4.go └── vast_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/* 2 | !vendor/vendor.json 3 | coverage.out 4 | count.out 5 | test 6 | profile.out 7 | tmp.out 8 | 9 | .settings/ 10 | .project 11 | runtime/ 12 | .idea/ 13 | .git/ 14 | .DS_Store 15 | .buildpath 16 | *.patch -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | go_import_path: github.com/haxqer/vast 5 | env: 6 | global: 7 | - TEST_TIMEOUT_SCALE=10 8 | - GO111MODULE=on 9 | 10 | matrix: 11 | include: 12 | - go: 1.13.x 13 | env: LINT=1 14 | 15 | script: 16 | - test -z "$LINT" || make lint 17 | - make test 18 | - make bench 19 | 20 | after_success: 21 | - make cover 22 | - bash <(curl -s https://codecov.io/bash) 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 haxqer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vast 2 | 3 | VAST 4.2 : https://github.com/haxqer/vast/tree/4.2 4 | 5 | XML/Json 6 | 7 | :star: VAST Ad generator and parser library on GoLang. 8 | 9 | ## todo 10 | - [x] Support for all TrackEvents 11 | 12 | ## Specs 13 | * VAST 2.0 Spec: http://www.iab.net/media/file/VAST-2_0-FINAL.pdf 14 | * VAST 3.0 Spec: http://www.iab.com/wp-content/uploads/2015/06/VASTv3_0.pdf 15 | * VAST 4.0 Spec: 16 | * http://www.iab.com/wp-content/uploads/2016/01/VAST_4-0_2016-01-21.pdf 17 | * https://www.iab.com/wp-content/uploads/2016/04/VAST4.0_Updated_April_2016.pdf 18 | * VAST 4.1 Spec: 19 | * https://iabtechlab.com/wp-content/uploads/2018/11/VAST4.1-final-Nov-8-2018.pdf 20 | * VAST 4.2 Spec: 21 | * https://iabtechlab.com/wp-content/uploads/2019/06/VAST_4.2_final_june26.pdf 22 | * [VAST Samples](https://github.com/InteractiveAdvertisingBureau/VAST_Samples) 23 | 24 | ## Installation 25 | 26 | `go get -u github.com/haxqer/vast` 27 | 28 | 29 | 30 | ## Quick Start 31 | 32 | ```go 33 | package main 34 | 35 | import ( 36 | "encoding/xml" 37 | "fmt" 38 | . "github.com/haxqer/vast" 39 | "time" 40 | ) 41 | 42 | func main() { 43 | v := VAST{ 44 | Version: "3.0", 45 | Ads: []Ad{ 46 | { 47 | ID: "123", 48 | Type: "front", 49 | InLine: &InLine{ 50 | AdSystem: &AdSystem{Name: "DSP"}, 51 | AdTitle: CDATAString{CDATA: "adTitle"}, 52 | Impressions: []Impression{ 53 | {ID: "11111", URI: "http://impressionv1.track.com"}, 54 | {ID: "11112", URI: "http://impressionv2.track.com"}, 55 | }, 56 | Creatives: []Creative{ 57 | { 58 | ID: "987", 59 | Sequence: 0, 60 | Linear: &Linear{ 61 | Duration: Duration(15 * time.Second), 62 | TrackingEvents: []Tracking{ 63 | {Event: Event_type_start, URI: "http://track.xxx.com/q/start?xx"}, 64 | {Event: Event_type_firstQuartile, URI: "http://track.xxx.com/q/firstQuartile?xx"}, 65 | {Event: Event_type_midpoint, URI: "http://track.xxx.com/q/midpoint?xx"}, 66 | {Event: Event_type_thirdQuartile, URI: "http://track.xxx.com/q/thirdQuartile?xx"}, 67 | {Event: Event_type_complete, URI: "http://track.xxx.com/q/complete?xx"}, 68 | }, 69 | MediaFiles: []MediaFile{ 70 | { 71 | Delivery: "progressive", 72 | Type: "video/mp4", 73 | Width: 1024, 74 | Height: 576, 75 | URI: "http://mp4.res.xxx.com/new_video/2020/01/14/1485/335928CBA9D02E95E63ED9F4D45DF6DF_20200114_1_1_1051.mp4", 76 | }, 77 | }, 78 | }, 79 | }, 80 | }, 81 | }, 82 | }, 83 | }, 84 | } 85 | vastXMLText, _ := xml.Marshal(v) 86 | fmt.Printf("%s", vastXMLText) 87 | } 88 | 89 | ``` 90 | 91 | Result Demo 92 | ```xml 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 00:00:15 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | ``` 124 | 125 | ## Thanks 126 | + https://github.com/rs/vast 127 | + https://github.com/xsharp -------------------------------------------------------------------------------- /duration.go: -------------------------------------------------------------------------------- 1 | package vast 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | "time" 8 | ) 9 | 10 | // Duration is a VAST duration expressed a hh:mm:ss 11 | type Duration time.Duration 12 | 13 | // MarshalText implements the encoding.TextMarshaler interface. 14 | func (dur Duration) MarshalText() ([]byte, error) { 15 | h := dur / Duration(time.Hour) 16 | m := dur % Duration(time.Hour) / Duration(time.Minute) 17 | s := dur % Duration(time.Minute) / Duration(time.Second) 18 | ms := dur % Duration(time.Second) / Duration(time.Millisecond) 19 | if ms == 0 { 20 | return []byte(fmt.Sprintf("%02d:%02d:%02d", h, m, s)), nil 21 | } 22 | return []byte(fmt.Sprintf("%02d:%02d:%02d.%03d", h, m, s, ms)), nil 23 | } 24 | 25 | // UnmarshalText implements the encoding.TextUnmarshaler interface. 26 | func (dur *Duration) UnmarshalText(data []byte) (err error) { 27 | s := string(data) 28 | s = strings.TrimSpace(s) 29 | if s == "" || strings.ToLower(s) == "undefined" { 30 | *dur = 0 31 | return nil 32 | } 33 | parts := strings.SplitN(s, ":", 3) 34 | if len(parts) != 3 { 35 | return fmt.Errorf("invalid duration: %s", data) 36 | } 37 | if i := strings.IndexByte(parts[2], '.'); i > 0 { 38 | ms, err := strconv.ParseInt(parts[2][i+1:], 10, 32) 39 | if err != nil || ms < 0 || ms > 999 { 40 | return fmt.Errorf("invalid duration: %s", data) 41 | } 42 | parts[2] = parts[2][:i] 43 | *dur += Duration(ms) * Duration(time.Millisecond) 44 | } 45 | f := Duration(time.Second) 46 | for i := 2; i >= 0; i-- { 47 | n, err := strconv.ParseInt(parts[i], 10, 32) 48 | if err != nil || n < 0 || n > 59 { 49 | return fmt.Errorf("invalid duration: %s", data) 50 | } 51 | *dur += Duration(n) * f 52 | f *= 60 53 | } 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /duration_test.go: -------------------------------------------------------------------------------- 1 | package vast 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestDurationMarshaler(t *testing.T) { 11 | b, err := Duration(0).MarshalText() 12 | if assert.NoError(t, err) { 13 | assert.Equal(t, "00:00:00", string(b)) 14 | } 15 | b, err = Duration(2 * time.Millisecond).MarshalText() 16 | if assert.NoError(t, err) { 17 | assert.Equal(t, "00:00:00.002", string(b)) 18 | } 19 | b, err = Duration(2 * time.Second).MarshalText() 20 | if assert.NoError(t, err) { 21 | assert.Equal(t, "00:00:02", string(b)) 22 | } 23 | b, err = Duration(2 * time.Minute).MarshalText() 24 | if assert.NoError(t, err) { 25 | assert.Equal(t, "00:02:00", string(b)) 26 | } 27 | b, err = Duration(2 * time.Hour).MarshalText() 28 | if assert.NoError(t, err) { 29 | assert.Equal(t, "02:00:00", string(b)) 30 | } 31 | } 32 | 33 | func TestDurationUnmarshal(t *testing.T) { 34 | var d Duration 35 | if assert.NoError(t, d.UnmarshalText([]byte("00:00:00"))) { 36 | assert.Equal(t, Duration(0), d) 37 | } 38 | d = 0 39 | if assert.NoError(t, d.UnmarshalText([]byte("00:00:02"))) { 40 | assert.Equal(t, Duration(2*time.Second), d) 41 | } 42 | d = 0 43 | if assert.NoError(t, d.UnmarshalText([]byte(" 00:00:02 "))) { 44 | assert.Equal(t, Duration(2*time.Second), d) 45 | } 46 | d = 0 47 | if assert.NoError(t, d.UnmarshalText([]byte("00:02:00"))) { 48 | assert.Equal(t, Duration(2*time.Minute), d) 49 | } 50 | d = 0 51 | if assert.NoError(t, d.UnmarshalText([]byte("02:00:00"))) { 52 | assert.Equal(t, Duration(2*time.Hour), d) 53 | } 54 | d = 0 55 | if assert.NoError(t, d.UnmarshalText([]byte("00:00:00.123"))) { 56 | assert.Equal(t, Duration(123*time.Millisecond), d) 57 | } 58 | d = 0 59 | if assert.NoError(t, d.UnmarshalText([]byte("undefined"))) { 60 | assert.Equal(t, Duration(0), d) 61 | } 62 | d = 0 63 | if assert.NoError(t, d.UnmarshalText([]byte(""))) { 64 | assert.Equal(t, Duration(0), d) 65 | } 66 | assert.EqualError(t, d.UnmarshalText([]byte("00:00:60")), "invalid duration: 00:00:60") 67 | assert.EqualError(t, d.UnmarshalText([]byte("00:60:00")), "invalid duration: 00:60:00") 68 | assert.EqualError(t, d.UnmarshalText([]byte("00:00:00.-1")), "invalid duration: 00:00:00.-1") 69 | assert.EqualError(t, d.UnmarshalText([]byte("00:00:00.1000")), "invalid duration: 00:00:00.1000") 70 | assert.EqualError(t, d.UnmarshalText([]byte("00h01m")), "invalid duration: 00h01m") 71 | } 72 | -------------------------------------------------------------------------------- /event_type.go: -------------------------------------------------------------------------------- 1 | package vast 2 | 3 | const ( 4 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 | // Player Operation Metrics (for use in Linear and NonLinear Ads) 6 | 7 | // the user activated the mute control and muted the creative. 8 | EventTypeMute = "mute" 9 | // the user activated the mute control and unmuted the creative. 10 | EventTypeUnmute = "unmute" 11 | // the user clicked the pause control and stopped the creative. 12 | EventTypePause = "pause" 13 | // the user activated the resume control after the creative had been stopped or paused. 14 | EventTypeResume = "resume" 15 | // the user activated the rewind control to access a previous point in the creative timeline. 16 | EventTypeRewind = "rewind" 17 | // the user activated a skip control to skip the creative, which is a 18 | // different control than the one used to close the creative. 19 | EventTypeSkip = "skip" 20 | // the user activated a control to extend the player to a larger size. This 21 | // event replaces the fullscreen event per the 2014 Digital Video In-Stream Ad Metric 22 | // Definitions. 23 | EventTypePlayerExpand = "playerExpand" 24 | // the user activated a control to reduce player to a smaller size. This 25 | // event replaces the exitFullscreen event per the 2014 Digital Video In-Stream Ad 26 | // Metric Definitions. 27 | EventTypePlayerCollapse = "playerCollapse" 28 | // This ad was not and will not be played (e.g. it was prefetched for a particular 29 | // ad break but was not chosen for playback). This allows ad servers to reuse an ad earlier 30 | // than otherwise would be possible due to budget/frequency capping. This is a terminal 31 | // event; no other tracking events should be sent when this is used. Player support is 32 | // optional and if implemented is provided on a best effort basis as it is not technically 33 | // possible to fire this event for every unused ad (e.g. when the player itself is terminated 34 | // before playback) 35 | EventTypeNotUsed = "notUsed" 36 | 37 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 38 | // Linear Ad Metrics 39 | 40 | // This event should be used to indicate when the player considers that 41 | // it has loaded and buffered the creative’s media and assets either fully or 42 | // to the extent that it is ready to play the media 43 | EventTypeLoaded = "loaded" 44 | // this event is used to indicate that an individual creative within the ad was loaded and playback 45 | //began. As with creativeView, this event is another way of tracking creative playback. 46 | EventTypeStart = "start" 47 | // the creative played for at least 25% of the total duration. 48 | EventTypeFirstQuartile = "firstQuartile" 49 | // the creative played for at least 50% of the total duration. 50 | EventTypeMidpoint = "midpoint" 51 | // the creative played for at least 75% of the duration. 52 | EventTypeThirdQuartile = "thirdQuartile" 53 | // The creative was played to the end at normal speed. 54 | EventTypeComplete = "complete" 55 | // An optional metric that can capture all other user interactions under one metric such a s hover-overs, or custom clicks. 56 | // It should NOT replace clickthrough events or other existing events like mute, unmute, pause, etc. 57 | EventTypeOtherAdInteraction = "otherAdInteraction" 58 | // the creative played for a duration at normal speed that is equal to or greater than the 59 | // value provided in an additional attribute for offset . Offset values can be time in the format 60 | // HH:MM:SS or HH:MM:SS.mmm or a percentage value in the format n% . Multiple progress ev 61 | EventTypeProgress = "progress" 62 | // the user clicked the close button on the creative. The name of this event distinguishes it 63 | // from the existing “close” event described in the 2008 IAB Digital Video In-Stream Ad Metrics 64 | // Definitions, which defines the “close” metric as applying to non-linear ads only. The “closeLinear” event 65 | // extends the “close” event for use in Linear creative. 66 | EventTypeCloseLinear = "closeLinear" 67 | 68 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 69 | // NonLinear Ad Metrics 70 | 71 | // Not to be confused with an impression, this event indicates that an individual creative portion of the ad was viewed. 72 | // An impression indicates that at least a portion of the ad was displayed; 73 | // however an ad may be composed of multiple creative, or creative that only play on some platforms and not others. 74 | // This event enables ad servers to track which ad creative are viewed, and therefore, which platforms are more common. 75 | EventTypeCreativeView = "creativeView" 76 | // The user clicked or otherwise activated a control used to pause streaming content, 77 | // which either expands the ad within the player’s viewable area or “takes-over” the streaming content area 78 | // by launching an additional portion of the ad. 79 | // An ad in video format ad is usually played upon acceptance, but other forms of media such as games, animation, 80 | // tutorials, social media, or other engaging media are also used. 81 | EventTypeAcceptInvitation = "acceptInvitation" 82 | // The user activated a control to expand the creative. 83 | EventTypeAdExpand = "adExpand" 84 | // The user activated a control to reduce the creative to its original dimensions. 85 | EventTypeAdCollapse = "adCollapse" 86 | // The user clicked or otherwise activated a control used to minimize the ad 87 | // to a size smaller than a collapsed ad but without fully dispatching the ad from the player environment. 88 | // Unlike a collapsed ad that is big enough to display it’s message, 89 | // the minimized ad is only big enough to offer a control that enables the user to redisplay the ad if desired. 90 | EventTypeMinimize = "minimize" 91 | // The user clicked or otherwise activated a control for removing the ad, 92 | // which fully dispatches the ad from the player environment in a manner that does not allow the user to re-display the ad. 93 | EventTypeClose = "close" 94 | // The time that the initial ad is displayed. 95 | // This time is based on the time between the impression and either the completed length of display based on the agreement between 96 | // transactional parties or a close, minimize, or accept invitation event. 97 | EventTypeOverlayViewDuration = "overlayViewDuration" 98 | 99 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 100 | // Interactive Ad Metric 101 | 102 | // With VAST 4, video playback and interactive creative playback now happens in parallel. 103 | // Video playback and interactive creative start may not happen at the same time. 104 | // A separate way of tracking the interactive creative start is needed. 105 | // The interactive creative specification (SIMID, etc.) will define when this event should be fired. 106 | EventTypeInteractiveStart = "interactiveStart" 107 | 108 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 109 | // Other 110 | 111 | EventTypeView = "view" 112 | EventTypeMonitor = "monitor" 113 | ) 114 | -------------------------------------------------------------------------------- /extension.go: -------------------------------------------------------------------------------- 1 | package vast 2 | 3 | import "encoding/xml" 4 | 5 | // Extension represent arbitrary XML provided by the platform to extend the 6 | // VAST response or by custom trackers. 7 | type Extension struct { 8 | Type string `xml:"type,attr,omitempty"` 9 | CustomTracking []Tracking `xml:"CustomTracking>Tracking,omitempty" json:",omitempty"` 10 | Data string `xml:",innerxml" json:",omitempty"` 11 | } 12 | 13 | // the extension type as a middleware in the encoding process. 14 | type extension Extension 15 | 16 | type extensionNoCT struct { 17 | Type string `xml:"type,attr,omitempty"` 18 | Data string `xml:",innerxml" json:",omitempty"` 19 | } 20 | 21 | // MarshalXML implements xml.Marshaler interface. 22 | func (e Extension) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { 23 | // create a temporary element from a wrapper Extension, copy what we need to 24 | // it and return it's encoding. 25 | var e2 interface{} 26 | // if we have custom trackers, we should ignore the data, if not, then we 27 | // should consider only the data. 28 | if len(e.CustomTracking) > 0 { 29 | e2 = extension{Type: e.Type, CustomTracking: e.CustomTracking} 30 | } else { 31 | e2 = extensionNoCT{Type: e.Type, Data: e.Data} 32 | } 33 | 34 | return enc.EncodeElement(e2, start) 35 | } 36 | 37 | // UnmarshalXML implements xml.Unmarshaler interface. 38 | func (e *Extension) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { 39 | // decode the extension into a temporary element from a wrapper Extension, 40 | // copy what we need over. 41 | var e2 extension 42 | if err := dec.DecodeElement(&e2, &start); err != nil { 43 | return err 44 | } 45 | // copy the type and the customTracking 46 | e.Type = e2.Type 47 | e.CustomTracking = e2.CustomTracking 48 | // copy the data only of customTracking is empty 49 | if len(e.CustomTracking) == 0 { 50 | e.Data = e2.Data 51 | } 52 | return nil 53 | } 54 | -------------------------------------------------------------------------------- /extension_test.go: -------------------------------------------------------------------------------- 1 | package vast 2 | 3 | import ( 4 | "encoding/xml" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | var ( 11 | extensionCustomTracking = []byte(``) 12 | extensionData = []byte(`Generic`) 13 | ) 14 | 15 | func TestExtensionCustomTrackingMarshal(t *testing.T) { 16 | e := Extension{ 17 | Type: "testCustomTracking", 18 | CustomTracking: []Tracking{ 19 | { 20 | Event: "event.1", 21 | URI: "http://event.1", 22 | }, 23 | { 24 | Event: "event.2", 25 | URI: "http://event.2", 26 | }, 27 | }, 28 | } 29 | 30 | // marshal the extension 31 | xmlExtensionOutput, err := xml.Marshal(e) 32 | assert.NoError(t, err) 33 | 34 | // assert the resulting marshaled extension 35 | assert.Equal(t, string(extensionCustomTracking), string(xmlExtensionOutput)) 36 | } 37 | 38 | func TestExtensionCustomTracking(t *testing.T) { 39 | // unmarshal the Extension 40 | var e Extension 41 | assert.NoError(t, xml.Unmarshal(extensionCustomTracking, &e)) 42 | 43 | // assert the resulting extension 44 | assert.Equal(t, "testCustomTracking", e.Type) 45 | assert.Empty(t, string(e.Data)) 46 | if assert.Len(t, e.CustomTracking, 2) { 47 | // first event 48 | assert.Equal(t, "event.1", e.CustomTracking[0].Event) 49 | assert.Equal(t, "http://event.1", e.CustomTracking[0].URI) 50 | // second event 51 | assert.Equal(t, "event.2", e.CustomTracking[1].Event) 52 | assert.Equal(t, "http://event.2", e.CustomTracking[1].URI) 53 | } 54 | 55 | // marshal the extension 56 | xmlExtensionOutput, err := xml.Marshal(e) 57 | assert.NoError(t, err) 58 | 59 | // assert the resulting marshaled extension 60 | assert.Equal(t, string(extensionCustomTracking), string(xmlExtensionOutput)) 61 | } 62 | 63 | func TestExtensionGeneric(t *testing.T) { 64 | // unmarshal the Extension 65 | var e Extension 66 | assert.NoError(t, xml.Unmarshal(extensionData, &e)) 67 | 68 | // assert the resulting extension 69 | assert.Equal(t, "testCustomTracking", e.Type) 70 | assert.Equal(t, "Generic", string(e.Data)) 71 | assert.Empty(t, e.CustomTracking) 72 | 73 | // marshal the extension 74 | xmlExtensionOutput, err := xml.Marshal(e) 75 | assert.NoError(t, err) 76 | 77 | // assert the resulting marshaled extension 78 | assert.Equal(t, string(extensionData), string(xmlExtensionOutput)) 79 | } 80 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/haxqer/vast 2 | 3 | go 1.13 4 | 5 | require ( 6 | aqwari.net/xml v0.0.0-20210331023308-d9421b293817 7 | github.com/davecgh/go-spew v1.1.1 // indirect 8 | github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 9 | github.com/stretchr/testify v1.5.1 10 | gopkg.in/yaml.v2 v2.2.8 // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | aqwari.net/xml v0.0.0-20210331023308-d9421b293817 h1:+3Rh5EaTzNLnzWx3/uy/mAaH/dGI7svJ6e0oOIDcPuE= 2 | aqwari.net/xml v0.0.0-20210331023308-d9421b293817/go.mod h1:c7kkWzc7HS/t8Q2DcVY8P2d1dyWNEhEVT5pL0ZHO11c= 3 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 5 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 6 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 7 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 8 | github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20= 9 | github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= 10 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 11 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= 12 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 13 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 14 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 15 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 16 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 17 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 18 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 19 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 20 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 21 | golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4= 22 | golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 23 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 24 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 25 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 26 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 27 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 28 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 29 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 30 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 31 | golang.org/x/tools v0.0.0-20200821192610-3366bbee4705/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 32 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 33 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 34 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 35 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 36 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 37 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 38 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 39 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 40 | -------------------------------------------------------------------------------- /offset.go: -------------------------------------------------------------------------------- 1 | package vast 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | ) 8 | 9 | // Offset represents either a vast.Duration or a percentage of the video duration. 10 | type Offset struct { 11 | // If not nil, the Offset is duration based 12 | Duration *Duration 13 | // If Duration is nil, the Offset is percent based 14 | Percent float32 15 | } 16 | 17 | // MarshalText implements the encoding.TextMarshaler interface. 18 | func (o Offset) MarshalText() ([]byte, error) { 19 | if o.Duration != nil { 20 | return o.Duration.MarshalText() 21 | } 22 | return []byte(fmt.Sprintf("%d%%", int(o.Percent*100))), nil 23 | } 24 | 25 | // UnmarshalText implements the encoding.TextUnmarshaler interface. 26 | func (o *Offset) UnmarshalText(data []byte) error { 27 | if strings.HasSuffix(string(data), "%") { 28 | p, err := strconv.ParseInt(string(data[:len(data)-1]), 10, 8) 29 | if err != nil { 30 | return fmt.Errorf("invalid offset: %s", data) 31 | } 32 | o.Percent = float32(p) / 100 33 | return nil 34 | } 35 | var d Duration 36 | o.Duration = &d 37 | return o.Duration.UnmarshalText(data) 38 | } 39 | -------------------------------------------------------------------------------- /offset_test.go: -------------------------------------------------------------------------------- 1 | package vast 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestOffsetMarshaler(t *testing.T) { 10 | b, err := Offset{}.MarshalText() 11 | if assert.NoError(t, err) { 12 | assert.Equal(t, "0%", string(b)) 13 | } 14 | b, err = Offset{Percent: .1}.MarshalText() 15 | if assert.NoError(t, err) { 16 | assert.Equal(t, "10%", string(b)) 17 | } 18 | d := Duration(0) 19 | b, err = Offset{Duration: &d}.MarshalText() 20 | if assert.NoError(t, err) { 21 | assert.Equal(t, "00:00:00", string(b)) 22 | } 23 | } 24 | 25 | func TestOffsetUnmarshaler(t *testing.T) { 26 | var o Offset 27 | if assert.NoError(t, o.UnmarshalText([]byte("0%"))) { 28 | assert.Nil(t, o.Duration) 29 | assert.Equal(t, float32(0.0), o.Percent) 30 | } 31 | o = Offset{} 32 | if assert.NoError(t, o.UnmarshalText([]byte("10%"))) { 33 | assert.Nil(t, o.Duration) 34 | assert.Equal(t, float32(0.1), o.Percent) 35 | } 36 | o = Offset{} 37 | if assert.NoError(t, o.UnmarshalText([]byte("00:00:00"))) { 38 | if assert.NotNil(t, o.Duration) { 39 | assert.Equal(t, Duration(0), *o.Duration) 40 | } 41 | assert.Equal(t, float32(0), o.Percent) 42 | } 43 | o = Offset{} 44 | assert.EqualError(t, o.UnmarshalText([]byte("abc%")), "invalid offset: abc%") 45 | } 46 | -------------------------------------------------------------------------------- /testdata/creative_extensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | US 10 | 3 11 | 1680 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Generic 21 | 22 | 23 | MubmWKCWLs_tiQPYiYrwBw 24 | CIGpsPCTkdMCFdN-Ygod-xkCKQ 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /testdata/extraspaces_vpaid.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SpotXchange 6 | 7 | 8 | 9 | 10 | 11 | 00:00:16 12 | 13 | ]]> 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Ad_Verification-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | a532d16d-4d7f-4440-bd29-2ec0e693fc80 14 | iabtechlab video ad 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | IAB Sample Company 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 00:00:16 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 8465 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Category-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | a532d16d-4d7f-4440-bd29-2ec0e693fc82 9 | iabtechlab video ad 10 | American Cuisine 11 | Guitar 12 | Vegan 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 00:00:16 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 8465 35 | 6666465 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Closed_Caption_Test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | a532d16d-4d7f-4440-bd29-2ec0e693fc83 14 | iabtechlab video ad 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 00:00:16 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 8465 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Event_Tracking-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | 9 | 1 10 | 11 | 12 | 13 | 14 | a532d16d-4d7f-4440-bd29-2ec0e693fc80 15 | iabtechlab video ad 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 00:00:16 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 8465 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/IconClickFallbacks.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | a532d16d-4d7f-4440-bd29-2ec0e693fc80 9 | iabtechlab video ad 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | The live click interaction 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 00:00:16 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 8465 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Inline_Companion_Tag-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | a532d16d-4d7f-4440-bd29-2ec0e693fc80 9 | VAST 4.0 Pilot - Scenario 5 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 8465 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 00:00:16 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 8466 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Inline_Linear_Tag-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | a532d16d-4d7f-4440-bd29-2ec0e693fc80 14 | iabtechlab video ad 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 00:00:16 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 8465 37 | 4444323 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Inline_Non-Linear_Tag-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | a532d16d-4d7f-4440-bd29-2ec0e693fc80 14 | VAST 4.0 Pilot - Scenario 5 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 8465 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Inline_Simple.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | a532d16d-4d7f-4440-bd29-2ec05553fc80 8 | Inline Simple Ad 9 | 10 | IAB Sample Company 11 | AD CONTENT description category 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 00:00:16 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 8465 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/LICENSE: -------------------------------------------------------------------------------- 1 | THE STANDARDS, THE SPECIFICATIONS, THE MEASUREMENT GUIDELINES, AND ANY OTHER MATERIALS OR SERVICES PROVIDED TO OR USED BY YOU HEREUNDER (THE “PRODUCTS AND SERVICES”) ARE PROVIDED “AS IS” AND “AS AVAILABLE,” AND IAB TECHNOLOGY LABORATORY, INC. (“TECH LAB”) MAKES NO WARRANTY WITH RESPECT TO THE SAME AND HEREBY DISCLAIMS ANY AND ALL EXPRESS, IMPLIED, OR STATUTORY WARRANTIES, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AVAILABILITY, ERROR-FREE OR UNINTERRUPTED OPERATION, AND ANY WARRANTIES ARISING FROM A COURSE OF DEALING, COURSE OF PERFORMANCE, OR USAGE OF TRADE. TO THE EXTENT THAT TECH LAB MAY NOT AS A MATTER OF APPLICABLE LAW DISCLAIM ANY IMPLIED WARRANTY, THE SCOPE AND DURATION OF SUCH WARRANTY WILL BE THE MINIMUM PERMITTED UNDER SUCH LAW. THE PRODUCTS AND SERVICES DO NOT CONSTITUTE BUSINESS OR LEGAL ADVICE. TECH LAB DOES NOT WARRANT THAT THE PRODUCTS AND SERVICES PROVIDED TO OR USED BY YOU HEREUNDER SHALL CAUSE YOU AND/OR YOUR PRODUCTS OR SERVICES TO BE IN COMPLIANCE WITH ANY APPLICABLE LAWS, REGULATIONS, OR SELF-REGULATORY FRAMEWORKS, AND YOU ARE SOLELY RESPONSIBLE FOR COMPLIANCE WITH THE SAME, INCLUDING, BUT NOT LIMITED TO, DATA PROTECTION LAWS, SUCH AS THE PERSONAL INFORMATION PROTECTION AND ELECTRONIC DOCUMENTS ACT (CANADA), THE DATA PROTECTION DIRECTIVE (EU), THE E-PRIVACY DIRECTIVE (EU), THE GENERAL DATA PROTECTION REGULATION (EU), AND THE E-PRIVACY REGULATION (EU) AS AND WHEN THEY BECOME EFFECTIVE. 2 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/No_Wrapper_Tag-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | a532d16d-4d7f-4440-bd29-2ec0e693fc80 9 | iabtechlab video ad 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 00:00:16 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 8465 32 | AA8465 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Ready_to_serve_Media_Files_check-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | a532d16d-4d7f-4440-bd29-2ec0e693fc80 14 | iabtechlab video ad 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 00:00:16 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 8465 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Universal_Ad_ID-multi-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | a532d16d-4d7f-4440-bd29-2ec0e693fc81 14 | iabtechlab video ad 15 | AD CONTENT description category 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 00:00:16 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 8465 38 | 9999 39 | ADSe9999 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Video_Clicks_and_click_tracking-Inline-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | a532d16d-4d7f-4440-bd29-2ec0e693fc89 14 | iabtechlab video ad 15 | AD CONTENT description category 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 00:00:16 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 8465 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Viewable_Impression-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /testdata/iab/vast_4.2_samples/Wrapper_Tag-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iabtechlab 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /testdata/inline_extensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | US 8 | 3 9 | 1680 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Generic 19 | 20 | 21 | MubmWKCWLs_tiQPYiYrwBw 22 | CIGpsPCTkdMCFdN-Ygod-xkCKQ 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /testdata/liverail-vast2-linear-companion.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | LiveRail 5 | 6 | 7 | 8 | 9 | 10 | 00:00:11 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /testdata/liverail-vast2-nonlinear.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | LiveRail 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /testdata/spotx_adparameters.txt: -------------------------------------------------------------------------------- 1 | {"ad_id":"1130507-1818483","title":"IntegralAds_VAST_2_0_Ad_Wrapper","page_url":"","media":{"ad_source":"rtb","syn":{"video_uri_required":1},"tracking":{"video_valid_first_frame":1,"beacon":[{"type":"skip","beacon_url":"https:\\/\\/search.spotxchange.com\\/beacon?_a=137530&_p=spotx&_z=1&_m=eNpVz99vgjAQB%2FD%2BLTyP0rM%2FLCZ7WOKWbFF5GJr4RAotUBUwgkHZ9rdvVB8W%2B3BJv3eXT45hQhBCwAnhEkKQKA2lZCHLhJYSwExTSgSkqcpBCEIIIKBTTglaf6JQ4glleAISAxOo7LpjOwuCvu9xrip7uJaq1tdK1ThrqgB9eefWnJLibLU385hRoTQ8FylPnSNzMgUtc6EpdY73dB%2B3bVKbflwYg6xp9tYkuqmUrceoNeqUlbg9Nt0lG7HCOGkcVGdtTZ2Z5IHyneU7zHea%2F8D93A6bcPR7e2i1XizuBW4R4oJcKPDx%2B99y5TuKD%2BU23rPlrhiW849dFG%2FstnqrVsPLJYrfYTm88mi%2BZ6uheP4DQppvcA%3D%3D&_l=eNplj01rwkAYhN%2FfsleLvJv9yEbooUXoxU1BDKW5yGazNUk1SZMNtVr%2Fe9VgofQyh5mHGYYqqrhiEEYykIyDABWgAi4wlAAUKKdcRIpD3zZ%2BD5MJSBpB3dQOEI6EkdmRZGVOZgSniEySO9Kar2bwNwcvVt%2B6%2BpeJrtCQbUu7dntbmHrj1m%2FOXXOKiOfYDp3xLl%2FvTPfufLs11v1n8cKeThAni8UoCDhVAparR%2FDdsGuLxrttP7XNDlBxRjORW5pxhRYjIYULc8nDyDLm8vH3%2BRxy%2BBhM7a3p%2FdhKWSgC8XcGvuNK8%2FQp2b%2BuiiKdb1AfNNfVw6eukkBXcfk8T4L0ZVnqQ3L%2FAyjAYKo%3D&_t=eNotjFFvwiAUhfkt99ksQDtQjA9Llix7qMsSF1NfGkpRmW0hhS1W538fFe%2FLuefLOafWUtkeLfaYS8wb1sznhGheZ5iTupZ7whjGmCB1lKZHdjjI3ihUp9YV0lOF0WkQ4E%2FGwQxcK8dguokQFr3XclDHyjutQFzByUF2OujBT67Rv0bp6dPnMIl3NpyrhCvp3GOc3GbQ2Ua3IOgMbOzSWzyEyBPGSAourl4wAYfW1rKFpRF4eQfO%2BpAAWRAaWSbAdHICWc45ziPKBSgTxkeIpOKgD8b2E2NkERGPIfvTh%2BGeozRLW03aYpQsb%2Biv2KzN7q3M19%2Flc7H9xFEv5eZrLLbv9GNzGnev5VhcXki5LVf%2F4KN2Bg%3D%3D&_b=eNozY%2FAL9fFBI2r8qiINo8IjDaJyA038wqOy%2FIz8Mv1CQqt83T3L%2FV0iDXyrUrJ9jbwyokJCbQF2oxP%2F&beacon_type=skip"},{"type":"exception","beacon_url":"https:\\/\\/search.spotxchange.com\\/exception?_a=137530&_p=spotx&_z=1&_m=eNpVz99vgjAQB%2FD%2BLTyP0rM%2FLCZ7WOKWbFF5GJr4RAotUBUwgkHZ9rdvVB8W%2B3BJv3eXT45hQhBCwAnhEkKQKA2lZCHLhJYSwExTSgSkqcpBCEIIIKBTTglaf6JQ4glleAISAxOo7LpjOwuCvu9xrip7uJaq1tdK1ThrqgB9eefWnJLibLU385hRoTQ8FylPnSNzMgUtc6EpdY73dB%2B3bVKbflwYg6xp9tYkuqmUrceoNeqUlbg9Nt0lG7HCOGkcVGdtTZ2Z5IHyneU7zHea%2F8D93A6bcPR7e2i1XizuBW4R4oJcKPDx%2B99y5TuKD%2BU23rPlrhiW849dFG%2FstnqrVsPLJYrfYTm88mi%2BZ6uheP4DQppvcA%3D%3D&_l=eNplj01rwkAYhN%2FfsleLvJv9yEbooUXoxU1BDKW5yGazNUk1SZMNtVr%2Fe9VgofQyh5mHGYYqqrhiEEYykIyDABWgAi4wlAAUKKdcRIpD3zZ%2BD5MJSBpB3dQOEI6EkdmRZGVOZgSniEySO9Kar2bwNwcvVt%2B6%2BpeJrtCQbUu7dntbmHrj1m%2FOXXOKiOfYDp3xLl%2FvTPfufLs11v1n8cKeThAni8UoCDhVAparR%2FDdsGuLxrttP7XNDlBxRjORW5pxhRYjIYULc8nDyDLm8vH3%2BRxy%2BBhM7a3p%2FdhKWSgC8XcGvuNK8%2FQp2b%2BuiiKdb1AfNNfVw6eukkBXcfk8T4L0ZVnqQ3L%2FAyjAYKo%3D&_t=eNpdUGFr2zAQ9W%2FR58SRXEgyQxkZXT%2BMOqVsI2QEhCydY2WypEly5iztf985CR3svhz33r17dweDBJ%2B0s9mHhi4EXai5Wi4Zg0V9RxesrkXD5nNKKctkK7TNXNgLq2UG78IzqUFIZ3k6eSAleWfIhHgjTkl3I8zmWB%2B1AsePwmjFGx1i4k0QVxpZoXg8xQQdKc8kpHpM0miwiUcUkpJOSB8hYJeVvA8GdW1KPpa72W7m9QAm%2F9ULm7DnCLl03Q3FNJ2uNqtPqmi%2Fto%2BPXb7XzUetOpFke0%2FRugFAc9cHOS5jdEza7hH%2FZ3Lx6OP0N8SUR%2B%2FSkOOK%2F%2FmVS7qku9mFRnWULVyucx4sdvOCF%2BTtDQkQQbY8epDjkV6MX0gQ4lgpOOpxjTO%2BMo3pMo5fYS68v33a9sbgrM4pMNdqQly84RhZxnJKs%2FX3p6fstSqq4XmzZT82L3%2Bqw%2Br0%2FFDR7UF11beXu3VRserweai6Lz%2FXD9v7vx8btes%3D&_b=eNozZfAL9fFBI2r8QzxNolwiK%2FxDkkF0VZS7W5ZfladJZJavkV94VK6%2Fi6exX4hTpr97qC0AcfcToA%3D%3D&beacon_type=exception&exception%5Bid%5D=%24EXCEPTION_ID&exception%5Bdata%5D=%24EXCEPTION_DATA&exception%5Btrace%5D=%24EXCEPTION_TRACE&syn%5Btiming%5D=%24TIMING_DATA"},{"type":"thirdQuartile","beacon_url":"https:\\/\\/search.spotxchange.com\\/beacon?_a=137530&_p=spotx&_z=1&_m=eNpFizsOwjAQBfdEaBd7HbugIFKgiY0QThF3mI9CTPoQcXbAgYIpRho9PblABABiRNZkSEM0WksjT%2BqsNdGliAIVxXi8klKISECiYIHQHGA%2B5lgyvL6Aa%2Br6J4J3BljhKIhz%2FqdZTzeVXfAVu6EVdtok65MIvry1fZdCvx9323C3fv2wQ7X6ANPiL68%3D&_l=eNpljl1rwjAUhs9vya1DTpomTYXdDMcQtKWgSHtTYsycH02rTZnV%2Bd%2FXKhuMnYv34nmfFw6VVPqSQRAKTzAfOEgPJfgcAwFAAaGuSneGwQAEDcGW1nTsShgZXclquyYjgkNEJsgTqVRbNu6HYI%2FqythfJ7xLzeqw1bk56w9lNyZ%2FN%2BbeU0Tsat2clDPrvFCnvXHVQWnz38Xevd0gWkynj0DAoeTQHfZ%2Fog%2FHRlmnVe0eAmUB9%2FjfBXzNdulntNvQeP6K2Vu2j8cvRVSkl6yYtelywuJxwrJl0sbz5PkbhgZPGQ%3D%3D&_t=eNpdUO9rwjAQ7d%2BSz1rTytQVxnBsftKOMUUcQkiTqw1LkyxJ%2FTHn%2F77UCoPly%2BXdu3fv7gqgTKvovsRjisd8xCeTJIFxMcTjpChomYxGGOMkYhUVKtJ2R5VgUdGpzqj7EH8ygDJkgTXWCrVDPWQkPXlRt%2BlkFPBecNBkT6XgpBTWeVJa2tGBpZy4k%2FNQo%2ByMrC%2FawKQA5YkLQpThHmoc2FClGGmsDLrKe%2BOy7WA7MOIIMv5qqPKhZg8x0%2FUtG0K%2FP11Pn3havVezWR3vRPkoeE09qx5wsC4BgrluLGuHkcL5boE%2Fk6tH4%2FoHcD52RvtjHEb855dN8ARvB1c6qB2r4LqdNqBCNUlJii6XQAC1rCLOAGuXNLS9ggfrWsRhL9oxzgiOvg3XdqRLE2rM7dKqkTL0qjUH2aEe0u6WDy%2BKkhjjKF%2FN59HPon5JFsvNYbOc3uXp4jt%2F3g039cdnvn45vT6%2FDfN0dfhYrg4BP%2FwCbHyzFQ%3D%3D&_b=eNozYfAL9fFBI2r8w12NI3N9TfyyHE39QzKyorIcDfxcko19qxxNfF2CsiOznDL9XPyyfatCbQFnrxOe&beacon_type=recurring&view_percent=75"},{"type":"midpoint","beacon_url":"https:\\/\\/search.spotxchange.com\\/beacon?_a=137530&_p=spotx&_z=1&_m=eNpFizsOwjAQBfdEaBd7HbugIFKgiY0QThF3mI9CTPoQcXbAgYIpRho9PblABABiRNZkSEM0WksjT%2BqsNdGliAIVxXi8klKISECiYIHQHGA%2B5lgyvL6Aa%2Br6J4J3BljhKIhz%2FqdZTzeVXfAVu6EVdtok65MIvry1fZdCvx9323C3fv2wQ7X6ANPiL68%3D&_l=eNpljl1rwjAUhs9vya1DTpomTYXdDMcQtKWgSHtTYsycH02rTZnV%2Bd%2FXKhuMnYv34nmfFw6VVPqSQRAKTzAfOEgPJfgcAwFAAaGuSneGwQAEDcGW1nTsShgZXclquyYjgkNEJsgTqVRbNu6HYI%2FqythfJ7xLzeqw1bk56w9lNyZ%2FN%2BbeU0Tsat2clDPrvFCnvXHVQWnz38Xevd0gWkynj0DAoeTQHfZ%2Fog%2FHRlmnVe0eAmUB9%2FjfBXzNdulntNvQeP6K2Vu2j8cvRVSkl6yYtelywuJxwrJl0sbz5PkbhgZPGQ%3D%3D&_t=eNpdUO9rwjAQ7d%2BSz1rTytQVxnBsftKOMUUcQkiTqw1LkyxJ%2FTHn%2F77UCoPly%2BXdu3fv7gqgTKvovsRjisd8xCeTJIFxMcTjpChomYxGGOMkYhUVKtJ2R5VgUdGpzqj7EH8ygDJkgTXWCrVDPWQkPXlRt%2BlkFPBecNBkT6XgpBTWeVJa2tGBpZy4k%2FNQo%2ByMrC%2FawKQA5YkLQpThHmoc2FClGGmsDLrKe%2BOy7WA7MOIIMv5qqPKhZg8x0%2FUtG0K%2FP11Pn3havVezWR3vRPkoeE09qx5wsC4BgrluLGuHkcL5boE%2Fk6tH4%2FoHcD52RvtjHEb855dN8ARvB1c6qB2r4LqdNqBCNUlJii6XQAC1rCLOAGuXNLS9ggfrWsRhL9oxzgiOvg3XdqRLE2rM7dKqkTL0qjUH2aEe0u6WDy%2BKkhjjKF%2FN59HPon5JFsvNYbOc3uXp4jt%2F3g039cdnvn45vT6%2FDfN0dfhYrg4BP%2FwCbHyzFQ%3D%3D&_b=eNozZvAL9fFBI2r8srJN%2FENcjf1cnHIjQ6Jyo3J9q6LC%2FbJ9XVwrfKu8cn1dQg0ic%2F2AMNQWAHwnFGs%3D&beacon_type=recurring&view_percent=50"},{"type":"firstQuartile","beacon_url":"https:\\/\\/search.spotxchange.com\\/beacon?_a=137530&_p=spotx&_z=1&_m=eNpFizsOwjAQBfdEaBd7HbugIFKgiY0QThF3mI9CTPoQcXbAgYIpRho9PblABABiRNZkSEM0WksjT%2BqsNdGliAIVxXi8klKISECiYIHQHGA%2B5lgyvL6Aa%2Br6J4J3BljhKIhz%2FqdZTzeVXfAVu6EVdtok65MIvry1fZdCvx9323C3fv2wQ7X6ANPiL68%3D&_l=eNpljl1rwjAUhs9vya1DTpomTYXdDMcQtKWgSHtTYsycH02rTZnV%2Bd%2FXKhuMnYv34nmfFw6VVPqSQRAKTzAfOEgPJfgcAwFAAaGuSneGwQAEDcGW1nTsShgZXclquyYjgkNEJsgTqVRbNu6HYI%2FqythfJ7xLzeqw1bk56w9lNyZ%2FN%2BbeU0Tsat2clDPrvFCnvXHVQWnz38Xevd0gWkynj0DAoeTQHfZ%2Fog%2FHRlmnVe0eAmUB9%2FjfBXzNdulntNvQeP6K2Vu2j8cvRVSkl6yYtelywuJxwrJl0sbz5PkbhgZPGQ%3D%3D&_t=eNpdUO9rwjAQ7d%2BSz1rTytQVxnBsftKOMUUcQkiTqw1LkyxJ%2FTHn%2F77UCoPly%2BXdu3fv7gqgTKvovsRjisd8xCeTJIFxMcTjpChomYxGGOMkYhUVKtJ2R5VgUdGpzqj7EH8ygDJkgTXWCrVDPWQkPXlRt%2BlkFPBecNBkT6XgpBTWeVJa2tGBpZy4k%2FNQo%2ByMrC%2FawKQA5YkLQpThHmoc2FClGGmsDLrKe%2BOy7WA7MOIIMv5qqPKhZg8x0%2FUtG0K%2FP11Pn3havVezWR3vRPkoeE09qx5wsC4BgrluLGuHkcL5boE%2Fk6tH4%2FoHcD52RvtjHEb855dN8ARvB1c6qB2r4LqdNqBCNUlJii6XQAC1rCLOAGuXNLS9ggfrWsRhL9oxzgiOvg3XdqRLE2rM7dKqkTL0qjUH2aEe0u6WDy%2BKkhjjKF%2FN59HPon5JFsvNYbOc3uXp4jt%2F3g039cdnvn45vT6%2FDfN0dfhYrg4BP%2FwCbHyzFQ%3D%3D&_b=eNozYvAL9fFBI2p8qxwNIrOyK6JCUnL8XUIr%2FEIyMiOz0iv83X0rfLOyTX2rko38XVwrIqsibQGT7hUz&beacon_type=recurring&view_percent=25"},{"type":"complete","beacon_url":"https:\\/\\/search.spotxchange.com\\/beacon?_a=137530&_p=spotx&_z=1&_m=eNpFizsOwjAQBfdEaBd7HbugIFKgiY0QThF3mI9CTPoQcXbAgYIpRho9PblABABiRNZkSEM0WksjT%2BqsNdGliAIVxXi8klKISECiYIHQHGA%2B5lgyvL6Aa%2Br6J4J3BljhKIhz%2FqdZTzeVXfAVu6EVdtok65MIvry1fZdCvx9323C3fv2wQ7X6ANPiL68%3D&_l=eNpljl1rwjAUhs9vya1DTpomTYXdDMcQtKWgSHtTYsycH02rTZnV%2Bd%2FXKhuMnYv34nmfFw6VVPqSQRAKTzAfOEgPJfgcAwFAAaGuSneGwQAEDcGW1nTsShgZXclquyYjgkNEJsgTqVRbNu6HYI%2FqythfJ7xLzeqw1bk56w9lNyZ%2FN%2BbeU0Tsat2clDPrvFCnvXHVQWnz38Xevd0gWkynj0DAoeTQHfZ%2Fog%2FHRlmnVe0eAmUB9%2FjfBXzNdulntNvQeP6K2Vu2j8cvRVSkl6yYtelywuJxwrJl0sbz5PkbhgZPGQ%3D%3D&_t=eNpdUNuK2zAQ9bfoOXHktLnUsJSUdEtg66U0y7IhIGRpHKvVrZKcJpvuv3ccBwrVy2jOzJlzZmrgwtnsQ0MXnC7kXC6XRQGL%2Bh1dFHXNm2I%2Bp5QWmWi5spkLB26VyOqBdSHDh6WzB1IS4YzXkICMiNf8nJTp0WKO%2BVFJcOzItZKsUSEm1gQ%2BlLHKJYvnmMCQ8kJCqvsgtAKbWEQiKemIdBECdlnBuqCR16bkY7mf7CdenUDnvzpuE%2FYcIUcfNxTDeLx6Xn2S0%2FZ7e39v8oNqPippeBLtHUXpBgDFXRdEb0armJQ9IP5P5KrRxfFviCmP3qVTjhb%2F0yuXdEn3k2sZ2VG0cN3OebDYzaZsSt7esAA8iJZFD6Jf0vP%2BCglC7DMJR9XbuBA4pT5cx7EBZtz726FtpzXOMk6CHrIRcfGG48uyIqc0q54eHrI%2F1fOGvmzFbGcqszOb8%2B7Hz%2FfVl11bbVevX9eb2eP62%2FRx%2FXlWbTd3fwGJWrJT&_b=eNozZPAL9fFBI2ois8Iy%2FN2DcvyqPCsjq7KN%2FKqSjaNy3TKjXMIy%2FLKyTfyyXMsjszyNfLN8bQGSHxTj&beacon_type=complete"},{"type":"impression","beacon_url":"https:\\/\\/search.spotxchange.com\\/beacon?_a=137530&_p=spotx&_z=1&_m=eNpVz99vgjAQB%2FD%2BLTyP0rM%2FLCZ7WOKWbFF5GJr4RAotUBUwgkHZ9rdvVB8W%2B3BJv3eXT45hQhBCwAnhEkKQKA2lZCHLhJYSwExTSgSkqcpBCEIIIKBTTglaf6JQ4glleAISAxOo7LpjOwuCvu9xrip7uJaq1tdK1ThrqgB9eefWnJLibLU385hRoTQ8FylPnSNzMgUtc6EpdY73dB%2B3bVKbflwYg6xp9tYkuqmUrceoNeqUlbg9Nt0lG7HCOGkcVGdtTZ2Z5IHyneU7zHea%2F8D93A6bcPR7e2i1XizuBW4R4oJcKPDx%2B99y5TuKD%2BU23rPlrhiW849dFG%2FstnqrVsPLJYrfYTm88mi%2BZ6uheP4DQppvcA%3D%3D&_l=eNplj01rwkAYhN%2FfsleLvJv9yEbooUXoxU1BDKW5yGazNUk1SZMNtVr%2Fe9VgofQyh5mHGYYqqrhiEEYykIyDABWgAi4wlAAUKKdcRIpD3zZ%2BD5MJSBpB3dQOEI6EkdmRZGVOZgSniEySO9Kar2bwNwcvVt%2B6%2BpeJrtCQbUu7dntbmHrj1m%2FOXXOKiOfYDp3xLl%2FvTPfufLs11v1n8cKeThAni8UoCDhVAparR%2FDdsGuLxrttP7XNDlBxRjORW5pxhRYjIYULc8nDyDLm8vH3%2BRxy%2BBhM7a3p%2FdhKWSgC8XcGvuNK8%2FQp2b%2BuiiKdb1AfNNfVw6eukkBXcfk8T4L0ZVnqQ3L%2FAyjAYKo%3D&_t=eNpdkVGP4iAQx%2FtZeNYKrWkVs7l42fim%2B3Cb22hMCKW0xWsLB9S15%2Fndd9qaXHK8DPzm%2F58ZIJNc6DZYFzjlOM2TfLUiRKZZjFOSZbwgSYIxJoGouGoDbUveKhFkk%2BuOpg3zvZGIIue59WiGTM17r5oBkQTOV5VLza68VjkrlHWeFZZPacjynLneedkgekfWZ0MQtZKtZw6MiOIZ6py0oGoF62wNvsp74%2Bh5cV4YdZN1%2BLvjrQfNVYZCN08KYT7ffmy%2F51H1o9rtmrBUxTeVN9yL6gVD60JKaK47K4ZhauW8akvg%2F5qMPTo3%2F5TOh85ofwthxP%2F60RVe4fNiTIPbiUqOt9NGtqBmEYvQ4wEJya2omDNSDJc0fHgFL60bTrm8qmGMO5I3P4SxHJsw48Y8X5lAoUbnEiaMZkiDN3rACgISYhxwmtK7owlFZa0zXqONongzAqPhf0ZA1iQCFlOkGj6AeJmmeAloSZFQvn%2BKyGS0slS6HVhC1oBSEOmu9XbURVE81cqnWklENo%2Fg7%2BlSxoePn5dTc%2BwP7%2FvPw%2BVQnS7H%2Fu11V%2B%2BbIzm9%2F%2Frz9rqN95f9yxciMdN%2F&_b=eNozYPAL9fFBI2r8qiINfbNCDSOr%2FHJ8s7IrI41CTXyNIk0jQ5LLI7MCjf3cA6v8w8OyfXMDbQF9gxRO&beacon_type=start&aid=4ea98e5f-6b5b-11e7-8f07-1d8f6d330001&syn%5Btiming%5D=%24TIMING_DATA"},{"type":"click","beacon_url":"https:\\/\\/search.spotxchange.com\\/click?_a=137530&_p=spotx&_z=1&_m=eNpVz99vgjAQB%2FD%2BLTyP0rM%2FLCZ7WOKWbFF5GJr4RAotUBUwgkHZ9rdvVB8W%2B3BJv3eXT45hQhBCwAnhEkKQKA2lZCHLhJYSwExTSgSkqcpBCEIIIKBTTglaf6JQ4glleAISAxOo7LpjOwuCvu9xrip7uJaq1tdK1ThrqgB9eefWnJLibLU385hRoTQ8FylPnSNzMgUtc6EpdY73dB%2B3bVKbflwYg6xp9tYkuqmUrceoNeqUlbg9Nt0lG7HCOGkcVGdtTZ2Z5IHyneU7zHea%2F8D93A6bcPR7e2i1XizuBW4R4oJcKPDx%2B99y5TuKD%2BU23rPlrhiW849dFG%2FstnqrVsPLJYrfYTm88mi%2BZ6uheP4DQppvcA%3D%3D&_l=eNplj01rwkAYhN%2FfsleLvJv9yEbooUXoxU1BDKW5yGazNUk1SZMNtVr%2Fe9VgofQyh5mHGYYqqrhiEEYykIyDABWgAi4wlAAUKKdcRIpD3zZ%2BD5MJSBpB3dQOEI6EkdmRZGVOZgSniEySO9Kar2bwNwcvVt%2B6%2BpeJrtCQbUu7dntbmHrj1m%2FOXXOKiOfYDp3xLl%2FvTPfufLs11v1n8cKeThAni8UoCDhVAparR%2FDdsGuLxrttP7XNDlBxRjORW5pxhRYjIYULc8nDyDLm8vH3%2BRxy%2BBhM7a3p%2FdhKWSgC8XcGvuNK8%2FQp2b%2BuiiKdb1AfNNfVw6eukkBXcfk8T4L0ZVnqQ3L%2FAyjAYKo%3D&_t=eNotkFtv3CAQhf1beI5awBs7y6oPlaq%2BRdVKvchpK2sMrD2JMRaw9%2B5%2F77AOL8z5dM7MgB5RvxXrHa%2BB16YyT09C2LoreS26DnaiqjjnotAD4FT40MOEujigsb7V9%2BiVOWsQWjRMMfbAdj44SEudAkxRe4NTz9RvNvojwWzfOyoG7Af2lwA626bzbCkE80xdIaGf%2Fnx8hQNEHXBO5J5HOCdykklUeQ6ONuLFLpM6pFkpC07qiCYNVJc8q8HSoLyRfMwSYxtTsODafRiXdLQQ9NDG2WqmrmyGAM4mG2JWxh5Q21zZU8pXnH06tQtuaeH33cWNnuKNpZ7ygXnKyhudohAfOC9A1eoaVaVYP%2FoORrZBxTd3MPuYFiDWQhIrFUMHGZSruuYrQivFNKbzu0kswWB7%2BqfMKrEmVJPJ76cU7j4py6WXWXpVUmxuxb9GbmXzvZeN2x5fXj%2Bfnn99fXtx28dnt119%2B%2FLTNZembNyPC7FP%2FwHQgKlo&_b=eNozYGDwC%2FXxYbBMMzQyMrQ0MEuxsDA0TDVPMjYwN0xKSkwzNDNzAwKwqhrfkOzyyPCwXN9cV1PfXL8sX5eMXD%2F3wErfKk%2FTKBe%2FrMiQlIyokGRTPxdPWwBB6Ro5"},{"beacon_url":"https:\\/\\/exch.quantserve.com\\/pixel\\/p-e_yCqWnB93CQF.gif?media=ad&p=0.978&r=&rand=86985&labels=_qc.imp,_imp.adserver.rtb,_qc.vast,_imp.qccampaign.556888,_imp.flight.409580,_imp.lineitem.354317&rtbip=192.184.68.197&rtbdata2=EBYaHlRoZV9UcnVtcF9Pcmdhbml6YXRpb25fUTNfMjAxNyDY_iEojdAVMIuARToeaHR0cHM6Ly93d3cuZmFtaWx5aGFuZHltYW4uY29tWig3UE4yak9feUl0RDByaUhkN0t4dDN1SHlkZHIwcTNiZjY2OGgyQnd4dQlqrD-AAanX4-0PoAEBqAHxrsQDugEkNGVhOThlNWYtNmI1Yi0xMWU3LThmMDctMWQ4ZjZkMzMwMDAxwAGMkfcByAHQ7puN1ivaASBiOTg4NDk0YzZkODgxMWU3YjMwNjFiYmFmMTY2MDAwMeUBBjH5O-gBZJgC7P8YqAIGqAIFsAIIugIEwLhExcACAsgCANAC4Ojb04yY0-2ZAeACAA","type":"impression"},{"beacon_url":"https:\\/\\/exch.quantserve.com\\/pixel\\/p-e_yCqWnB93CQF.gif?media=ad&r=&rand=86985&labels=_qc.vast,_qc.event.start&rtbip=192.184.68.197&rtbdata2=EBYaHlRoZV9UcnVtcF9Pcmdhbml6YXRpb25fUTNfMjAxNyDY_iEojdAVMIuARToeaHR0cHM6Ly93d3cuZmFtaWx5aGFuZHltYW4uY29tWig3UE4yak9feUl0RDByaUhkN0t4dDN1SHlkZHIwcTNiZjY2OGgyQnd4dQlqrD-AAanX4-0PoAEBqAHxrsQDugEkNGVhOThlNWYtNmI1Yi0xMWU3LThmMDctMWQ4ZjZkMzMwMDAxwAGMkfcByAHQ7puN1ivaASBiOTg4NDk0YzZkODgxMWU3YjMwNjFiYmFmMTY2MDAwMeUBBjH5O-gBZJgC7P8YqAIGqAIFsAIIugIEwLhExcACAsgCANAC4Ojb04yY0-2ZAeACAA","type":"start"},{"beacon_url":"https:\\/\\/exch.quantserve.com\\/pixel\\/p-e_yCqWnB93CQF.gif?media=ad&r=&rand=86985&labels=_qc.vast,_qc.event.firstQuartile&rtbip=192.184.68.197&rtbdata2=EBYaHlRoZV9UcnVtcF9Pcmdhbml6YXRpb25fUTNfMjAxNyDY_iEojdAVMIuARToeaHR0cHM6Ly93d3cuZmFtaWx5aGFuZHltYW4uY29tWig3UE4yak9feUl0RDByaUhkN0t4dDN1SHlkZHIwcTNiZjY2OGgyQnd4dQlqrD-AAanX4-0PoAEBqAHxrsQDugEkNGVhOThlNWYtNmI1Yi0xMWU3LThmMDctMWQ4ZjZkMzMwMDAxwAGMkfcByAHQ7puN1ivaASBiOTg4NDk0YzZkODgxMWU3YjMwNjFiYmFmMTY2MDAwMeUBBjH5O-gBZJgC7P8YqAIGqAIFsAIIugIEwLhExcACAsgCANAC4Ojb04yY0-2ZAeACAA","type":"firstQuartile"},{"beacon_url":"https:\\/\\/exch.quantserve.com\\/pixel\\/p-e_yCqWnB93CQF.gif?media=ad&r=&rand=86985&labels=_qc.vast,_qc.event.midpoint&rtbip=192.184.68.197&rtbdata2=EBYaHlRoZV9UcnVtcF9Pcmdhbml6YXRpb25fUTNfMjAxNyDY_iEojdAVMIuARToeaHR0cHM6Ly93d3cuZmFtaWx5aGFuZHltYW4uY29tWig3UE4yak9feUl0RDByaUhkN0t4dDN1SHlkZHIwcTNiZjY2OGgyQnd4dQlqrD-AAanX4-0PoAEBqAHxrsQDugEkNGVhOThlNWYtNmI1Yi0xMWU3LThmMDctMWQ4ZjZkMzMwMDAxwAGMkfcByAHQ7puN1ivaASBiOTg4NDk0YzZkODgxMWU3YjMwNjFiYmFmMTY2MDAwMeUBBjH5O-gBZJgC7P8YqAIGqAIFsAIIugIEwLhExcACAsgCANAC4Ojb04yY0-2ZAeACAA","type":"midpoint"},{"beacon_url":"https:\\/\\/exch.quantserve.com\\/pixel\\/p-e_yCqWnB93CQF.gif?media=ad&r=&rand=86985&labels=_qc.vast,_qc.event.thirdQuartile&rtbip=192.184.68.197&rtbdata2=EBYaHlRoZV9UcnVtcF9Pcmdhbml6YXRpb25fUTNfMjAxNyDY_iEojdAVMIuARToeaHR0cHM6Ly93d3cuZmFtaWx5aGFuZHltYW4uY29tWig3UE4yak9feUl0RDByaUhkN0t4dDN1SHlkZHIwcTNiZjY2OGgyQnd4dQlqrD-AAanX4-0PoAEBqAHxrsQDugEkNGVhOThlNWYtNmI1Yi0xMWU3LThmMDctMWQ4ZjZkMzMwMDAxwAGMkfcByAHQ7puN1ivaASBiOTg4NDk0YzZkODgxMWU3YjMwNjFiYmFmMTY2MDAwMeUBBjH5O-gBZJgC7P8YqAIGqAIFsAIIugIEwLhExcACAsgCANAC4Ojb04yY0-2ZAeACAA","type":"thirdQuartile"},{"beacon_url":"https:\\/\\/exch.quantserve.com\\/pixel\\/p-e_yCqWnB93CQF.gif?media=ad&r=&rand=86985&labels=_qc.vast,_qc.event.complete&rtbip=192.184.68.197&rtbdata2=EBYaHlRoZV9UcnVtcF9Pcmdhbml6YXRpb25fUTNfMjAxNyDY_iEojdAVMIuARToeaHR0cHM6Ly93d3cuZmFtaWx5aGFuZHltYW4uY29tWig3UE4yak9feUl0RDByaUhkN0t4dDN1SHlkZHIwcTNiZjY2OGgyQnd4dQlqrD-AAanX4-0PoAEBqAHxrsQDugEkNGVhOThlNWYtNmI1Yi0xMWU3LThmMDctMWQ4ZjZkMzMwMDAxwAGMkfcByAHQ7puN1ivaASBiOTg4NDk0YzZkODgxMWU3YjMwNjFiYmFmMTY2MDAwMeUBBjH5O-gBZJgC7P8YqAIGqAIFsAIIugIEwLhExcACAsgCANAC4Ojb04yY0-2ZAeACAA","type":"complete"},{"beacon_url":"https:\\/\\/exch.quantserve.com\\/pixel\\/p-e_yCqWnB93CQF.gif?media=ad&r=&rand=86985&labels=_qc.vast,_qc.event.close&rtbip=192.184.68.197&rtbdata2=EBYaHlRoZV9UcnVtcF9Pcmdhbml6YXRpb25fUTNfMjAxNyDY_iEojdAVMIuARToeaHR0cHM6Ly93d3cuZmFtaWx5aGFuZHltYW4uY29tWig3UE4yak9feUl0RDByaUhkN0t4dDN1SHlkZHIwcTNiZjY2OGgyQnd4dQlqrD-AAanX4-0PoAEBqAHxrsQDugEkNGVhOThlNWYtNmI1Yi0xMWU3LThmMDctMWQ4ZjZkMzMwMDAxwAGMkfcByAHQ7puN1ivaASBiOTg4NDk0YzZkODgxMWU3YjMwNjFiYmFmMTY2MDAwMeUBBjH5O-gBZJgC7P8YqAIGqAIFsAIIugIEwLhExcACAsgCANAC4Ojb04yY0-2ZAeACAA","type":"close"},{"beacon_url":"https:\\/\\/exch.quantserve.com\\/pixel\\/p-e_yCqWnB93CQF.gif?media=ad&r=&rand=86985&labels=_qc.clk,_click.adserver.rtb,_qc.vast&rtbip=192.184.68.197&rtbdata2=EBYaHlRoZV9UcnVtcF9Pcmdhbml6YXRpb25fUTNfMjAxNyDY_iEojdAVMIuARToeaHR0cHM6Ly93d3cuZmFtaWx5aGFuZHltYW4uY29tWig3UE4yak9feUl0RDByaUhkN0t4dDN1SHlkZHIwcTNiZjY2OGgyQnd4dQlqrD-AAanX4-0PoAEBqAHxrsQDugEkNGVhOThlNWYtNmI1Yi0xMWU3LThmMDctMWQ4ZjZkMzMwMDAxwAGMkfcByAHQ7puN1ivaASBiOTg4NDk0YzZkODgxMWU3YjMwNjFiYmFmMTY2MDAwMeUBBjH5O-gBZJgC7P8YqAIGqAIFsAIIugIEwLhExcACAsgCANAC4Ojb04yY0-2ZAeACAA","type":"click"},{"type":"initialization","beacon_url":"https:\\/\\/pr-bh.ybp.yahoo.com\\/sync\\/spotx\\/4ea98e5f-6b5b-11e7-8f07-1d8f6d330001"},{"type":"initialization","beacon_url":"https:\\/\\/spotxbidder-east.extend.tv\\/r.gif"},{"type":"impression","beacon_url":"https:\\/\\/event.spotxchange.com\\/vast\\/impression?_x=WzE1MDA1ODE5MTgsImI5ODg0OTRjNmQ4ODExZTdiMzA2MWJiYWYxNjYwMDAxIiwiMTM3NTMwIiwic3BvdHgiLCI4MjA4IiwiMTQxNDU5ODQiLCIxMTMwNTA3IiwiNGVhOThlNWYtNmI1Yi0xMWU3LThmMDctMWQ4ZjZkMzMwMDAxIl0mc2V0ZWM9TkRCaFpUY3lPRFF6WVRSa016WTNOVFl3WWpZeFl6QmpZV1kxWkRkalpqYz0~","with_creds":false},{"type":"complete","beacon_url":"https:\\/\\/event.spotxchange.com\\/vast\\/complete?_x=WzE1MDA1ODE5MTgsImI5ODg0OTRjNmQ4ODExZTdiMzA2MWJiYWYxNjYwMDAxIiwiMTM3NTMwIiwic3BvdHgiLCI4MjA4IiwiMTQxNDU5ODQiLCIxMTMwNTA3Il0mc2V0ZWM9T0RNNU9UWmpNVE01Wm1RMU1URmhPVFU1Tm1FM016a3pPR1U1TURGbU9UVT0~","with_creds":false},{"type":"firstQuartile","beacon_url":"https:\\/\\/event.spotxchange.com\\/vast\\/25?_x=WzE1MDA1ODE5MTgsImI5ODg0OTRjNmQ4ODExZTdiMzA2MWJiYWYxNjYwMDAxIiwiMTM3NTMwIiwic3BvdHgiLCI4MjA4IiwiMTQxNDU5ODQiLCIxMTMwNTA3Il0mc2V0ZWM9T0RNNU9UWmpNVE01Wm1RMU1URmhPVFU1Tm1FM016a3pPR1U1TURGbU9UVT0~","with_creds":false},{"type":"midpoint","beacon_url":"https:\\/\\/event.spotxchange.com\\/vast\\/50?_x=WzE1MDA1ODE5MTgsImI5ODg0OTRjNmQ4ODExZTdiMzA2MWJiYWYxNjYwMDAxIiwiMTM3NTMwIiwic3BvdHgiLCI4MjA4IiwiMTQxNDU5ODQiLCIxMTMwNTA3Il0mc2V0ZWM9T0RNNU9UWmpNVE01Wm1RMU1URmhPVFU1Tm1FM016a3pPR1U1TURGbU9UVT0~","with_creds":false},{"type":"thirdQuartile","beacon_url":"https:\\/\\/event.spotxchange.com\\/vast\\/75?_x=WzE1MDA1ODE5MTgsImI5ODg0OTRjNmQ4ODExZTdiMzA2MWJiYWYxNjYwMDAxIiwiMTM3NTMwIiwic3BvdHgiLCI4MjA4IiwiMTQxNDU5ODQiLCIxMTMwNTA3Il0mc2V0ZWM9T0RNNU9UWmpNVE01Wm1RMU1URmhPVFU1Tm1FM016a3pPR1U1TURGbU9UVT0~","with_creds":false},{"type":"skip","beacon_url":"https:\\/\\/event.spotxchange.com\\/vast\\/skip?_x=WzE1MDA1ODE5MTgsImI5ODg0OTRjNmQ4ODExZTdiMzA2MWJiYWYxNjYwMDAxIiwiMTM3NTMwIiwic3BvdHgiLCI4MjA4IiwiMTQxNDU5ODQiLCIxMTMwNTA3Il0mc2V0ZWM9T0RNNU9UWmpNVE01Wm1RMU1URmhPVFU1Tm1FM016a3pPR1U1TURGbU9UVT0~","with_creds":false},{"type":"event","beacon_url":"https:\\/\\/event.spotxchange.com\\/event\\/d?_x=WzE1MDA1ODE5MTgsImI5ODg0OTRjNmQ4ODExZTdiMzA2MWJiYWYxNjYwMDAxIiwiMTM3NTMwIiwic3BvdHgiLCI4MjA4IiwiMTQxNDU5ODQiLCIxMTMwNTA3Il0mc2V0ZWM9T0RNNU9UWmpNVE01Wm1RMU1URmhPVFU1Tm1FM016a3pPR1U1TURGbU9UVT0~&es=$EVENT_SOURCE&ts=$TS&eid=$EVENT_ID","with_creds":false},{"type":"initialization","beacon_url":"https:\\/\\/sb.scorecardresearch.com\\/b?c1=1&c2=6272977&c3=137530&cv=1.3&cj=1"},{"type":"click","beacon_url":""}]},"video":[{"playtime":16,"vpi":"VPAID_JS","transcoding":["low","medium","high"],"maintain_aspect_ratio":"","height":"250","source_uri":"https:\\/\\/svastx.moatads.com\\/quantcastvpaid04786010\\/moatwrapper.js#vast=https%3a%2f%2ffw.adsafeprotected.com%2fvast%2ffwjsvid%2fst%2f97316%2f16816497%2fskeleton.js%3fincludeFlash%3dfalse%26originalVast%3dhttps%3a%2f%2fad.doubleclick.net%2fddm%2fpfadx%2fN3727.Quantcast%2fB10712985.201400089%3bsz%3d0x0%3bord%3d489477956%3bdc_lat%3d%3bdc_rdid%3d%3btag_for_child_directed_treatment%3d%3bdcmt%3dtext%2fxml&level1=undefined&level2=undefined&level3=undefined&level4=undefined&slicer1=undefined&slicer2=undefined&pcode=quantcastvpaid04786010&spvb=1&zMoatAccount=p-e_yCqWnB93CQF&zMoatCreate=1130507&zMoatuid=b988494c6d8811e7b3061bbaf1660001&zMoatCamp=556888&zMoatLine=354317","bitrate":0,"width":"300","mime_type":"application\\/javascript","source_uri_external":true,"api_framework":"VPAID","media_id":"","scalable":"","page_url":null,"media_url":"https:\\/\\/svastx.moatads.com\\/quantcastvpaid04786010\\/moatwrapper.js#vast=https%3a%2f%2ffw.adsafeprotected.com%2fvast%2ffwjsvid%2fst%2f97316%2f16816497%2fskeleton.js%3fincludeFlash%3dfalse%26originalVast%3dhttps%3a%2f%2fad.doubleclick.net%2fddm%2fpfadx%2fN3727.Quantcast%2fB10712985.201400089%3bsz%3d0x0%3bord%3d489477956%3bdc_lat%3d%3bdc_rdid%3d%3btag_for_child_directed_treatment%3d%3bdcmt%3dtext%2fxml&level1=undefined&level2=undefined&level3=undefined&level4=undefined&slicer1=undefined&slicer2=undefined&pcode=quantcastvpaid04786010&spvb=1&zMoatAccount=p-e_yCqWnB93CQF&zMoatCreate=1130507&zMoatuid=b988494c6d8811e7b3061bbaf1660001&zMoatCamp=556888&zMoatLine=354317"},{"playtime":16,"vpi":"VPAID_JS","transcoding":["low","medium","high"],"maintain_aspect_ratio":"","height":"250","source_uri":"https:\\/\\/svastx.moatads.com\\/quantcastvpaid04786010\\/moatwrapper.js#vast=https%3a%2f%2ffw.adsafeprotected.com%2fvast%2ffwjsvid%2fst%2f97316%2f16816497%2fskeleton.js%3fincludeFlash%3dfalse%26originalVast%3dhttps%3a%2f%2fad.doubleclick.net%2fddm%2fpfadx%2fN3727.Quantcast%2fB10712985.201400089%3bsz%3d0x0%3bord%3d489477956%3bdc_lat%3d%3bdc_rdid%3d%3btag_for_child_directed_treatment%3d%3bdcmt%3dtext%2fxml&level1=undefined&level2=undefined&level3=undefined&level4=undefined&slicer1=undefined&slicer2=undefined&pcode=quantcastvpaid04786010&spvb=1&zMoatAccount=p-e_yCqWnB93CQF&zMoatCreate=1130507&zMoatuid=b988494c6d8811e7b3061bbaf1660001&zMoatCamp=556888&zMoatLine=354317","bitrate":0,"width":"300","mime_type":"application\\/javascript","source_uri_external":true,"api_framework":"VPAID","media_id":"","scalable":"","media_url":"https:\\/\\/svastx.moatads.com\\/quantcastvpaid04786010\\/moatwrapper.js#vast=https%3a%2f%2ffw.adsafeprotected.com%2fvast%2ffwjsvid%2fst%2f97316%2f16816497%2fskeleton.js%3fincludeFlash%3dfalse%26originalVast%3dhttps%3a%2f%2fad.doubleclick.net%2fddm%2fpfadx%2fN3727.Quantcast%2fB10712985.201400089%3bsz%3d0x0%3bord%3d489477956%3bdc_lat%3d%3bdc_rdid%3d%3btag_for_child_directed_treatment%3d%3bdcmt%3dtext%2fxml&level1=undefined&level2=undefined&level3=undefined&level4=undefined&slicer1=undefined&slicer2=undefined&pcode=quantcastvpaid04786010&spvb=1&zMoatAccount=p-e_yCqWnB93CQF&zMoatCreate=1130507&zMoatuid=b988494c6d8811e7b3061bbaf1660001&zMoatCamp=556888&zMoatLine=354317"},{"playtime":16,"vpi":"VPAID_JS","transcoding":["low","medium","high"],"maintain_aspect_ratio":"","height":"250","source_uri":"https:\\/\\/svastx.moatads.com\\/quantcastvpaid04786010\\/moatwrapper.js#vast=https%3a%2f%2ffw.adsafeprotected.com%2fvast%2ffwjsvid%2fst%2f97316%2f16816497%2fskeleton.js%3fincludeFlash%3dfalse%26originalVast%3dhttps%3a%2f%2fad.doubleclick.net%2fddm%2fpfadx%2fN3727.Quantcast%2fB10712985.201400089%3bsz%3d0x0%3bord%3d489477956%3bdc_lat%3d%3bdc_rdid%3d%3btag_for_child_directed_treatment%3d%3bdcmt%3dtext%2fxml&level1=undefined&level2=undefined&level3=undefined&level4=undefined&slicer1=undefined&slicer2=undefined&pcode=quantcastvpaid04786010&spvb=1&zMoatAccount=p-e_yCqWnB93CQF&zMoatCreate=1130507&zMoatuid=b988494c6d8811e7b3061bbaf1660001&zMoatCamp=556888&zMoatLine=354317","bitrate":0,"width":"300","mime_type":"application\\/javascript","source_uri_external":true,"api_framework":"VPAID","media_id":"","scalable":"","media_url":"https:\\/\\/svastx.moatads.com\\/quantcastvpaid04786010\\/moatwrapper.js#vast=https%3a%2f%2ffw.adsafeprotected.com%2fvast%2ffwjsvid%2fst%2f97316%2f16816497%2fskeleton.js%3fincludeFlash%3dfalse%26originalVast%3dhttps%3a%2f%2fad.doubleclick.net%2fddm%2fpfadx%2fN3727.Quantcast%2fB10712985.201400089%3bsz%3d0x0%3bord%3d489477956%3bdc_lat%3d%3bdc_rdid%3d%3btag_for_child_directed_treatment%3d%3bdcmt%3dtext%2fxml&level1=undefined&level2=undefined&level3=undefined&level4=undefined&slicer1=undefined&slicer2=undefined&pcode=quantcastvpaid04786010&spvb=1&zMoatAccount=p-e_yCqWnB93CQF&zMoatCreate=1130507&zMoatuid=b988494c6d8811e7b3061bbaf1660001&zMoatCamp=556888&zMoatLine=354317"}],"banners":{"medium_rectangle":{"banner_type":"auto","mime_type":"image\\/gif","iab_imu":"medium_rectangle","width":300,"height":250,"page_url":"https:\\/\\/search.spotxchange.com\\/click?_a=137530&_p=spotx&_z=1&_m=eNpVz99vgjAQB%2FD%2BLTyP0rM%2FLCZ7WOKWbFF5GJr4RAotUBUwgkHZ9rdvVB8W%2B3BJv3eXT45hQhBCwAnhEkKQKA2lZCHLhJYSwExTSgSkqcpBCEIIIKBTTglaf6JQ4glleAISAxOo7LpjOwuCvu9xrip7uJaq1tdK1ThrqgB9eefWnJLibLU385hRoTQ8FylPnSNzMgUtc6EpdY73dB%2B3bVKbflwYg6xp9tYkuqmUrceoNeqUlbg9Nt0lG7HCOGkcVGdtTZ2Z5IHyneU7zHea%2F8D93A6bcPR7e2i1XizuBW4R4oJcKPDx%2B99y5TuKD%2BU23rPlrhiW849dFG%2FstnqrVsPLJYrfYTm88mi%2BZ6uheP4DQppvcA%3D%3D&_l=eNplj01rwkAYhN%2FfsleLvJv9yEbooUXoxU1BDKW5yGazNUk1SZMNtVr%2Fe9VgofQyh5mHGYYqqrhiEEYykIyDABWgAi4wlAAUKKdcRIpD3zZ%2BD5MJSBpB3dQOEI6EkdmRZGVOZgSniEySO9Kar2bwNwcvVt%2B6%2BpeJrtCQbUu7dntbmHrj1m%2FOXXOKiOfYDp3xLl%2FvTPfufLs11v1n8cKeThAni8UoCDhVAparR%2FDdsGuLxrttP7XNDlBxRjORW5pxhRYjIYULc8nDyDLm8vH3%2BRxy%2BBhM7a3p%2FdhKWSgC8XcGvuNK8%2FQp2b%2BuiiKdb1AfNNfVw6eukkBXcfk8T4L0ZVnqQ3L%2FAyjAYKo%3D&_t=eNotj0tv3CAUhf1bWEcJYMeOPeomqhplMVOp8iwcVUI87tgkYCzMNPPo%2FPeAHRZwz8c5l4s0Wn5k9QFXHFeqVE9PhEAlclwRIfiBlCXGmGRy4HrMnO%2F5qGUm%2BDiCZ3LJXpEFpTnTCjVIKSFKQRUhdfGYxx1ULQtVQ81LVVNAd%2BjgvOUhel9ef0VptQUWzhNEoi3v4e9Drw%2Fx4lOrMESYYxzVALofUoo%2BLjJYw6SzkwELY%2BIRai6Ytsco0kRHyzzIwMfepGdn4F4ObJ5AouaKJu65hQB%2BTkrBPy0hVXAK6ZgnF05sxYxP0%2FeE5BYHdgoMaugdcjFLb3FlGbnHOONN1VznpmxQb5zgBm10gzcLmNwcVkBqQiPLl98mkBdVhYuIigZJHc7fJrIGPfTajYmVpI6oiiZ3HINffJTmay%2B19iop2dyy%2F93lj%2Bnandm1%2B3P3PrzvXl4%2Fu8v2tG3fzNbuL7tW6a59Hn7%2F3P%2F4Ap5ioKM%3D&_b=eNozYMgoKSkottLXLy7IL6lIzkjMS0%2FVS87PZfAL9fFhsEwzsLQ0NzQ0S7GwMDRMNU8yNjA3TEpKTDM0M3MDArCqmih3V5PIrGxDX5d0g8gqr0x%2Fl0hDfxe3bN8sTwO%2FrLDMyKycDD8XEJ1uCwCmYiLM","media_id":"ddbb6b2d119453119ed9c4d9e9a6d92e","filesize":420,"type":"image","format":"GIF","html_tag":"&lt;a href=&quot;https:\\/\\/search.spotxchange.com\\/click?_a=137530&_p=spotx&_z=1&_m=eNpVz99vgjAQB%2FD%2BLTyP0rM%2FLCZ7WOKWbFF5GJr4RAotUBUwgkHZ9rdvVB8W%2B3BJv3eXT45hQhBCwAnhEkKQKA2lZCHLhJYSwExTSgSkqcpBCEIIIKBTTglaf6JQ4glleAISAxOo7LpjOwuCvu9xrip7uJaq1tdK1ThrqgB9eefWnJLibLU385hRoTQ8FylPnSNzMgUtc6EpdY73dB%2B3bVKbflwYg6xp9tYkuqmUrceoNeqUlbg9Nt0lG7HCOGkcVGdtTZ2Z5IHyneU7zHea%2F8D93A6bcPR7e2i1XizuBW4R4oJcKPDx%2B99y5TuKD%2BU23rPlrhiW849dFG%2FstnqrVsPLJYrfYTm88mi%2BZ6uheP4DQppvcA%3D%3D&_l=eNplj01rwkAYhN%2FfsleLvJv9yEbooUXoxU1BDKW5yGazNUk1SZMNtVr%2Fe9VgofQyh5mHGYYqqrhiEEYykIyDABWgAi4wlAAUKKdcRIpD3zZ%2BD5MJSBpB3dQOEI6EkdmRZGVOZgSniEySO9Kar2bwNwcvVt%2B6%2BpeJrtCQbUu7dntbmHrj1m%2FOXXOKiOfYDp3xLl%2FvTPfufLs11v1n8cKeThAni8UoCDhVAparR%2FDdsGuLxrttP7XNDlBxRjORW5pxhRYjIYULc8nDyDLm8vH3%2BRxy%2BBhM7a3p%2FdhKWSgC8XcGvuNK8%2FQp2b%2BuiiKdb1AfNNfVw6eukkBXcfk8T4L0ZVnqQ3L%2FAyjAYKo%3D&_t=eNotj0tv3CAUhf1bWEcJYMeOPeomqhplMVOp8iwcVUI87tgkYCzMNPPo%2FPeAHRZwz8c5l4s0Wn5k9QFXHFeqVE9PhEAlclwRIfiBlCXGmGRy4HrMnO%2F5qGUm%2BDiCZ3LJXpEFpTnTCjVIKSFKQRUhdfGYxx1ULQtVQ81LVVNAd%2BjgvOUhel9ef0VptQUWzhNEoi3v4e9Drw%2Fx4lOrMESYYxzVALofUoo%2BLjJYw6SzkwELY%2BIRai6Ytsco0kRHyzzIwMfepGdn4F4ObJ5AouaKJu65hQB%2BTkrBPy0hVXAK6ZgnF05sxYxP0%2FeE5BYHdgoMaugdcjFLb3FlGbnHOONN1VznpmxQb5zgBm10gzcLmNwcVkBqQiPLl98mkBdVhYuIigZJHc7fJrIGPfTajYmVpI6oiiZ3HINffJTmay%2B19iop2dyy%2F93lj%2Bnandm1%2B3P3PrzvXl4%2Fu8v2tG3fzNbuL7tW6a59Hn7%2F3P%2F4Ap5ioKM%3D&_b=eNozYMgoKSkottLXLy7IL6lIzkjMS0%2FVS87PZfAL9fFhsEwzsLQ0NzQ0S7GwMDRMNU8yNjA3TEpKTDM0M3MDArCqmih3V5PIrGxDX5d0g8gqr0x%2Fl0hDfxe3bN8sTwO%2FrLDMyKycDD8XEJ1uCwCmYiLM&quot; border=&quot;0&quot; target=&quot;_blank&quot; title=&quot;IntegralAds_VAST_2_0_Ad_Wrapper&quot;&gt;&lt;img style=&quot;border:0; width:300px; height:250px;&quot; src=&quot;https:\\/\\/search.spotxchange.com\\/banner?_a=137530&_p=spotx&_z=1&_m=eNpVz99vgjAQB%2FD%2BLTyP0rM%2FLCZ7WOKWbFF5GJr4RAotUBUwgkHZ9rdvVB8W%2B3BJv3eXT45hQhBCwAnhEkKQKA2lZCHLhJYSwExTSgSkqcpBCEIIIKBTTglaf6JQ4glleAISAxOo7LpjOwuCvu9xrip7uJaq1tdK1ThrqgB9eefWnJLibLU385hRoTQ8FylPnSNzMgUtc6EpdY73dB%2B3bVKbflwYg6xp9tYkuqmUrceoNeqUlbg9Nt0lG7HCOGkcVGdtTZ2Z5IHyneU7zHea%2F8D93A6bcPR7e2i1XizuBW4R4oJcKPDx%2B99y5TuKD%2BU23rPlrhiW849dFG%2FstnqrVsPLJYrfYTm88mi%2BZ6uheP4DQppvcA%3D%3D&_l=eNplj01rwkAYhN%2FfsleLvJv9yEbooUXoxU1BDKW5yGazNUk1SZMNtVr%2Fe9VgofQyh5mHGYYqqrhiEEYykIyDABWgAi4wlAAUKKdcRIpD3zZ%2BD5MJSBpB3dQOEI6EkdmRZGVOZgSniEySO9Kar2bwNwcvVt%2B6%2BpeJrtCQbUu7dntbmHrj1m%2FOXXOKiOfYDp3xLl%2FvTPfufLs11v1n8cKeThAni8UoCDhVAparR%2FDdsGuLxrttP7XNDlBxRjORW5pxhRYjIYULc8nDyDLm8vH3%2BRxy%2BBhM7a3p%2FdhKWSgC8XcGvuNK8%2FQp2b%2BuiiKdb1AfNNfVw6eukkBXcfk8T4L0ZVnqQ3L%2FAyjAYKo%3D&_t=eNotj9Fu4yAQRf0tPFdbwK5dE%2B1b1aiVnGpXlVaJKlkDTGxaYyxMtsmm%2BfeFuDzA3MO9wyBhHNFn9Z5WQCtd6vt7xrCSOa2YlLBnZUkpZZnqwYyZ8x2MRmVySZ2JRW2gNZoIorWUpeSasbq4y%2BOOulaFrrGGUtccyQ3ZO28hRO%2F66TFKayy24TRhJMZCh2%2B3ndnHi0%2BjQx9hTmlUPZquTyl%2Bd5XBDq1ydhrQ4ph4hAZka%2BwhijTRwbYeVYCxG9KzM4JXfTtPqIg4kwk8WAzo56Q0%2FjUKU4XHkI55cuHYLriFafqekF3iwE7jQAS%2FIS5m%2BSWuLGM%2FKM1AVOI8i1KQbnASBrIygq6uYHJzWACrGY8sv%2F42gbyoKlpEVAiiTDh9m9gS9NgZNyZWsjqiKprcYQz%2B6uM8X3rppVfJ2eqSfW3Wv05b%2Fvy%2Be2j4br352NqN3f55Ys2%2Fj8%2FNQ3d8WTfHhv8eXl6bn%2F8BtbOdiA%3D%3D&_b=eNpFxl0LgjAUgGF%2FkSc%2FEhZ0EUje6AFFibxznuXmsklbGNKPL6%2FihYd350nnZnsA6Onh29m49za9mWASpDpw8jVxC%2BapBqAt4jzhIQUBi%2FfRT0Gsj4kJ1iXEQuEP6uZhk%2Bd%2FPsVaKUxPK6Z3haOO26xZ2gvKoi6Xa30eMas0rmWEtT5%2BAZ5CLzA%3D&quot; alt=&quot;IntegralAds_VAST_2_0_Ad_Wrapper&quot; \\/&gt;&lt;\\/a&gt;","source_uri":null,"html_source":null,"iframe_source":null,"banner_url":"https:\\/\\/search.spotxchange.com\\/banner?_a=137530&_p=spotx&_z=1&_m=eNpVz99vgjAQB%2FD%2BLTyP0rM%2FLCZ7WOKWbFF5GJr4RAotUBUwgkHZ9rdvVB8W%2B3BJv3eXT45hQhBCwAnhEkKQKA2lZCHLhJYSwExTSgSkqcpBCEIIIKBTTglaf6JQ4glleAISAxOo7LpjOwuCvu9xrip7uJaq1tdK1ThrqgB9eefWnJLibLU385hRoTQ8FylPnSNzMgUtc6EpdY73dB%2B3bVKbflwYg6xp9tYkuqmUrceoNeqUlbg9Nt0lG7HCOGkcVGdtTZ2Z5IHyneU7zHea%2F8D93A6bcPR7e2i1XizuBW4R4oJcKPDx%2B99y5TuKD%2BU23rPlrhiW849dFG%2FstnqrVsPLJYrfYTm88mi%2BZ6uheP4DQppvcA%3D%3D&_l=eNplj01rwkAYhN%2FfsleLvJv9yEbooUXoxU1BDKW5yGazNUk1SZMNtVr%2Fe9VgofQyh5mHGYYqqrhiEEYykIyDABWgAi4wlAAUKKdcRIpD3zZ%2BD5MJSBpB3dQOEI6EkdmRZGVOZgSniEySO9Kar2bwNwcvVt%2B6%2BpeJrtCQbUu7dntbmHrj1m%2FOXXOKiOfYDp3xLl%2FvTPfufLs11v1n8cKeThAni8UoCDhVAparR%2FDdsGuLxrttP7XNDlBxRjORW5pxhRYjIYULc8nDyDLm8vH3%2BRxy%2BBhM7a3p%2FdhKWSgC8XcGvuNK8%2FQp2b%2BuiiKdb1AfNNfVw6eukkBXcfk8T4L0ZVnqQ3L%2FAyjAYKo%3D&_t=eNotj9Fu4yAQRf0tPFdbwK5dE%2B1b1aiVnGpXlVaJKlkDTGxaYyxMtsmm%2BfeFuDzA3MO9wyBhHNFn9Z5WQCtd6vt7xrCSOa2YlLBnZUkpZZnqwYyZ8x2MRmVySZ2JRW2gNZoIorWUpeSasbq4y%2BOOulaFrrGGUtccyQ3ZO28hRO%2F66TFKayy24TRhJMZCh2%2B3ndnHi0%2BjQx9hTmlUPZquTyl%2Bd5XBDq1ydhrQ4ph4hAZka%2BwhijTRwbYeVYCxG9KzM4JXfTtPqIg4kwk8WAzo56Q0%2FjUKU4XHkI55cuHYLriFafqekF3iwE7jQAS%2FIS5m%2BSWuLGM%2FKM1AVOI8i1KQbnASBrIygq6uYHJzWACrGY8sv%2F42gbyoKlpEVAiiTDh9m9gS9NgZNyZWsjqiKprcYQz%2B6uM8X3rppVfJ2eqSfW3Wv05b%2Fvy%2Be2j4br352NqN3f55Ys2%2Fj8%2FNQ3d8WTfHhv8eXl6bn%2F8BtbOdiA%3D%3D&_b=eNpFxl0LgjAUgGF%2FkSc%2FEhZ0EUje6AFFibxznuXmsklbGNKPL6%2FihYd350nnZnsA6Onh29m49za9mWASpDpw8jVxC%2BapBqAt4jzhIQUBi%2FfRT0Gsj4kJ1iXEQuEP6uZhk%2Bd%2FPsVaKUxPK6Z3haOO26xZ2gvKoi6Xa30eMas0rmWEtT5%2BAZ5CLzA%3D","html_banner_url":"https:\\/\\/search.spotxchange.com\\/banner?_a=137530&_p=spotx&_z=1&_m=eNpVz99vgjAQB%2FD%2BLTyP0rM%2FLCZ7WOKWbFF5GJr4RAotUBUwgkHZ9rdvVB8W%2B3BJv3eXT45hQhBCwAnhEkKQKA2lZCHLhJYSwExTSgSkqcpBCEIIIKBTTglaf6JQ4glleAISAxOo7LpjOwuCvu9xrip7uJaq1tdK1ThrqgB9eefWnJLibLU385hRoTQ8FylPnSNzMgUtc6EpdY73dB%2B3bVKbflwYg6xp9tYkuqmUrceoNeqUlbg9Nt0lG7HCOGkcVGdtTZ2Z5IHyneU7zHea%2F8D93A6bcPR7e2i1XizuBW4R4oJcKPDx%2B99y5TuKD%2BU23rPlrhiW849dFG%2FstnqrVsPLJYrfYTm88mi%2BZ6uheP4DQppvcA%3D%3D&_l=eNplj01rwkAYhN%2FfsleLvJv9yEbooUXoxU1BDKW5yGazNUk1SZMNtVr%2Fe9VgofQyh5mHGYYqqrhiEEYykIyDABWgAi4wlAAUKKdcRIpD3zZ%2BD5MJSBpB3dQOEI6EkdmRZGVOZgSniEySO9Kar2bwNwcvVt%2B6%2BpeJrtCQbUu7dntbmHrj1m%2FOXXOKiOfYDp3xLl%2FvTPfufLs11v1n8cKeThAni8UoCDhVAparR%2FDdsGuLxrttP7XNDlBxRjORW5pxhRYjIYULc8nDyDLm8vH3%2BRxy%2BBhM7a3p%2FdhKWSgC8XcGvuNK8%2FQp2b%2BuiiKdb1AfNNfVw6eukkBXcfk8T4L0ZVnqQ3L%2FAyjAYKo%3D&_t=eNotj9Fu4yAQRf0tPFdbwK5dE%2B1b1aiVnGpXlVaJKlkDTGxaYyxMtsmm%2BfeFuDzA3MO9wyBhHNFn9Z5WQCtd6vt7xrCSOa2YlLBnZUkpZZnqwYyZ8x2MRmVySZ2JRW2gNZoIorWUpeSasbq4y%2BOOulaFrrGGUtccyQ3ZO28hRO%2F66TFKayy24TRhJMZCh2%2B3ndnHi0%2BjQx9hTmlUPZquTyl%2Bd5XBDq1ydhrQ4ph4hAZka%2BwhijTRwbYeVYCxG9KzM4JXfTtPqIg4kwk8WAzo56Q0%2FjUKU4XHkI55cuHYLriFafqekF3iwE7jQAS%2FIS5m%2BSWuLGM%2FKM1AVOI8i1KQbnASBrIygq6uYHJzWACrGY8sv%2F42gbyoKlpEVAiiTDh9m9gS9NgZNyZWsjqiKprcYQz%2B6uM8X3rppVfJ2eqSfW3Wv05b%2Fvy%2Be2j4br352NqN3f55Ys2%2Fj8%2FNQ3d8WTfHhv8eXl6bn%2F8BtbOdiA%3D%3D&_b=eNozYEjRB8KUpCSzJKMUQ0NLE1NjIJmaYplskmKZaplolmJplKqXUZKbw%2BAX6uODIGp83T0NI7MysiOzHCv8wj0rI3MDq3yNwnKAtEFkuKtBVDiQrvI1jqxKtwUAEJMfUw%3D%3D","html_tag_internal":true}},"ad_parameters":""},"ad_system":[],"referrer":"https:\\/\\/www.familyhandyman.com\\/","inventory_class":null,"safety":null,"client_playback":{"ados":{"client_side":{"feed_timeout":2000,"load_timeout":120000,"total_timeout":15000}},"ad_broker":{"idod_always_monetize":false,"idod_disable_max":false,"idod_max_count":5,"idod_detect":false,"idod_kill":false},"channel_name":"Familyhandyman.com TMBI","playback_conf":{"third_party_tracking":{"double_verify":true,"double_verify_noscript":false,"integral":false,"moat":true,"whiteops":false},"instream":[],"min_volume":"0","release_track":"beta"},"ad_unit":{"outstream":{"retry_timeout":10000,"retry_interval":850}},"publisher_name":"Trusted Media Brands, Inc","publisher_id":"137525","custom_skin":0},"skipit":{"enabled":1},"display":{"ad_marker":{"evidon":{"enabled":0}}},"third_party_tracking":{"providers":{"moat":{"id":"moat","parameters":{"level1":"137525","level2":"137530","level3":"8208","level4":"45076","slicer1":"www.familyhandyman.com","partnerCode":"spotxchangejsvideo759622536126","zMoatImpressionId":"9f07a07d6d8811e7b3071bbaf1660001","zMoatAD":["trumphotels.com"],"zMoatFD":null}},"double_verify":{"id":"double_verify","type":"impression","mime_type":"text\\/javascript","unique":"No","beacon_url":"https:\\/\\/cdn.doubleverify.com\\/dvtp_src.js?ctx=484047&cmp=2228897&sid=593588&plc=22288971&num=&adid=&advid=484048&adsrv=15&btreg=&btadsrv=&crt=&crtname=&chnl=&unit=&pid=&uid=&dvtagver=6.1.src&DVP_CHANNELID=137530&DVP_DEALID=spotx&DVP_CMPID=45076&turl=https:\\/\\/www.familyhandyman.com\\/&DVPX_SX_UID=4ea98e5f-6b5b-11e7-8f07-1d8f6d330001&DVPX_SX_MID=b988494c6d8811e7b3061bbaf1660001&DVPX_IP=98.234.218.146&DVPX_UA=Mozilla\\/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit\\/537.36 (KHTML, like Gecko) Chrome\\/59.0.3071.115 Safari\\/537.36","parameters":[]}}},"bundle_id":null,"channel_id":"137530"} -------------------------------------------------------------------------------- /testdata/spotx_html_resource.html: -------------------------------------------------------------------------------- 1 | IntegralAds_VAST_2_0_Ad_Wrapper -------------------------------------------------------------------------------- /testdata/vast4_universal_ad_id.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | iabtechlab 7 | http://example.com/error 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | http://example.com/track/impression 16 | 17 | 18 | 19 | iabtechlab video ad 20 | AD CONTENT description category 21 | 22 | 23 | 8465 24 | 25 | 26 | http://example.com/tracking/start 27 | http://example.com/tracking/firstQuartile 28 | http://example.com/tracking/midpoint 29 | http://example.com/tracking/thirdQuartile 30 | http://example.com/tracking/complete 31 | 32 | 00:00:16 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /testdata/vast_adaptv_attempt_attr.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Adap.tv 7 | 8 | 9 | 10 | &p.vw.viewableOpportunity=1&p.vw.viewableHistorical=61.49&p.vw.psize=3&a.sdk=o2unit&a.sdkType=js&pi.sdk=&pi.sdkType=&a.appReq=0&a.platformDevice=ONLINE_VIDEO&ipAddressOverride=98.234.218.146&a.platformOs=Mac+OS+X&p.vw.active=&a.rtbexch=&pi.sideview=&pi.flashonpage=&pi.mvoa=100&pi.avoa=&pi.sound=&pi.autoInitiation=&esVr=67.2897&esMvmr=61.4865&sadVr=67.2897&sadMvmr=61.4865&p.vw.geometric=&p.vw.framerate=&a.pub_id=&device_id_status=&a.ts=0&a.adSeq={adSeq}&isHttps=1&pubSettingId=5&eov=28963053&alephdEnabled=1&isFailoverAd=0&doubleAuction=&errorCode=%5BERRORCODE%5D]]> 11 | 12 | &f0=1&162=61.49&68=3&d7=o2unit&c0=js&c4=0&91=ONLINE_VIDEO&45=98.234.218.146&ee=Mac+OS+X&b5=&146=100&14c=67.2897&14d=61.4865&153=67.2897&154=61.4865&120=0&100={adSeq}&112=1&134=5&33=28963053&135=2&137=1&13d=0&14f=9zYHE4kOIKIZc1EDPjx1hw__&colo=NA&a.afv=-1&a.dfv=-2&168=}&16e=0a61ed6&16f=gayoncMgHis_&a.cv=1]]> 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | &p.vw.viewableOpportunity=1&p.vw.viewableHistorical=61.49&p.vw.psize=3&a.sdk=o2unit&a.sdkType=js&pi.sdk=&pi.sdkType=&a.appReq=0&a.platformDevice=ONLINE_VIDEO&ipAddressOverride=98.234.218.146&a.platformOs=Mac+OS+X&p.vw.active=&a.rtbexch=&pi.sideview=&pi.flashonpage=&pi.mvoa=100&pi.avoa=&pi.sound=&pi.autoInitiation=&esVr=67.2897&esMvmr=61.4865&sadVr=67.2897&sadMvmr=61.4865&p.vw.geometric=&p.vw.framerate=&a.pub_id=&device_id_status=&a.ts=0&a.adSeq={adSeq}&isHttps=1&pubSettingId=5&eov=28963053&doubleAuction=&nextSeatbid=&buyerSeatId=&isMatchedUser=]]> 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | &f0=1&162=61.49&68=3&d7=o2unit&c0=js&c4=0&91=ONLINE_VIDEO&45=98.234.218.146&ee=Mac+OS+X&b5=&146=100&14c=67.2897&14d=61.4865&153=67.2897&154=61.4865&120=0&100={adSeq}&112=1&134=5&33=28963053&a.cv=1]]> 45 | 46 | &f0=1&162=61.49&68=3&d7=o2unit&c0=js&c4=0&91=ONLINE_VIDEO&45=98.234.218.146&ee=Mac+OS+X&b5=&146=100&14c=67.2897&14d=61.4865&153=67.2897&154=61.4865&120=0&100={adSeq}&112=1&134=5&33=28963053&a.cv=1]]> 47 | 48 | &f0=1&162=61.49&68=3&d7=o2unit&c0=js&c4=0&91=ONLINE_VIDEO&45=98.234.218.146&ee=Mac+OS+X&b5=&146=100&14c=67.2897&14d=61.4865&153=67.2897&154=61.4865&120=0&100={adSeq}&112=1&134=5&33=28963053&a.cv=1]]> 49 | 50 | &f0=1&162=61.49&68=3&d7=o2unit&c0=js&c4=0&91=ONLINE_VIDEO&45=98.234.218.146&ee=Mac+OS+X&b5=&146=100&14c=67.2897&14d=61.4865&153=67.2897&154=61.4865&120=0&100={adSeq}&112=1&134=5&33=28963053&a.cv=1]]> 51 | 52 | &f0=1&162=61.49&68=3&d7=o2unit&c0=js&c4=0&91=ONLINE_VIDEO&45=98.234.218.146&ee=Mac+OS+X&b5=&146=100&14c=67.2897&14d=61.4865&153=67.2897&154=61.4865&120=0&100={adSeq}&112=1&134=5&33=28963053&91=ONLINE_VIDEO&f6=iCSArrpvL%2FM_&12e=-1.0000&12f=-1.0000&130=-1.0000&131=-1.0000&15c=-1&163=NFnJzCvmQNo7ZequqMcKyQ__&164=CNCzRkR4JL4_&a.cv=1]]> 53 | 54 | &p.vw.viewableOpportunity=1&p.vw.viewableHistorical=61.49&p.vw.psize=3&a.sdk=o2unit&a.sdkType=js&pi.sdk=&pi.sdkType=&a.appReq=0&a.platformDevice=ONLINE_VIDEO&ipAddressOverride=98.234.218.146&a.platformOs=Mac+OS+X&p.vw.active=&a.rtbexch=&pi.sideview=&pi.flashonpage=&pi.mvoa=100&pi.avoa=&pi.sound=&pi.autoInitiation=&esVr=67.2897&esMvmr=61.4865&sadVr=67.2897&sadMvmr=61.4865&p.vw.geometric=&p.vw.framerate=&a.pub_id=&device_id_status=&a.ts=0&a.adSeq={adSeq}&isHttps=1&pubSettingId=5&eov=28963053&doubleAuction=]]> 55 | 56 | &p.vw.viewableOpportunity=1&p.vw.viewableHistorical=61.49&p.vw.psize=3&a.sdk=o2unit&a.sdkType=js&pi.sdk=&pi.sdkType=&a.appReq=0&a.platformDevice=ONLINE_VIDEO&ipAddressOverride=98.234.218.146&a.platformOs=Mac+OS+X&p.vw.active=&a.rtbexch=&pi.sideview=&pi.flashonpage=&pi.mvoa=100&pi.avoa=&pi.sound=&pi.autoInitiation=&esVr=67.2897&esMvmr=61.4865&sadVr=67.2897&sadMvmr=61.4865&p.vw.geometric=&p.vw.framerate=&a.pub_id=&device_id_status=&a.ts=0&a.adSeq={adSeq}&isHttps=1&pubSettingId=5&eov=28963053]]> 57 | 58 | &p.vw.viewableOpportunity=1&p.vw.viewableHistorical=61.49&p.vw.psize=3&a.sdk=o2unit&a.sdkType=js&pi.sdk=&pi.sdkType=&a.appReq=0&a.platformDevice=ONLINE_VIDEO&ipAddressOverride=98.234.218.146&a.platformOs=Mac+OS+X&p.vw.active=&a.rtbexch=&pi.sideview=&pi.flashonpage=&pi.mvoa=100&pi.avoa=&pi.sound=&pi.autoInitiation=&esVr=67.2897&esMvmr=61.4865&sadVr=67.2897&sadMvmr=61.4865&p.vw.geometric=&p.vw.framerate=&a.pub_id=&device_id_status=&a.ts=0&a.adSeq={adSeq}&isHttps=1&pubSettingId=5&eov=28963053]]> 59 | 60 | &p.vw.viewableOpportunity=1&p.vw.viewableHistorical=61.49&p.vw.psize=3&a.sdk=o2unit&a.sdkType=js&pi.sdk=&pi.sdkType=&a.appReq=0&a.platformDevice=ONLINE_VIDEO&ipAddressOverride=98.234.218.146&a.platformOs=Mac+OS+X&p.vw.active=&a.rtbexch=&pi.sideview=&pi.flashonpage=&pi.mvoa=100&pi.avoa=&pi.sound=&pi.autoInitiation=&esVr=67.2897&esMvmr=61.4865&sadVr=67.2897&sadMvmr=61.4865&p.vw.geometric=&p.vw.framerate=&a.pub_id=&device_id_status=&a.ts=0&a.adSeq={adSeq}&isHttps=1&pubSettingId=5&eov=28963053]]> 61 | 62 | &p.vw.viewableOpportunity=1&p.vw.viewableHistorical=61.49&p.vw.psize=3&a.sdk=o2unit&a.sdkType=js&pi.sdk=&pi.sdkType=&a.appReq=0&a.platformDevice=ONLINE_VIDEO&ipAddressOverride=98.234.218.146&a.platformOs=Mac+OS+X&p.vw.active=&a.rtbexch=&pi.sideview=&pi.flashonpage=&pi.mvoa=100&pi.avoa=&pi.sound=&pi.autoInitiation=&esVr=67.2897&esMvmr=61.4865&sadVr=67.2897&sadMvmr=61.4865&p.vw.geometric=&p.vw.framerate=&a.pub_id=&device_id_status=&a.ts=0&a.adSeq={adSeq}&isHttps=1&pubSettingId=5&eov=28963053]]> 63 | 64 | &p.vw.viewableOpportunity=1&p.vw.viewableHistorical=61.49&p.vw.psize=3&a.sdk=o2unit&a.sdkType=js&pi.sdk=&pi.sdkType=&a.appReq=0&a.platformDevice=ONLINE_VIDEO&ipAddressOverride=98.234.218.146&a.platformOs=Mac+OS+X&p.vw.active=&a.rtbexch=&pi.sideview=&pi.flashonpage=&pi.mvoa=100&pi.avoa=&pi.sound=&pi.autoInitiation=&esVr=67.2897&esMvmr=61.4865&sadVr=67.2897&sadMvmr=61.4865&p.vw.geometric=&p.vw.framerate=&a.pub_id=&device_id_status=&a.ts=0&a.adSeq={adSeq}&isHttps=1&pubSettingId=5&eov=28963053]]> 65 | 66 | 67 | 68 | &f0=1&162=61.49&68=3&d7=o2unit&c0=js&c4=0&91=ONLINE_VIDEO&45=98.234.218.146&ee=Mac+OS+X&b5=&146=100&14c=67.2897&14d=61.4865&153=67.2897&154=61.4865&120=0&100={adSeq}&112=1&134=5&33=28963053&f6=iCSArrpvL%2FM_&12e=-1.0000&12f=-1.0000&130=-1.0000&131=-1.0000&15c=-1&163=NFnJzCvmQNo7ZequqMcKyQ__&164=CNCzRkR4JL4_&a.cv=1&rUrl=http%3A%2F%2Fwww.adap.tv]]> 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | &p.vw.viewableOpportunity=1&p.vw.viewableHistorical=61.49&p.vw.psize=3&a.sdk=o2unit&a.sdkType=js&pi.sdk=&pi.sdkType=&a.appReq=0&a.platformDevice=ONLINE_VIDEO&ipAddressOverride=98.234.218.146&a.platformOs=Mac+OS+X&p.vw.active=&a.rtbexch=&pi.sideview=&pi.flashonpage=&pi.mvoa=100&pi.avoa=&pi.sound=&pi.autoInitiation=&esVr=67.2897&esMvmr=61.4865&sadVr=67.2897&sadMvmr=61.4865&p.vw.geometric=&p.vw.framerate=&a.pub_id=&device_id_status=&a.ts=0&a.adSeq={adSeq}&isHttps=1&pubSettingId=5&eov=28963053]]> 141 | 142 | 143 | 144 | 145 | 146 | &p.vw.viewableOpportunity=1&p.vw.viewableHistorical=61.49&p.vw.psize=3&a.sdk=o2unit&a.sdkType=js&pi.sdk=&pi.sdkType=&a.appReq=0&a.platformDevice=ONLINE_VIDEO&ipAddressOverride=98.234.218.146&a.platformOs=Mac+OS+X&p.vw.active=&a.rtbexch=&pi.sideview=&pi.flashonpage=&pi.mvoa=100&pi.avoa=&pi.sound=&pi.autoInitiation=&esVr=67.2897&esMvmr=61.4865&sadVr=67.2897&sadMvmr=61.4865&p.vw.geometric=&p.vw.framerate=&a.pub_id=&device_id_status=&a.ts=0&a.adSeq={adSeq}&isHttps=1&pubSettingId=5&eov=28963053&doubleAuction=]]> 147 | 148 | &p.vw.viewableOpportunity=1&p.vw.viewableHistorical=61.49&p.vw.psize=3&a.sdk=o2unit&a.sdkType=js&pi.sdk=&pi.sdkType=&a.appReq=0&a.platformDevice=ONLINE_VIDEO&ipAddressOverride=98.234.218.146&a.platformOs=Mac+OS+X&p.vw.active=&a.rtbexch=&pi.sideview=&pi.flashonpage=&pi.mvoa=100&pi.avoa=&pi.sound=&pi.autoInitiation=&esVr=67.2897&esMvmr=61.4865&sadVr=67.2897&sadMvmr=61.4865&p.vw.geometric=&p.vw.framerate=&a.pub_id=&device_id_status=&a.ts=0&a.adSeq={adSeq}&isHttps=1&pubSettingId=5&eov=28963053&doubleAuction=]]> 149 | 150 | &p.vw.viewableOpportunity=1&p.vw.viewableHistorical=61.49&p.vw.psize=3&a.sdk=o2unit&a.sdkType=js&pi.sdk=&pi.sdkType=&a.appReq=0&a.platformDevice=ONLINE_VIDEO&ipAddressOverride=98.234.218.146&a.platformOs=Mac+OS+X&p.vw.active=&a.rtbexch=&pi.sideview=&pi.flashonpage=&pi.mvoa=100&pi.avoa=&pi.sound=&pi.autoInitiation=&esVr=67.2897&esMvmr=61.4865&sadVr=67.2897&sadMvmr=61.4865&p.vw.geometric=&p.vw.framerate=&a.pub_id=&device_id_status=&a.ts=0&a.adSeq={adSeq}&isHttps=1&pubSettingId=5&eov=28963053&doubleAuction=]]> 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /testdata/vast_inline_linear-duration_undefined.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Acudeo Compatible 6 | VAST 2.0 Instream Test 1 7 | 8 | 9 | 10 | undefined 11 | 12 | http://cdnp.tremormedia.com/video/acudeo/Carrot_400x300_500kb.flv 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /testdata/vast_inline_linear.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Acudeo Compatible 6 | VAST 2.0 Instream Test 1 7 | VAST 2.0 Instream Test 1 8 | http://myErrorURL/error 9 | http://myErrorURL/error2 10 | http://myTrackingURL/impression 11 | http://myTrackingURL/impression2 12 | 13 | 14 | 15 | 00:00:30 16 | 17 | http://myTrackingURL/creativeView 18 | http://myTrackingURL/start 19 | http://myTrackingURL/midpoint 20 | http://myTrackingURL/firstQuartile 21 | http://myTrackingURL/thirdQuartile 22 | http://myTrackingURL/complete 23 | 24 | 25 | http://www.tremormedia.com 26 | http://myTrackingURL/click 27 | 28 | 29 | http://cdnp.tremormedia.com/video/acudeo/Carrot_400x300_500kb.flv 30 | 31 | 32 | 33 | 34 | 35 | 36 | http://demo.tremormedia.com/proddev/vast/Blistex1.jpg 37 | 38 | http://myTrackingURL/firstCompanionCreativeView 39 | 40 | http://www.tremormedia.com 41 | 42 | 43 | http://demo.tremormedia.com/proddev/vast/728x90_banner1.jpg 44 | http://www.tremormedia.com 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /testdata/vast_inline_nonlinear.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Acudeo Compatible 6 | NonLinear Test Campaign 1 7 | NonLinear Test Campaign 1 8 | http://mySurveyURL/survey 9 | http://myErrorURL/error 10 | http://myTrackingURL/impression 11 | 12 | 13 | 14 | 15 | http://myTrackingURL/nonlinear/creativeView 16 | http://myTrackingURL/nonlinear/expand 17 | http://myTrackingURL/nonlinear/collapse 18 | http://myTrackingURL/nonlinear/acceptInvitation 19 | http://myTrackingURL/nonlinear/close 20 | 21 | 22 | 23 | http://demo.tremormedia.com/proddev/vast/50x300_static.jpg 24 | 25 | http://www.tremormedia.com 26 | 27 | 28 | 29 | http://demo.tremormedia.com/proddev/vast/50x450_static.jpg 30 | 31 | http://www.tremormedia.com 32 | 33 | 34 | 35 | 36 | 37 | 38 | http://demo.tremormedia.com/proddev/vast/300x250_companion_1.swf 39 | 40 | http://www.tremormedia.com 41 | 42 | 43 | http://demo.tremormedia.com/proddev/vast/728x90_banner1.jpg 44 | 45 | http://myTrackingURL/secondCompanion 46 | 47 | http://www.tremormedia.com 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /testdata/vast_wrapper_linear_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Acudeo Compatible 6 | http://demo.tremormedia.com/proddev/vast/vast_inline_linear.xml 7 | http://myErrorURL/wrapper/error 8 | http://myTrackingURL/wrapper/impression 9 | 10 | 11 | 12 | 13 | http://myTrackingURL/wrapper/creativeView 14 | http://myTrackingURL/wrapper/start 15 | http://myTrackingURL/wrapper/midpoint 16 | http://myTrackingURL/wrapper/firstQuartile 17 | http://myTrackingURL/wrapper/thirdQuartile 18 | http://myTrackingURL/wrapper/complete 19 | http://myTrackingURL/wrapper/mute 20 | http://myTrackingURL/wrapper/unmute 21 | http://myTrackingURL/wrapper/pause 22 | http://myTrackingURL/wrapper/resume 23 | http://myTrackingURL/wrapper/fullscreen 24 | 25 | 26 | 27 | 28 | 29 | 30 | http://myTrackingURL/wrapper/click 31 | 32 | 33 | 34 | 35 | 36 | 37 | http://myTrackingURL/wrapper/creativeView 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /testdata/vast_wrapper_linear_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Acudeo Compatible 6 | http://demo.tremormedia.com/proddev/vast/vast_inline_linear.xml 7 | http://myTrackingURL/wrapper/impression 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | http://demo.tremormedia.com/proddev/vast/300x250_banner1.jpg 19 | 20 | http://myTrackingURL/wrapper/firstCompanionCreativeView 21 | 22 | http://www.tremormedia.com 23 | 24 | 25 | http://demo.tremormedia.com/proddev/vast/728x90_banner1.jpg 26 | http://www.tremormedia.com 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /testdata/vast_wrapper_nonlinear_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Acudeo Compatible 6 | http://demo.tremormedia.com/proddev/vast/vast_inline_nonlinear2.xml 7 | http://myErrorURL/wrapper/error 8 | http://myTrackingURL/wrapper/impression 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | http://myTrackingURL/wrapper/nonlinear/creativeView/creativeView 20 | http://myTrackingURL/wrapper/nonlinear/creativeView/expand 21 | http://myTrackingURL/wrapper/nonlinear/creativeView/collapse 22 | http://myTrackingURL/wrapper/nonlinear/creativeView/acceptInvitation 23 | http://myTrackingURL/wrapper/nonlinear/creativeView/close 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /testdata/vast_wrapper_nonlinear_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Acudeo Compatible 6 | http://demo.tremormedia.com/proddev/vast/vast_inline_nonlinear3.xml 7 | http://myTrackingURL/wrapper/impression 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | http://demo.tremormedia.com/proddev/vast/300x250_banner1.jpg 25 | 26 | http://myTrackingURL/wrapper/firstCompanionCreativeView 27 | 28 | http://www.tremormedia.com 29 | 30 | 31 | http://demo.tremormedia.com/proddev/vast/728x90_banner1.jpg 32 | http://www.tremormedia.com 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /vast4.go: -------------------------------------------------------------------------------- 1 | package vast 2 | 3 | // The ad server may provide URIs for tracking publisher-determined view-ability 4 | type ViewableImpression struct { 5 | // An ad server id for the impression. 6 | // Viewable impression resources of the same id should be requested at the same time, 7 | // or as close in time as possible, to help prevent discrepancies. 8 | ID string `xml:"id,attr"` 9 | // The element is used to place a URI that the player triggers if and when 10 | // the ad meets criteria for a viewable video ad impression. 11 | Viewable []CDATAString `xml:"Viewable,omitempty"` 12 | // The element is a container for placing a URI that the player triggers 13 | // if the ad is executed but never meets criteria for a viewable video ad impression. 14 | NotViewable []CDATAString `xml:"NotViewable,omitempty"` 15 | // The element is a container for placing a URI that the player triggers 16 | // if it cannot determine whether the ad has met criteria for a viewable video ad impression. 17 | ViewUndetermined []CDATAString `xml:"ViewUndetermined,omitempty"` 18 | } 19 | 20 | // Providing an advertiser name can help publishers prevent display of the ad with its competitors. 21 | type Advertiser struct { 22 | // An (optional) identifier for the advertiser, provided by the ad server. Can be used for internal analytics. 23 | ID string `xml:"id,attr,omitempty"` 24 | // A string that provides the name of the advertiser as defined by the ad serving party. 25 | // Recommend using the domain of the advertiser. 26 | Advertiser string `xml:",chardata"` 27 | } 28 | 29 | type AdVerifications struct { 30 | Verification []Verification `xml:",omitempty"` 31 | } 32 | 33 | // The element contains the executable and bootstrapping data required to run the measurement code for a single verification vendor. 34 | // Multiple elements may be listed, in order to support multiple vendors, or if multiple API frameworks are supported. 35 | // At least one or should be provided. 36 | // At most one of these resources should selected for execution, as best matches the technology available in the current environment. 37 | type Verification struct { 38 | // An identifier for the verification vendor. The recommended format is [domain]- [useCase], 39 | // to avoid name collisions. For example, "company.com-omid". 40 | Vendor string `xml:"vendor,attr,omitempty"` 41 | // A container for the URI to the JavaScript file used to collect verification data. 42 | // Some verification vendors may provide JavaScript executables which work in non-browser environments, 43 | // for example, in an iOS app enabled by JavaScriptCore. These resources only require methods of the API framework, 44 | // without relying on any browser built-in functionality. 45 | JavaScriptResource []JavaScriptResource `xml:"JavaScriptResource,omitempty"` 46 | // A reference to a non-JavaScript or custom-integration resource intended for collecting verification data via the listed apiFramework. 47 | ExecutableResource []ExecutableResource `xml:"ExecutableResource,omitempty"` 48 | // The verification vendor may provide URIs for tracking events relating to the execution of their code during the ad session. 49 | TrackingEvents *TrackingEvents `xml:"TrackingEvents,omitempty"` 50 | // contains a CDATA-wrapped string intended for bootstrapping the verification code and providing metadata about the current impression. 51 | // The format of the string is up to the individual vendor and should be passed along verbatim. 52 | VerificationParameters *VerificationParameters `xml:",omitempty"` 53 | // ad categories are used in creative separation and for compliance in certain programs 54 | BlockedAdCategories []Category `xml:",omitempty"` 55 | } 56 | 57 | type VerificationParameters struct { 58 | // CDATA-wrapped metadata string for the verification executable 59 | URI string `xml:",cdata"` 60 | } 61 | 62 | // A container for the URI to the JavaScript file used to collect verification data. 63 | type JavaScriptResource struct { 64 | // Identifies the API needed to execute the resource file if applicable. 65 | ApiFramework string `xml:"apiFramework,attr,omitempty"` 66 | // If "true", this resource is optimized and able to execute in 67 | // an environment without DOM and other browser built-ins (e.g. iOS' JavaScriptCore). 68 | BrowserOptional bool `xml:"browserOptional,attr,omitempty"` 69 | // A CDATA-wrapped URI to a file providing Closed Caption info for the media file. 70 | URI string `xml:",cdata"` 71 | } 72 | 73 | type ExecutableResource struct { 74 | // Identifies the API needed to execute the resource file if applicable. 75 | ApiFramework string `xml:"apiFramework,attr,omitempty"` 76 | // Identifies the MIME type of the file provided. 77 | Type bool `xml:"type,attr,omitempty"` 78 | // A CDATA-wrapped URI to a file providing Closed Caption info for the media file. 79 | URI string `xml:",cdata"` 80 | } 81 | 82 | type Mezzanine struct { 83 | // Method of delivery of ad (either "streaming" or "progressive") 84 | Delivery string `xml:"delivery,attr"` 85 | // MIME type. Popular MIME types include, but are not limited to 86 | // “video/x-ms-wmv” for Windows Media, and “video/x-flv” for Flash 87 | // Video. Image ads or interactive ads can be included in the 88 | // MediaFiles section with appropriate Mime types 89 | Type string `xml:"type,attr"` 90 | // Pixel dimensions of video. 91 | Width int `xml:"width,attr"` 92 | // Pixel dimensions of video. 93 | Height int `xml:"height,attr"` 94 | // The codec used to produce the media file. 95 | Codec string `xml:"codec,attr,omitempty" json:",omitempty"` 96 | // Optional identifier 97 | ID string `xml:"id,attr,omitempty" json:",omitempty"` 98 | // Optional field that helps eliminate the need to calculate the size based on bitrate and duration. 99 | // Units - Bytes 100 | FileSize int `xml:"fileSize,attr,omitempty" json:",omitempty"` 101 | // Type of media file (2D / 3D / 360 / etc). Optional. 102 | // Default value = 2D 103 | MediaType string `xml:"mediaType,attr,omitempty" json:",omitempty"` 104 | // A CDATA-wrapped URI to a raw, high-quality media file 105 | URI string `xml:",cdata"` 106 | } 107 | 108 | type InteractiveCreativeFile struct { 109 | // Identifies the API needed to execute the resource file if applicable. 110 | ApiFramework string `xml:"apiFramework,attr,omitempty"` 111 | // Identifies the MIME type of the file provided. 112 | Type bool `xml:"type,attr,omitempty"` 113 | // Useful for interactive use cases. 114 | // Identifies whether the ad always drops when the duration is reached, 115 | // or if it can potentially extend the duration by pausing the underlying video or delaying the adStopped call after adVideoComplete. 116 | // If it set to true the extension of the duration should be user-initiated (typically by engaging with an interactive element to view additional content). 117 | VariableDuration bool `xml:"variableDuration,attr,omitempty"` 118 | // A CDATA-wrapped URI to a file providing Closed Caption info for the media file. 119 | URI string `xml:",cdata"` 120 | } 121 | 122 | type ClosedCaptionFiles struct { 123 | ClosedCaptionFile []ClosedCaptionFile `xml:"ClosedCaptionFile,omitempty" json:",omitempty"` 124 | } 125 | 126 | type ClosedCaptionFile struct { 127 | // Identifies the MIME type of the file provided. 128 | Type string `xml:"type,attr,omitempty"` 129 | // Language of the Closed Caption File using ISO 631-1 codes. 130 | // An optional locale suffix can also be provided. 131 | // Examples - “en”, “en-US”, “zh-TW”, 132 | Language string `xml:"language,attr,omitempty"` 133 | // A CDATA-wrapped URI to a file providing Closed Caption info for the media file. 134 | URI string `xml:",cdata"` 135 | } 136 | 137 | type IconClickFallbackImages struct { 138 | // Use to display information when an IconClick occurs 139 | IconClickFallbackImage []IconClickFallbackImage `xml:"IconClickFallbackImage"` 140 | } 141 | 142 | type IconClickFallbackImage struct { 143 | AltText string `xml:"AltText,omitempty"` 144 | StaticResource *CDATAString `xml:"StaticResource,omitempty"` 145 | Height int `xml:"height,attr,omitempty"` 146 | Width int `xml:"width,attr,omitempty"` 147 | } 148 | --------------------------------------------------------------------------------