This repository has been archived by the owner on Jun 6, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ad-gen.coffee
142 lines (120 loc) · 4.38 KB
/
ad-gen.coffee
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
137
138
139
140
141
142
###
Source: https://github.com/guardian/ad-code-gen/blob/master/ad-gen.coffee
###
# Generates DFP ad code.
#
# Slot parameters:
# data-ad-unit: Targeted DFP ad unit name [required]
# data-ad-size: Targeted creative size(s), eg. "100x200" or "100x200,200x300" [required for in-page ads]
# - if "0x0", an out-of-page ad will be built
# data-ad-target-<name>: Custom targeting, eg. data-ad-target-s="culture", data-ad-target-k="music,culture" [optional]
scriptName = "ad-gen.js"
networkId = "59666047"
scripts = document.querySelectorAll("script[src$='#{scriptName}']")
slot = scripts[scripts.length - 1]
slotName = "ad-slot-#{scripts.length}"
buildTargetSize = (size) ->
formatted = size.replace(/\s*,\s*/g, "],[").replace(/\s*x\s*/g, ",")
"[[#{formatted}]]"
buildCustomTargeting = ->
targeting = ""
for attr in slot.attributes
match = attr.name.match /^data-ad-target-(.+)$/
if match?
key = match[1]
value = attr.value.replace(/\s*,\s*/g, "','")
targeting += ".setTargeting('#{key}',['#{value}'])"
targeting
buildAllThirdPartySegments = ->
targeting = ""
kruxSegments = window.localStorage.kxsegs ? ""
if kruxSegments != ""
filling = kruxSegments.split(',').join("','")
output = "['#{filling}']"
targeting += ".setTargeting('x', #{output})"
targeting
buildThirdPartySegments = (segments) ->
buildSegmentValues = ->
values = ""
for segment in segments.split "&" when segment.length > 0
kv = segment.split "="
value = kv[1]
values += "'#{value}',"
values.substring(1, values.length - 2)
key = segments.split("&")[0].split("=")[0]
".setTargeting('#{key}',['#{buildSegmentValues()}'])"
pageLevelCodePart1 = "
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
(function() {
var gads = document.createElement(\"script\");
gads.async = true;
gads.type = \"text/javascript\";
var useSSL = \"https:\" == document.location.protocol;
gads.src = (useSSL ? \"https:\" : \"http:\") + \"//www.googletagservices.com/tag/js/gpt.js\";
var node = document.getElementsByTagName(\"script\")[0];
node.parentNode.insertBefore(gads, node);
})();
"
pageLevelCodePart2 = "
function enforceGTPCCPA(gtp){
gtp.pubads().setTargeting('rdp', 'na');
if(! window.__uspapi ){ return; }
window.__uspapi('getUSPData', 2,
function( data, success ){
if( !success ){ return; }
var rdpChar = data.uspString.charAt(2);
if( 'Y' === rdpChar ){
gtp.pubads().setTargeting('rdp', 't');
gtp.pubads().setPrivacySettings({
'restrictDataProcessing': true
});
}else if( 'N' === rdpChar ){
gtp.pubads().setTargeting('rdp', 'f');
}
});
}
googletag.cmd.push(function() {
googletag.pubads().enableAsyncRendering();
googletag.pubads().collapseEmptyDivs();
googletag.enableServices();
enforceGTPCCPA(googletag);
});
"
# Beware: GPT ad request has a max length and beyond that any custom targeting is ignored
buildSlotDeclaration = (size) ->
adUnitName = slot.getAttribute "data-ad-unit"
"googletag.cmd.push(function() {
googletag.defineSlot('/#{networkId}/#{adUnitName}', #{buildTargetSize(size)}, '#{slotName}')#{buildCustomTargeting()}#{buildAllThirdPartySegments()}.addService(googletag.pubads());
});"
buildOutOfPageSlotDeclaration = ->
adUnitName = slot.getAttribute "data-ad-unit"
"googletag.cmd.push(function() {
googletag.defineOutOfPageSlot('/#{networkId}/#{adUnitName}', '#{slotName}')#{buildCustomTargeting()}#{buildAllThirdPartySegments()}.addService(googletag.pubads());
});"
buildSlotCode = ->
"googletag.cmd.push(function() {
googletag.display('#{slotName}');
});"
insertScript = (content) ->
script = document.createElement "script"
slot.parentElement.appendChild script
script.type = "text/javascript"
script.text = content
insertAdConfig = ->
isFirstAd = scripts.length == 1
if isFirstAd
insertScript pageLevelCodePart1
insertScript pageLevelCodePart2
size = slot.getAttribute "data-ad-size"
if size == "0x0"
insertScript buildOutOfPageSlotDeclaration()
else
insertScript buildSlotDeclaration(size)
insertAd = ->
slotDiv = document.createElement "div"
slotDiv.setAttribute("id", slotName)
slot.parentElement.appendChild slotDiv
insertScript buildSlotCode()
insertAdConfig()
insertAd()