summaryrefslogtreecommitdiff
path: root/node_modules/@jet-app/app-store/tmp/src/common/metrics/builder.js
diff options
context:
space:
mode:
authorrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
committerrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
commitbce557cc2dc767628bed6aac87301a1be7c5431b (patch)
treeb51a051228d01fe3306cd7626d4a96768aadb944 /node_modules/@jet-app/app-store/tmp/src/common/metrics/builder.js
init commit
Diffstat (limited to 'node_modules/@jet-app/app-store/tmp/src/common/metrics/builder.js')
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/metrics/builder.js257
1 files changed, 257 insertions, 0 deletions
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/metrics/builder.js b/node_modules/@jet-app/app-store/tmp/src/common/metrics/builder.js
new file mode 100644
index 0000000..ffb205f
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/metrics/builder.js
@@ -0,0 +1,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 \ No newline at end of file