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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
|
import { isSome } from "@jet/environment";
import { isNothing } from "@jet/environment/types/optional";
import { AppStoreMetricsData, } from "../../api/models/metrics/metrics";
import * as serverData from "../../foundation/json-parsing/server-data";
import * as client from "../../foundation/wrappers/client";
import { EventLinter } from "./event-linter";
import { optOutOfLegacyMetricsIdFieldsProvider } from "./helpers/legacy-metrics-identifier-fields-opt-out";
export function createMetricsClickData(objectGraph, targetId, targetType, eventFields, additionalIncludingFields, isDefaultBrowser) {
const fields = {};
Object.assign(fields, eventFields);
fields["eventType"] = "click";
fields["targetType"] = targetType;
fields["targetId"] = targetId;
const include = ["impressionsSnapshot", "pageFields"];
if (!preprocessor.GAMES_TARGET) {
include.push("contentRestrictionReasons");
}
if (additionalIncludingFields) {
include.push(...additionalIncludingFields);
}
addWebClientEventFields(objectGraph, fields);
addAltAb2DataToEventFields(objectGraph, fields);
return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, include, [], topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields, null, isDefaultBrowser)));
}
export function createMetricsBackClickData(objectGraph, eventFields) {
const fields = {};
Object.assign(fields, eventFields);
fields["actionType"] = "back";
const clickData = createMetricsClickData(objectGraph, "back", "button", fields);
return clickData;
}
export function createMetricsPageData(objectGraph, isReferralEligible, isCrossfireReferralCandidate, timingMetrics, eventFields, isDefaultBrowser) {
const fields = {};
Object.assign(fields, eventFields);
fields["eventType"] = "page";
if (timingMetrics) {
fields["clientCorrelationKey"] = timingMetrics.clientCorrelationKey;
fields["requestStartTime"] = timingMetrics.requestStartTime;
fields["responseStartTime"] = timingMetrics.responseStartTime;
fields["responseEndTime"] = timingMetrics.responseEndTime;
}
const include = ["pageFields", "pageReferrer"];
if (!preprocessor.GAMES_TARGET) {
include.push("userContentRestriction");
}
if (isReferralEligible) {
include.push("crossfireReferral");
}
else if (isCrossfireReferralCandidate) {
include.push("crossfireReferralCandidate"); // Only possible when not crossfire eligible.
}
addAltAb2DataToEventFields(objectGraph, fields);
addWebClientEventFields(objectGraph, fields);
return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, include, [], topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields, null, isDefaultBrowser)));
}
export function createMetricsSearchData(objectGraph, term, target, actionType, actionUrl, eventFields, additionalIncludingFields) {
const fields = {};
Object.assign(fields, eventFields);
fields["term"] = term;
fields["targetType"] = target;
fields["actionType"] = actionType;
if (actionUrl) {
fields["actionUrl"] = actionUrl; // actionUrl is defined for `hints` but not for searches fired from elsewhere.
}
fields["eventType"] = "search";
const include = ["pageReferrer"];
if (additionalIncludingFields) {
include.push(...additionalIncludingFields);
}
addWebClientEventFields(objectGraph, fields);
addAltAb2DataToEventFields(objectGraph, fields);
return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, include, [], topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields)));
}
export function createMetricsPageRenderFields(objectGraph, timingMetrics, eventFields) {
const fields = {};
Object.assign(fields, eventFields);
fields["eventType"] = "pageRender";
if (timingMetrics) {
if (!fields["pageUrl"]) {
fields["pageUrl"] = timingMetrics.pageURL;
}
fields["clientCorrelationKey"] = timingMetrics.clientCorrelationKey;
fields["platformRequestStartTime"] = timingMetrics.requestStartTime;
fields["platformResponseStartTime"] = timingMetrics.responseStartTime;
fields["platformResponseEndTime"] = timingMetrics.responseEndTime;
fields["platformResponseWasCached"] = timingMetrics.responseWasCached;
fields["platformJsonParseStartTime"] = timingMetrics.parseStartTime;
fields["platformJsonParseEndTime"] = timingMetrics.parseEndTime;
}
addWebClientEventFields(objectGraph, fields);
addAltAb2DataToEventFields(objectGraph, fields);
return fields;
}
/**
* Create a metrics data for regular impressions.
* @param objectGraph The dependency graph for the App Store.
* @param eventFields Base fields to build off on.
* @param shouldIncludeAdFieldsForPad Whether or not metrics data should include iPad related fields for adverts.
* @param includeAdRotationFields Whether or not metrics data should include advert related fields.
* @param hasImpressionsAppendix Whether condensed format search results should track appendix data.
*/
export function createMetricsImpressionsData(objectGraph, eventFields, shouldIncludeAdFieldsForPad, includeAdRotationFields, hasImpressionsAppendix) {
const fields = {};
Object.assign(fields, eventFields);
fields["eventType"] = "impressions";
fields["impressionQueue"] = "data-metrics";
fields["eventVersion"] = 4;
const include = ["impressions", "pageFields", "pageReferrer"];
if (!preprocessor.GAMES_TARGET) {
include.push("contentRestrictionReasons");
}
if (shouldIncludeAdFieldsForPad) {
include.push("advertDeviceWindow");
}
if (includeAdRotationFields) {
include.push("advertRotation");
}
if (hasImpressionsAppendix) {
include.push("impressionsAppendix");
}
addWebClientEventFields(objectGraph, fields);
addAltAb2DataToEventFields(objectGraph, fields);
return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, include, ["eventVersion"], topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields)));
}
/**
* Create a metrics data for fast impressions, a special type for SearchAds on Search Page.
* Included fields assume fields are for search page w/ Ads.
* @param baseFields Base fields to build off on.
*/
export function createMetricsFastImpressionsData(objectGraph, baseFields, pageInformation) {
var _a, _b;
const shouldIncludeAdFieldsForPad = serverData.isDefinedNonNull(pageInformation.iAdInfo) &&
objectGraph.client.isPad &&
(isNothing(pageInformation.iAdInfo.missedOpportunityReason) ||
pageInformation.iAdInfo.missedOpportunityReason.length === 0);
const shouldIncludeAdRotationFields = (_b = (_a = pageInformation.iAdInfo) === null || _a === void 0 ? void 0 : _a.shouldIncludeAdRotationFields) !== null && _b !== void 0 ? _b : false;
const exclude = [];
const fields = createMetricsImpressionsData(objectGraph, baseFields, shouldIncludeAdFieldsForPad, shouldIncludeAdRotationFields, false).fields;
fields["impressionQueue"] = "data-metrics-impressions-low-latency";
if (pageInformation !== null && serverData.isDefinedNonNull(pageInformation.iAdInfo)) {
const eventVersion = pageInformation.iAdInfo.fastImpressionsEventVersion;
fields["eventVersion"] = eventVersion;
exclude.push("eventVersion");
// Make some manual adjustments to events for v5.
if (eventVersion === 5) {
// Indicates the viewable area where elements can be impressed excludes the tab bar
fields["viewableArea"] = "excludingTabBar";
// Remove the `iAdPlacementId` for v5. It's added for compatibility with v4 impressions.
delete fields["iAdPlacementId"];
}
}
const include = ["fastImpressions", "pageFields", "pageReferrer"];
if (shouldIncludeAdFieldsForPad) {
include.push("advertDeviceWindow");
}
if (shouldIncludeAdRotationFields) {
include.push("advertRotation");
}
return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, include, exclude, topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields, pageInformation)));
}
export function createMetricsMediaData(objectGraph, eventFields) {
const fields = {};
Object.assign(fields, eventFields);
fields["eventType"] = "media";
addWebClientEventFields(objectGraph, fields);
addAltAb2DataToEventFields(objectGraph, fields);
return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, [], [], topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields)));
}
export function createMetricsMediaClickData(objectGraph, targetId, targetType, eventFields) {
const fields = {};
Object.assign(fields, eventFields);
fields["eventType"] = "click";
fields["targetType"] = targetType;
fields["targetId"] = targetId;
const include = ["pageFields"];
addWebClientEventFields(objectGraph, fields);
addAltAb2DataToEventFields(objectGraph, fields);
return optOutOfLegacyMetricsIdFieldsProvider(objectGraph, new AppStoreMetricsData(fields, include, [], topicFromEventFields(objectGraph, fields), shouldFlushFromEventFields(objectGraph, fields)));
}
function shouldFlushFromEventFields(objectGraph, eventFields, pageInformation = null, isDefaultBrowser) {
var _a, _b;
const eventType = eventFields["eventType"];
let shouldFlush = false;
if (!serverData.isDefinedNonNullNonEmpty(eventType)) {
return shouldFlush;
}
const isDefaultBrowserContext = isDefaultBrowser !== null && isDefaultBrowser !== void 0 ? isDefaultBrowser : false;
switch (eventType) {
case "click":
shouldFlush =
serverData.asBooleanOrFalse(eventFields, EventLinter.hasIAdData) ||
isDefaultBrowserContext;
break;
case "exit":
shouldFlush = true;
break;
case "impressions":
shouldFlush = serverData.asBooleanOrFalse(eventFields, EventLinter.hasIAdData);
// Not my best work here.
// For most ad placements on a page, it's fine to check the `hasIAdData` as an indicator for whether we should flush after a given event.
// The challenge for the product page placements is that they're fetched asynchronously, and we don't create an entirely new impressions
// event when that happens (we just update fields within the event via the `pageChange` mechanism). To ensure that fast impression events on
// the product page are actually fast, we have to force the events to flush if they meet the below conditions that effectively guarantee
// we will be impressing something on the low latency queue.
if (eventFields["impressionQueue"] === "data-metrics-impressions-low-latency" &&
(((_a = pageInformation === null || pageInformation === void 0 ? void 0 : pageInformation.iAdInfo) === null || _a === void 0 ? void 0 : _a.placementType) === "productPageYMAL" ||
((_b = pageInformation === null || pageInformation === void 0 ? void 0 : pageInformation.iAdInfo) === null || _b === void 0 ? void 0 : _b.placementType) === "productPageYMALDuringDownload")) {
shouldFlush = true;
}
break;
case "page":
// rdar://98487650 (CL seed: Product Page observed lower % of events coming in <2 mins ( page change + page events ))
// In order to resolve issues with flushing timeliness in the PPE: rdar://93127678 ([Metrics] Dismissing store sheet does not fire clickstream events)
// we allow page events with ad data in them to cause a flush on product pages in the PPE.
// We also pre-emptively flush for page events where it's the default browser flow in order to "prewarm" the metrics pipeline, ensuring flushes can occur
// if and when the user taps "Open" on an installed app.
const isProductPageExtension = objectGraph.host.clientIdentifier === client.productPageExtensionIdentifier;
shouldFlush =
isProductPageExtension &&
(serverData.asBooleanOrFalse(eventFields, EventLinter.hasIAdData) ||
isDefaultBrowserContext);
break;
default:
break;
}
const isSubscribePageExtensionEnterExitEventsEnabled = objectGraph.host.isiOS;
if (objectGraph.host.clientIdentifier === client.subscribePageExtensionIdentifier &&
!isSubscribePageExtensionEnterExitEventsEnabled) {
// <rdar://problem/55865604> Metrics: missing metrics events for arcade upsell from springboard app open on unsubscribed user
// Until a native fix is in to address enter/exit events in SPE (subscribePageExtensionEnterExitEvents), we
// need to force events in the SubscribePageExtension to trigger a flush.
shouldFlush = true;
}
return shouldFlush;
}
function topicFromEventFields(objectGraph, eventFields) {
const topic = eventFields["topic"] || objectGraph.bag.metricsTopic;
return topic;
}
function addAltAb2DataToEventFields(objectGraph, eventFields) {
if (objectGraph.bag.isMetricsAb2DataFallbackEnabled && isSome(objectGraph.experimentCache)) {
eventFields["alt_ab2_data"] = JSON.stringify(objectGraph.experimentCache.createAb2Data());
}
}
/**
* Attach expected metrics fields specific to the "web" client, if necessary
*/
function addWebClientEventFields(objectGraph, eventFields) {
var _a;
if (!objectGraph.client.isWeb) {
return;
}
// The `platformContext` field is expected to reflect the "platform" that the user is browsing
// at the time of the event
eventFields["platformContext"] = (_a = objectGraph.activeIntent) === null || _a === void 0 ? void 0 : _a.previewPlatform;
}
//# sourceMappingURL=builder.js.map
|