forked from prebid/prebid-server
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathevents.go
136 lines (123 loc) · 5.01 KB
/
events.go
1
2
3
4
5
6
7
8
9
10
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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
package exchange
import (
"time"
"github.com/prebid/prebid-server/v3/exchange/entities"
jsonpatch "gopkg.in/evanphx/json-patch.v4"
"github.com/prebid/prebid-server/v3/analytics"
"github.com/prebid/prebid-server/v3/config"
"github.com/prebid/prebid-server/v3/endpoints/events"
"github.com/prebid/prebid-server/v3/openrtb_ext"
"github.com/prebid/prebid-server/v3/util/jsonutil"
)
// eventTracking has configuration fields needed for adding event tracking to an auction response
type eventTracking struct {
accountID string
enabledForAccount bool
enabledForRequest bool
auctionTimestampMs int64
integrationType string
bidderInfos config.BidderInfos
externalURL string
}
// getEventTracking creates an eventTracking object from the different configuration sources
func getEventTracking(requestExtPrebid *openrtb_ext.ExtRequestPrebid, ts time.Time, account *config.Account, bidderInfos config.BidderInfos, externalURL string) *eventTracking {
return &eventTracking{
accountID: account.ID,
enabledForAccount: account.Events.Enabled,
enabledForRequest: requestExtPrebid != nil && requestExtPrebid.Events != nil,
auctionTimestampMs: ts.UnixNano() / 1e+6,
integrationType: getIntegrationType(requestExtPrebid),
bidderInfos: bidderInfos,
externalURL: externalURL,
}
}
func getIntegrationType(requestExtPrebid *openrtb_ext.ExtRequestPrebid) string {
if requestExtPrebid != nil {
return requestExtPrebid.Integration
}
return ""
}
// modifyBidsForEvents adds bidEvents and modifies VAST AdM if necessary.
func (ev *eventTracking) modifyBidsForEvents(seatBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid) map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid {
for bidderName, seatBid := range seatBids {
modifyingVastXMLAllowed := ev.isModifyingVASTXMLAllowed(bidderName.String())
for _, pbsBid := range seatBid.Bids {
if modifyingVastXMLAllowed {
ev.modifyBidVAST(pbsBid, bidderName)
}
pbsBid.BidEvents = ev.makeBidExtEvents(pbsBid, bidderName)
}
}
return seatBids
}
// isModifyingVASTXMLAllowed returns true if this bidder config allows modifying VAST XML for event tracking
func (ev *eventTracking) isModifyingVASTXMLAllowed(bidderName string) bool {
return ev.bidderInfos[bidderName].ModifyingVastXmlAllowed && ev.isEventAllowed()
}
// modifyBidVAST injects event Impression url if needed, otherwise returns original VAST string
func (ev *eventTracking) modifyBidVAST(pbsBid *entities.PbsOrtbBid, bidderName openrtb_ext.BidderName) {
bid := pbsBid.Bid
if pbsBid.BidType != openrtb_ext.BidTypeVideo || len(bid.AdM) == 0 && len(bid.NURL) == 0 {
return
}
vastXML := makeVAST(bid)
bidID := bid.ID
if len(pbsBid.GeneratedBidID) > 0 {
bidID = pbsBid.GeneratedBidID
}
if newVastXML, ok := events.ModifyVastXmlString(ev.externalURL, vastXML, bidID, bidderName.String(), ev.accountID, ev.auctionTimestampMs, ev.integrationType); ok {
bid.AdM = newVastXML
}
}
// modifyBidJSON injects "wurl" (win) event url if needed, otherwise returns original json
func (ev *eventTracking) modifyBidJSON(pbsBid *entities.PbsOrtbBid, bidderName openrtb_ext.BidderName, jsonBytes []byte) ([]byte, error) {
if !ev.isEventAllowed() || pbsBid.BidType == openrtb_ext.BidTypeVideo {
return jsonBytes, nil
}
var winEventURL string
if pbsBid.BidEvents != nil { // All bids should have already been updated with win/imp event URLs
winEventURL = pbsBid.BidEvents.Win
} else {
winEventURL = ev.makeEventURL(analytics.Win, pbsBid, bidderName)
}
// wurl attribute is not in the schema, so we have to patch
patch, err := jsonutil.Marshal(map[string]string{"wurl": winEventURL})
if err != nil {
return jsonBytes, err
}
modifiedJSON, err := jsonpatch.MergePatch(jsonBytes, patch)
if err != nil {
return jsonBytes, err
}
return modifiedJSON, nil
}
// makeBidExtEvents make the data for bid.ext.prebid.events if needed, otherwise returns nil
func (ev *eventTracking) makeBidExtEvents(pbsBid *entities.PbsOrtbBid, bidderName openrtb_ext.BidderName) *openrtb_ext.ExtBidPrebidEvents {
if !ev.isEventAllowed() || pbsBid.BidType == openrtb_ext.BidTypeVideo {
return nil
}
return &openrtb_ext.ExtBidPrebidEvents{
Win: ev.makeEventURL(analytics.Win, pbsBid, bidderName),
Imp: ev.makeEventURL(analytics.Imp, pbsBid, bidderName),
}
}
// makeEventURL returns an analytics event url for the requested type (win or imp)
func (ev *eventTracking) makeEventURL(evType analytics.EventType, pbsBid *entities.PbsOrtbBid, bidderName openrtb_ext.BidderName) string {
bidId := pbsBid.Bid.ID
if len(pbsBid.GeneratedBidID) > 0 {
bidId = pbsBid.GeneratedBidID
}
return events.EventRequestToUrl(ev.externalURL,
&analytics.EventRequest{
Type: evType,
BidID: bidId,
Bidder: string(bidderName),
AccountID: ev.accountID,
Timestamp: ev.auctionTimestampMs,
Integration: ev.integrationType,
})
}
// isEventAllowed checks if events are enabled by default or on account/request level
func (ev *eventTracking) isEventAllowed() bool {
return ev.enabledForAccount || ev.enabledForRequest
}