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  }