github.com/prebid/prebid-server/v2@v2.18.0/config/events.go (about) 1 package config 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 8 validator "github.com/asaskevich/govalidator" 9 ) 10 11 // VASTEventElement indicates valid VAST event element 12 type VASTEventElement string 13 14 const ( 15 ImpressionVASTElement VASTEventElement = "impression" 16 TrackingVASTElement VASTEventElement = "tracking" 17 ClickTrackingVASTElement VASTEventElement = "clicktracking" 18 CompanionClickThroughVASTElement VASTEventElement = "companionclickthrough" 19 ErrorVASTElement VASTEventElement = "error" 20 NonLinearClickTrackingVASTElement VASTEventElement = "nonlinearclicktracking" 21 ) 22 23 var vastEventElementMap = map[VASTEventElement]struct{}{ 24 ImpressionVASTElement: {}, 25 TrackingVASTElement: {}, 26 ClickTrackingVASTElement: {}, 27 CompanionClickThroughVASTElement: {}, 28 ErrorVASTElement: {}, 29 NonLinearClickTrackingVASTElement: {}, 30 } 31 32 // TrackingEventType indicates quartile events 33 type TrackingEventType string 34 35 const ( 36 Start TrackingEventType = "start" 37 FirstQuartile TrackingEventType = "firstQuartile" 38 MidPoint TrackingEventType = "midPoint" 39 ThirdQuartile TrackingEventType = "thirdQuartile" 40 Complete TrackingEventType = "complete" 41 ) 42 43 var trackingEventTypeMap = map[TrackingEventType]struct{}{ 44 Start: {}, 45 FirstQuartile: {}, 46 MidPoint: {}, 47 ThirdQuartile: {}, 48 Complete: {}, 49 } 50 51 // VASTEvent indicates the configurations required for injecting VAST event trackers within 52 // VAST XML 53 type VASTEvent struct { 54 CreateElement VASTEventElement `mapstructure:"create_element" json:"create_element"` 55 Type TrackingEventType `mapstructure:"type" json:"type"` 56 ExcludeDefaultURL bool `mapstructure:"exclude_default_url" json:"exclude_default_url"` 57 URLs []string `mapstructure:"urls" json:"urls"` 58 } 59 60 // Events indicates the various types of events to be captured typically for injecting tracker URLs 61 // within the VAST XML 62 // Don't enable this feature. It is still under developmment. Please follow https://github.com/prebid/prebid-server/issues/1725 for more updates 63 type Events struct { 64 Enabled bool `mapstructure:"enabled" json:"enabled"` 65 DefaultURL string `mapstructure:"default_url" json:"default_url"` 66 VASTEvents []VASTEvent `mapstructure:"vast_events" json:"vast_events,omitempty"` 67 } 68 69 // validate verifies the events object and returns error if at least one is invalid. 70 func (e Events) validate(errs []error) []error { 71 if e.Enabled { 72 if !isValidURL(e.DefaultURL) { 73 return append(errs, errors.New("Invalid events.default_url")) 74 } 75 err := validateVASTEvents(e.VASTEvents) 76 if err != nil { 77 return append(errs, err) 78 } 79 } 80 return errs 81 } 82 83 // validateVASTEvents verifies the all VASTEvent objects and returns error if at least one is invalid. 84 func validateVASTEvents(events []VASTEvent) error { 85 for i, event := range events { 86 if err := event.validate(); err != nil { 87 return fmt.Errorf(err.Error(), i, i) 88 } 89 } 90 return nil 91 } 92 93 // validate validates event object and returns error if at least one is invalid 94 func (e VASTEvent) validate() error { 95 if !e.CreateElement.isValid() { 96 return fmt.Errorf("Invalid events.vast_events[%s].create_element", "%d") 97 } 98 validType := e.Type.isValid() 99 100 if e.isTrackingEvent() && !validType { 101 var ele []string 102 for k := range vastEventElementMap { 103 ele = append(ele, string(k)) 104 } 105 return fmt.Errorf("Missing or Invalid events.vast_events[%s].type. Valid values are %v", "%d", strings.Join(ele, ", ")) 106 } 107 if validType && !e.isTrackingEvent() { 108 return fmt.Errorf("events.vast_events[%s].type is not applicable for create element '%s'", "%d", e.CreateElement) 109 } 110 for i, url := range e.URLs { 111 if !isValidURL(url) { 112 return fmt.Errorf("Invalid events.vast_events[%s].urls[%d]", "%d", i) 113 } 114 } 115 // ensure at least one valid url exists when default URL to be excluded 116 if e.ExcludeDefaultURL && len(e.URLs) == 0 { 117 return fmt.Errorf("Please provide at least one valid URL in events.vast_events[%s].urls or set events.vast_events[%s].exclude_default_url=false", "%d", "%d") 118 } 119 120 return nil // no errors 121 } 122 123 // isValid checks create_element has valid value 124 // if value is value returns true, otherwise false 125 func (element VASTEventElement) isValid() bool { 126 // validate create element 127 if _, ok := vastEventElementMap[element]; ok { 128 return true 129 } 130 return false 131 } 132 133 // isValid checks if valid type is provided (case-sensitive) 134 func (t TrackingEventType) isValid() bool { 135 _, valid := trackingEventTypeMap[t] 136 return valid 137 } 138 139 // isValidURL validates the event URL 140 func isValidURL(eventURL string) bool { 141 return validator.IsURL(eventURL) && validator.IsRequestURL(eventURL) 142 } 143 144 // isTrackingEvent returns true if event object contains event.CreateElement == "tracking" 145 func (e VASTEvent) isTrackingEvent() bool { 146 return e.CreateElement == TrackingVASTElement 147 }