Skip to content

Commit a22eec5

Browse files
authored
1 parent fc3dd28 commit a22eec5

File tree

7 files changed

+15378
-0
lines changed

7 files changed

+15378
-0
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
2+
2.0.2 / 2018-07-09
3+
==================
4+
5+
* Pushes `event_name: 'identify'` to the dataLayer for Segment identify
6+
events when "Send Event Names" UI setting is enabled.
7+
8+
2.0.1 / 2018-06-25
9+
==================
10+
11+
* Fix bug preventing us from deleting dataLayer b/w sessions.
12+
13+
2.0.0 / 2018-06-13
14+
==================
15+
16+
* Add v2 logic and tests and remove temp fix.
17+
18+
1.3.4 / 2018-01-18
19+
==================
20+
21+
* Instantiate window.kruxDataLayer manually if non-existent
22+
23+
1.3.0 / 2017-11-21
24+
==================
25+
26+
* Add functionality for Track calls to re-fire pixel.gif
27+
28+
1.2.0 / 2017-08-28
29+
==================
30+
31+
* Modify usermatch logic.
32+
33+
1.0.1 / 2017-07-18
34+
==================
35+
36+
* Patch bump for deploy
37+
38+
1.0.0 / 2017-07-16
39+
==================
40+
41+
* Initial commit :sparkles:
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# analytics.js-integration-salesforce-dmp [![Build Status][ci-badge]][ci-link]
2+
3+
Salesforce DMP integration for [Analytics.js][].
4+
5+
## License
6+
7+
Released under the [MIT license](LICENSE).
8+
9+
10+
[Analytics.js]: https://segment.com/docs/libraries/analytics.js/
11+
[ci-link]: https://ci.segment.com/gh/segment-integrations/analytics.js-integration-salesforce-dmp
12+
[ci-badge]: https://ci.segment.com/gh/segment-integrations/analytics.js-integration-salesforce-dmp.svg?style=svg
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
'use strict'
2+
3+
/**
4+
* Module dependencies.
5+
*/
6+
7+
var integration = require('@segment/analytics.js-integration')
8+
9+
/**
10+
* Expose `Salesforce DMP` integration.
11+
*/
12+
13+
var SalesforceDMP = module.exports = integration('Salesforce DMP')
14+
.option('confId', '')
15+
.option('trackFireEvents', [])
16+
.option('eventAttributeMap', {})
17+
.option('namespace', '')
18+
.tag('init', '<script src="//cdn.krxd.net/controltag/{{ confId }}.js">')
19+
.tag('usermatch', '<img src="https://beacon.krxd.net/usermatch.gif?partner=segment_io&partner_uid={{ userId }}">')
20+
21+
SalesforceDMP.prototype.initialize = function () {
22+
// We require a confid to run this integration.
23+
if (!this.options.confId) return
24+
if (this.options.useV2LogicClient) {
25+
this.identify = this.identifyV2
26+
this.page = this.pageV2
27+
this.track = this.trackV2
28+
}
29+
var self = this
30+
31+
window.Krux||((window.Krux=function(){window.Krux.q.push(arguments)}).q=[]) //eslint-disable-line
32+
33+
this.load('init', function () {
34+
self.ready()
35+
})
36+
}
37+
38+
SalesforceDMP.prototype.loaded = function () {
39+
return !!(window.Krux && window.Krux.q && window.Krux.ns)
40+
}
41+
42+
SalesforceDMP.prototype.identify = function (identify) {
43+
// Identify should prefer the userId, if it exists.
44+
var userId = identify.userId() || identify.anonymousId()
45+
this.load('usermatch', {userId: userId})
46+
}
47+
48+
SalesforceDMP.prototype.page = function (page) {
49+
// Page should prefer the anonId, if it exists.
50+
var userId = page.anonymousId() || page.userId()
51+
this.load('usermatch', {userId: userId})
52+
}
53+
54+
SalesforceDMP.prototype.track = function (track) {
55+
// Track allows the user to re-fire the Krux pixel on specific events, as well
56+
// as modify the Krux datalayer, if they so choose.
57+
if (!this.options.namespace) return
58+
59+
// Initialize kruxDataLayer
60+
// Some customers manage this directly. Delete it between sessions if it doesn't pre-exist.
61+
var resetDataLayer = false
62+
63+
if (!window.kruxDataLayer) {
64+
resetDataLayer = true
65+
window.kruxDataLayer = {}
66+
}
67+
68+
// Verify that this event is one we want to fire on, if a whitelist exists.
69+
if (this.options.trackFireEvents.length) {
70+
for (var i = 0; i < this.options.trackFireEvents.length; i++) {
71+
var event = this.options.trackFireEvents[i]
72+
// Continue execution if we find the event in the list. Otherwise, bail out.
73+
if (event.toLowerCase() === track.event().toLowerCase()) break
74+
if (i === this.options.trackFireEvents.length - 1) return
75+
}
76+
}
77+
78+
// Modify the dataLayer with any defined adjustments. It's okay if they choose to make none.
79+
for (var segmentProp in this.options.eventAttributeMap) {
80+
// { Segment Property -> Krux Property }
81+
var kruxKey = this.options.eventAttributeMap[segmentProp]
82+
var value = track.proxy('properties.' + segmentProp)
83+
if (value) window.kruxDataLayer[kruxKey] = value
84+
}
85+
86+
// This re-fires the Krux tag with the given namespace without counting it as a new page view.
87+
// Namespace starts with 'ns:'
88+
var namespace = this.options.namespace
89+
if (namespace.length <= 3 || namespace.toLowerCase().slice(0, 3) !== 'ns:') namespace = 'ns:' + namespace
90+
91+
// This re-fires the pixel.gif. It will silently fail if `namespace` does not match the namespace on the main Krux instance!
92+
window.Krux(namespace, 'page:load', function (err) {
93+
if (err) console.error(err)
94+
if (resetDataLayer) delete window.kruxDataLayer
95+
}, {pageView: false})
96+
}
97+
98+
/**
99+
* `Salesforce DMP` V2 Logic.
100+
*/
101+
102+
SalesforceDMP.prototype.identifyV2 = SalesforceDMP.prototype.trackV2 = function (msg) {
103+
if (!this.options.namespace) return
104+
var resetDataLayer
105+
var type = msg.type()
106+
107+
if (type === 'track') {
108+
// Verify that this event is one we want to fire on, if a whitelist exists.
109+
if (this.options.trackFireEvents.length) {
110+
for (var i = 0; i < this.options.trackFireEvents.length; i++) {
111+
var event = this.options.trackFireEvents[i]
112+
// Continue execution if we find the event in the list. Otherwise, bail out.
113+
if (event.toLowerCase() === msg.event().toLowerCase()) {
114+
// Create window.kruxDataLayer
115+
resetDataLayer = createDataLayer()
116+
break
117+
}
118+
if (i === this.options.trackFireEvents.length - 1) return
119+
}
120+
}
121+
122+
// Modify the dataLayer with any defined adjustments. It's okay if they choose to make none.
123+
for (var segmentProp in this.options.eventAttributeMap) {
124+
// { Segment Property -> Krux Property }
125+
var kruxKey = this.options.eventAttributeMap[segmentProp]
126+
var value = msg.proxy('properties.' + segmentProp)
127+
if (value) window.kruxDataLayer[kruxKey] = value
128+
}
129+
130+
for (segmentProp in this.options.contextTraitsMap) {
131+
// { Segment Context Property -> Krux Property }
132+
kruxKey = this.options.contextTraitsMap[segmentProp]
133+
value = msg.proxy('context.traits.' + segmentProp)
134+
if (value) window.kruxDataLayer[kruxKey] = value
135+
}
136+
} else {
137+
resetDataLayer = createDataLayer()
138+
}
139+
140+
if (this.options.sendEventNames && !window.kruxDataLayer['event_name']) {
141+
var name
142+
if (type === 'track') {
143+
name = msg.event()
144+
} else {
145+
if (this.options.sendIdentifyAsEventName) {
146+
name = type
147+
}
148+
}
149+
if (name) window.kruxDataLayer['event_name'] = name
150+
}
151+
152+
if (msg.userId()) window.kruxDataLayer['segmentio_user_id'] = msg.userId()
153+
if (msg.anonymousId()) window.kruxDataLayer['segmentio_anonymous_id'] = msg.anonymousId()
154+
if (msg.proxy('context.traits.crossDomainId')) window.kruxDataLayer['segmentio_xid'] = msg.proxy('context.traits.crossDomainId')
155+
156+
this.firePixel(resetDataLayer)
157+
}
158+
159+
SalesforceDMP.prototype.pageV2 = function (page) {
160+
// Noop on page events because SFDMP's control tag auto-fires a call to the pixel endpoint on page load
161+
}
162+
163+
SalesforceDMP.prototype.firePixel = function (resetDataLayer) {
164+
// This re-fires the Krux tag with the given namespace without counting it as a new page view.
165+
// Namespace starts with 'ns:'
166+
var namespace = this.options.namespace
167+
if (namespace.length <= 3 || namespace.toLowerCase().slice(0, 3) !== 'ns:') namespace = 'ns:' + namespace
168+
169+
// This re-fires the pixel.gif. It will silently fail if `namespace` does not match the namespace on the main Krux instance!
170+
window.Krux(namespace, 'page:load', function (err) {
171+
if (err) console.error(err)
172+
if (resetDataLayer) delete window.kruxDataLayer
173+
}, {pageView: false})
174+
}
175+
176+
/**
177+
* Initialize kruxDataLayer
178+
* Some customers manage this directly. Segment deletes it between sessions if it doesn't pre-exist.
179+
*/
180+
181+
function createDataLayer () {
182+
if (!window.kruxDataLayer) {
183+
window.kruxDataLayer = {}
184+
return true
185+
}
186+
return false
187+
}

0 commit comments

Comments
 (0)