summaryrefslogtreecommitdiff
path: root/node_modules/@jet-app/app-store/tmp/src/common/metrics/helpers/buy.js
blob: b39f9cf08f9c5c0418843b185a70fc18d28cd13c (plain)
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
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
import { isNothing, isSome } from "@jet/environment/types/optional";
import * as serverData from "../../../foundation/json-parsing/server-data";
import { BuyParameters } from "../../../foundation/metrics/buy-parameters";
import { URL } from "../../../foundation/network/urls";
import * as productVariants from "../../product-page/product-page-variants";
import { MetricsReferralContext } from "../metrics-referral-context";
import * as metricsPosting from "../posting";
import * as misc from "./misc";
import { IAdSearchInformation } from "./models";
import * as metricsUtil from "./util";
//* *************************
//* Buy Metrics
//* *************************
/**
 * Adds bag driven metrics fields.
 * @param objectGraph
 * @returns
 */
function addBagMetricsToBuyParams(objectGraph, baseBuyParams) {
    const buyParams = new BuyParameters(baseBuyParams);
    const metricsConfiguration = objectGraph.bag.metricsConfiguration;
    const language = serverData.asString(metricsConfiguration, "metricsBase.language");
    buyParams.set("languageId", language);
    return buyParams.toString();
}
export function addPageMetricsToBuyParams(objectGraph, baseBuyParams, adamId, pageInformation, targetType, kind, metricsPlatformDisplayStyle, productVariantData, inAppEventId, excludeCrossfireAttribution, extRefApp2, extRefUrl2) {
    const buyParams = new BuyParameters(baseBuyParams);
    addPageMetricsToBuyParamsObject(objectGraph, buyParams, adamId, pageInformation, targetType, kind, metricsPlatformDisplayStyle, productVariantData, inAppEventId, excludeCrossfireAttribution, extRefApp2, extRefUrl2);
    addExtraInfoToBuyParamsObject(objectGraph, buyParams, pageInformation);
    return buyParams.toString();
}
export function addPageMetricsToBuyParamsObject(objectGraph, buyParams, adamId, pageInformation, targetType, kind, metricsPlatformDisplayStyle, productVariantData, inAppEventId, excludeCrossfireAttribution, extRefApp2, extRefUrl2) {
    var _a, _b, _c;
    const fields = misc.fieldsFromPageInformation(pageInformation);
    if (targetType) {
        buyParams.set("impressionType", targetType); // impressionType == targetType == locationType.
    }
    if (kind) {
        buyParams.set("kind", kind);
    }
    const pageId = serverData.asString(serverData.asJSONData(fields), "pageId");
    buyParams.set("pageId", pageId);
    const pageType = serverData.asString(serverData.asJSONData(fields), "pageType");
    buyParams.set("pageType", pageType);
    // Ad container id
    const iAdContainerId = serverData.asString(serverData.asJSONData(fields), "iAdContainerId");
    if (isSome(iAdContainerId) && iAdContainerId.length > 0) {
        buyParams.set(adBuyParamKeys.containerId, iAdContainerId, null);
    }
    // we add search terms to the page if the page is for the item we are buying, or if
    // its for a streamlined contingent offer
    const pageIds = (_a = pageId === null || pageId === void 0 ? void 0 : pageId.split("_")) !== null && _a !== void 0 ? _a : [];
    const pageMatchesProduct = pageIds.includes(adamId);
    const isProductPage = pageType === "Software";
    const isStreamlinedContingentOffer = ((_b = buyParams.get("contingentItemId", null)) === null || _b === void 0 ? void 0 : _b.length) > 0;
    if (!isProductPage || pageMatchesProduct || isStreamlinedContingentOffer) {
        // If there is a native search term, it will overwrite this
        // initial value below in `addNativeMetricsToBuyParams`.
        let searchTerm = serverData.asString(serverData.asJSONData(pageInformation), "searchTermContext.resultsTerm");
        // A search term may be attached to the product URL as a means of associating buys with searches.
        if (serverData.isNullOrEmpty(searchTerm)) {
            searchTerm = metricsUtil.searchTermFromProductURL(pageInformation === null || pageInformation === void 0 ? void 0 : pageInformation.pageUrl);
        }
        if (!serverData.isNull(searchTerm)) {
            buyParams.set("searchTerm", searchTerm);
        }
    }
    if (isProductPage && isSome(pageInformation) && isSome(pageInformation.pageUrl)) {
        const pageUrl = new URL(pageInformation.pageUrl);
        if (((_c = pageUrl.query) === null || _c === void 0 ? void 0 : _c["context"]) === "browserChoice") {
            buyParams.set("prevPage", "BrowserChoice");
            buyParams.set("browserChoiceScreenBuy", "1", null);
        }
    }
    productVariants.addProductPageVariantMetricsToBuyParams(buyParams, adamId, pageInformation === null || pageInformation === void 0 ? void 0 : pageInformation.productVariantData, productVariantData !== null && productVariantData !== void 0 ? productVariantData : undefined);
    if (!serverData.isNull(metricsPlatformDisplayStyle) && metricsPlatformDisplayStyle.length > 0) {
        buyParams.set("platformDisplayStyle", metricsPlatformDisplayStyle);
    }
    // App Event ID
    buyParams.set("inAppEventId", inAppEventId);
    // Referrer
    if (!excludeCrossfireAttribution) {
        if (serverData.isDefinedNonNull(MetricsReferralContext.shared.activeReferralData)) {
            buyParams.set("extRefApp2", MetricsReferralContext.shared.activeReferralData.extRefApp2, null);
            buyParams.set("extRefUrl2", MetricsReferralContext.shared.activeReferralData.extRefUrl2, null);
            if (isSome(MetricsReferralContext.shared.activeReferralData.kind)) {
                const extRefAppKindName = MetricsReferralContext.shared.activeReferralData.kind.name;
                if (extRefAppKindName === "clip" || extRefAppKindName === "appClip") {
                    buyParams.set("hostApp", "com.apple.AppStore.clipOverlay");
                }
            }
        }
        else {
            buyParams.set("extRefApp2", extRefApp2, null);
            buyParams.set("extRefUrl2", extRefUrl2, null);
        }
    }
}
function addExtraInfoToBuyParamsObject(objectGraph, buyParams, pageInformation) {
    var _a, _b;
    if (isNothing(pageInformation)) {
        return;
    }
    const extraInfo = [];
    const hasiAdData = isSome((_a = pageInformation.iAdInfo) === null || _a === void 0 ? void 0 : _a.clickFields["hasiAdData"]);
    if (hasiAdData) {
        const iAdExtraInfoKey = isIAdFromCurrentPage(objectGraph, pageInformation) ? "iAdSponsored" : "iAdOriginated";
        extraInfo.push({ key: iAdExtraInfoKey, value: "true" });
    }
    if (serverData.isDefinedNonNullNonEmpty(extraInfo)) {
        const extraInfoParamValue = extraInfo
            .map((extraInfoValue) => `${extraInfoValue.key}=${extraInfoValue.value}`)
            .join(";");
        const encodedValue = (_b = objectGraph.cryptography) === null || _b === void 0 ? void 0 : _b.base64Encode(extraInfoParamValue);
        if (isSome(encodedValue)) {
            buyParams.set("extraInfo", encodedValue);
        }
    }
}
/**
 * Determines if an iAd is from the current page by comparing the iAd's placement type with the page type.
 *
 * This function validates whether an advertisement is correctly placed on the appropriate page type.
 * Different ad placement types are designed for specific page contexts, and this function ensures
 * that the placement matches the current page context.
 *
 * @param objectGraph - The AppStore object graph providing access to app services and utilities
 * @param pageInformation - Information about the current page, including its type and iAd information
 * @returns True if the iAd's placement type matches the current page type, false otherwise
 *          or if pageInformation or iAdInfo is missing
 */
function isIAdFromCurrentPage(objectGraph, pageInformation) {
    const iAdInfo = pageInformation === null || pageInformation === void 0 ? void 0 : pageInformation.iAdInfo;
    if (isNothing(pageInformation) || isNothing(iAdInfo)) {
        return false;
    }
    const pageType = pageInformation.baseFields["pageType"];
    const iAdPlacementType = IAdSearchInformation.placementTypeFromPlacementId(objectGraph, iAdInfo.placementId);
    switch (iAdPlacementType) {
        case "searchLanding":
            return pageType === "SearchLanding";
        case "today":
            return pageType === "Today";
        case "productPageYMAL":
        case "productPageYMALDuringDownload":
            return pageType === "Software" || pageType === "SoftwareBundle";
        default:
            return pageType === "Search";
    }
}
/**
 * Returns a copy of the specified buy parameters enriched with native metrics fields.
 *
 * @param baseBuyParams The buy parameters of an app which have previously been
 * decorated with page metrics. Passing buy parameters that were not decorated with page
 * metrics can result in incorrect search terms being reported.
 * @param adamId The identifier of the app whose buy parameters are being decorated.
 * @param excludeCrossfireAttribution Specifies whether crossfire attribution should be
 * excluded from the decorated buy params.
 * @param nativeMetrics Metrics fields provided by native code.
 * @param osMetrics Metrics fields describing the device's OS provided by native code.
 * @returns A copy of `baseBuyParams` enriched with native metrics fields.
 */
export function addNativeValuesToBuyParams(objectGraph, baseBuyParams, adamId, excludeCrossfireAttribution, isAppInstalled, nativeMetrics, osMetrics) {
    const baseBuyParamsObject = new BuyParameters(baseBuyParams);
    addNativeValuesToBuyParamsObject(objectGraph, baseBuyParamsObject, adamId, excludeCrossfireAttribution, isAppInstalled, nativeMetrics, osMetrics);
    return baseBuyParamsObject.toString();
}
/**
 * Returns a copy of the specified buy parameters enriched with native metrics fields.
 *
 * @param baseBuyParams The buy parameters of an app which have previously been
 * decorated with page metrics. Passing buy parameters that were not decorated with page
 * metrics can result in incorrect search terms being reported.
 * @param adamId The identifier of the app whose buy parameters are being decorated.
 * @param excludeCrossfireAttribution Specifies whether crossfire attribution should be
 * excluded from the decorated buy params.
 * @param nativeMetrics Metrics fields provided by native code.
 * @param osMetrics Metrics fields describing the device's OS provided by native code.
 * @returns A copy of `baseBuyParams` enriched with native metrics fields.
 */
export function addNativeValuesToBuyParamsObject(objectGraph, buyParams, adamId, excludeCrossfireAttribution, isAppInstalled, nativeMetrics, osMetrics) {
    var _a, _b;
    const pageContext = serverData.asString(nativeMetrics, "pageContext");
    buyParams.set("pageContext", pageContext);
    const paymentTopic = objectGraph.props.enabled("paymentTopicFromBag")
        ? objectGraph.bag.metricsPaymentTopic
        : undefined;
    buyParams.set("topic", paymentTopic !== null && paymentTopic !== void 0 ? paymentTopic : objectGraph.bag.metricsTopic);
    metricsPosting.buyDecorator.useNativeValues(nativeMetrics);
    const decoratorParams = metricsPosting.buyDecorator.params;
    for (const key of Object.keys(decoratorParams)) {
        if (key === "prevPage" && isSome(buyParams.get("prevPage"))) {
            // We may have added a `prevPage` param earlier, specifically don't override this value if we have.
            continue;
        }
        const value = serverData.asString(decoratorParams, key);
        buyParams.set(key, value);
    }
    if (!serverData.isNull(osMetrics)) {
        for (const key of Object.keys(osMetrics)) {
            const value = serverData.asString(osMetrics, key);
            buyParams.set(key, value);
            buyParams.set(key, value, null);
        }
    }
    if (!nativeMetrics) {
        // ^^ Is this actually needed?
        buyParams.set("searchTerm", null);
        buyParams.set("platformDisplayStyle", null);
        return;
    }
    const hostApp = serverData.asString(nativeMetrics, "hostApp");
    if (isSome(hostApp) && hostApp.length > 0) {
        buyParams.set("hostApp", hostApp);
    }
    const isContingentOffer = ((_a = buyParams.get("contingentItemId", null)) === null || _a === void 0 ? void 0 : _a.length) > 0;
    const app = serverData.asString(nativeMetrics, "app");
    if (isContingentOffer) {
        // Contingent Offer Streamline buy app install flag
        buyParams.set("app", objectGraph.host.clientIdentifier);
    }
    else if (isSome(app) && app.length > 0) {
        buyParams.set("app", app);
    }
    if (!excludeCrossfireAttribution && !MetricsReferralContext.shared.shouldUseJSReferralData) {
        const extRefUrl = serverData.asString(nativeMetrics, "extRefUrl2");
        const extractedSiriRefApp = metricsUtil.extractSiriRefAppFromRefURL(extRefUrl);
        if (extRefUrl && extractedSiriRefApp) {
            nativeMetrics["refApp"] = extractedSiriRefApp;
        }
        // ^^ Is this actually needed?
        const usageContext = serverData.asString(nativeMetrics, "usageContext");
        if (isSome(usageContext)) {
            switch (usageContext) {
                case "overlay":
                    buyParams.set("hostApp", "com.apple.AppStore.overlay");
                    break;
                case "overlayClip":
                    buyParams.set("hostApp", "com.apple.AppStore.clipOverlay");
                    break;
                default:
                    break;
            }
            buyParams.set("extRefApp2", hostApp, null);
        }
        else {
            const extRefApp2 = serverData.asString(nativeMetrics, "extRefApp2");
            buyParams.set("extRefApp2", extRefApp2, null);
            const extRefUrl2 = serverData.asString(nativeMetrics, "extRefUrl2");
            buyParams.set("extRefUrl2", extRefUrl2, null);
            const extRefAppType = serverData.asString(nativeMetrics, "extRefAppType");
            if (extRefAppType === "clip") {
                buyParams.set("hostApp", "com.apple.AppStore.clipOverlay");
            }
        }
    }
    // we add search terms to the page if the page is for the item we are buying
    const pageId = buyParams.get("pageId");
    const pageType = buyParams.get("pageType");
    const pageIds = (_b = pageId === null || pageId === void 0 ? void 0 : pageId.split("_")) !== null && _b !== void 0 ? _b : [];
    const pageMatchesProduct = pageIds.includes(adamId);
    const isProductPage = pageType === "Software";
    if (!isProductPage || pageMatchesProduct) {
        const searchTerm = metricsUtil.searchTermFromRefURL(serverData.asString(nativeMetrics, "refUrl"));
        if (serverData.isDefinedNonNull(searchTerm)) {
            buyParams.set("searchTerm", searchTerm);
        }
    }
    // Remove ownerDsid from buyParams
    buyParams.set("ownerDsid", null, null);
}
/**
 *
 * @param adamId The identifier of the app whose buy parameters are being decorated.
 * @param buyParams The buy parameters of an app from a Media API response.
 * @param pageInformation The purchase configuration page metrics configuration
 * from an offer action.
 * @param excludeCrossfireAttribution Specifies whether crossfire attribution should be
 * excluded from the decorated buy params.
 * @param targetType The target type that buy occured on
 * @param kind The Kind that buy occured on, if any.
 * @param metricsPlatformDisplayStyle The platform display style from an offer action.
 * @param nativeMetrics Metrics fields provided by native code.
 * @param osMetrics Metrics fields describing the device's OS provided by native code.
 * @returns A copy of `buyParams` decorated with all metrics.
 */
export function addMetricsToBuyParams(objectGraph, adamId, buyParams, pageInformation, excludeCrossfireAttribution, isAppInstalled, targetType, kind, metricsPlatformDisplayStyle, nativeMetrics, osMetrics, productVariantData, inAppEventId, extRefApp2, extRefUrl2) {
    // Future: Build BuyParameters once, instead of creating it per modification.
    const bagMetricsBuyParams = addBagMetricsToBuyParams(objectGraph, buyParams);
    const pageMetricsBuyParams = addPageMetricsToBuyParams(objectGraph, bagMetricsBuyParams, adamId, pageInformation, targetType, kind, metricsPlatformDisplayStyle, productVariantData, inAppEventId, excludeCrossfireAttribution, extRefApp2, extRefUrl2);
    const nativeMetricsBuyParams = addNativeValuesToBuyParams(objectGraph, pageMetricsBuyParams, adamId, excludeCrossfireAttribution, isAppInstalled, nativeMetrics, osMetrics);
    return nativeMetricsBuyParams;
}
/**
 * Keys used for ad-related buy params.
 */
export const adBuyParamKeys = {
    containerId: "mtContainerId",
    placementId: "mtIadPlacementId",
    templateType: "mtIadTemplateType",
};
/**
 * Copy ad-related buy params to the override buy params.
 * Override buy params are used for updated and redownloads, and in those cases we lose iAd download attribution.
 * If the original buy params had ad fields, we should copy them over here.
 * @param originalBuyParamsString The original buy params attached to the offerAction.
 * @param overrideBuyParamsString The override buy params from the purchase.
 * @returns An updated buy params string with any ad-related fields copied over.
 */
export function copyAdBuyParamsToOverrideBuyParams(originalBuyParamsString, overrideBuyParamsString) {
    const originalBuyParams = new BuyParameters(originalBuyParamsString);
    const overrideBuyParams = new BuyParameters(overrideBuyParamsString);
    const originalPlacementId = originalBuyParams.get(adBuyParamKeys.placementId, null);
    if ((originalPlacementId === null || originalPlacementId === void 0 ? void 0 : originalPlacementId.length) > 0 &&
        serverData.isNullOrEmpty(overrideBuyParams.get(adBuyParamKeys.placementId, null))) {
        overrideBuyParams.set(adBuyParamKeys.placementId, originalPlacementId, null);
    }
    const originalContainerId = originalBuyParams.get(adBuyParamKeys.containerId, null);
    if ((originalContainerId === null || originalContainerId === void 0 ? void 0 : originalContainerId.length) > 0 &&
        serverData.isNullOrEmpty(overrideBuyParams.get(adBuyParamKeys.containerId, null))) {
        overrideBuyParams.set(adBuyParamKeys.containerId, originalContainerId, null);
    }
    const originalTemplateType = originalBuyParams.get(adBuyParamKeys.templateType, null);
    if ((originalTemplateType === null || originalTemplateType === void 0 ? void 0 : originalTemplateType.length) > 0 &&
        serverData.isNullOrEmpty(overrideBuyParams.get(adBuyParamKeys.templateType, null))) {
        overrideBuyParams.set(adBuyParamKeys.templateType, originalTemplateType, null);
    }
    return overrideBuyParams.toString();
}
//# sourceMappingURL=buy.js.map