@levi-gemcommerce/analytics 1.0.0-dev.36 → 1.0.0-dev.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/CardPathAnalysis/CardJourneyAnalysis.d.ts +3 -1
- package/dist/esm/components/CardPathAnalysis/components/PathAnalysisChart.d.ts +1 -0
- package/dist/esm/components/CardPathAnalysis/contexts/PathAnalysisConfigProvider.d.ts +23 -0
- package/dist/esm/components/CardPathAnalysis/contexts/PathAnalysisProvider.d.ts +2 -0
- package/dist/esm/components/CardPathAnalysis/contexts/index.d.ts +1 -0
- package/dist/esm/components/CardPathAnalysis/helpers/pathAnalysis.d.ts +1 -1
- package/dist/esm/gemxql.js +1 -1
- package/dist/esm/gemxql.mjs +1 -1
- package/dist/esm/index.js +361 -465
- package/dist/esm/index.mjs +361 -465
- package/dist/esm/modules/page-analytic/index.d.ts +1 -2
- package/dist/esm/providers/PricingProvider.d.ts +1 -1
- package/dist/esm/providers/index.d.ts +0 -2
- package/dist/esm/types/pricing.d.ts +1 -1
- package/dist/esm/types.js +1 -1
- package/dist/esm/types.mjs +1 -1
- package/dist/style.css +1 -1
- package/dist/umd/esm/components/CardPathAnalysis/CardJourneyAnalysis.d.ts +3 -1
- package/dist/umd/esm/components/CardPathAnalysis/components/PathAnalysisChart.d.ts +1 -0
- package/dist/umd/esm/components/CardPathAnalysis/contexts/PathAnalysisConfigProvider.d.ts +23 -0
- package/dist/umd/esm/components/CardPathAnalysis/contexts/PathAnalysisProvider.d.ts +2 -0
- package/dist/umd/esm/components/CardPathAnalysis/contexts/index.d.ts +1 -0
- package/dist/umd/esm/components/CardPathAnalysis/helpers/pathAnalysis.d.ts +1 -1
- package/dist/umd/esm/modules/page-analytic/index.d.ts +1 -2
- package/dist/umd/esm/providers/PricingProvider.d.ts +1 -1
- package/dist/umd/esm/providers/index.d.ts +0 -2
- package/dist/umd/esm/types/pricing.d.ts +1 -1
- package/dist/umd/index.js +1 -1
- package/package.json +4 -4
package/dist/esm/index.js
CHANGED
|
@@ -13,8 +13,8 @@ import { create } from 'zustand';
|
|
|
13
13
|
import { useQuery } from '@tanstack/react-query';
|
|
14
14
|
import { PolarisVizProvider, LineChart, DonutChart } from '@shopify/polaris-viz';
|
|
15
15
|
import chartStyle from '@shopify/polaris-viz/build/esm/styles.css?url';
|
|
16
|
-
import { unstable_batchedUpdates, createPortal } from 'react-dom';
|
|
17
16
|
import { t as t$1 } from 'i18next';
|
|
17
|
+
import { unstable_batchedUpdates, createPortal } from 'react-dom';
|
|
18
18
|
|
|
19
19
|
var EMetricKey;
|
|
20
20
|
(function (EMetricKey) {
|
|
@@ -170,7 +170,7 @@ var ETrafficSourceType;
|
|
|
170
170
|
*
|
|
171
171
|
* They are duplicated here so the SDK no longer needs to import the host's
|
|
172
172
|
* pricing module directly. The host can import these enums back from
|
|
173
|
-
* `@gem-sdk/analytics/types` to build the value passed to `
|
|
173
|
+
* `@gem-sdk/analytics/types` to build the value passed to `PathAnalysisConfigProvider`,
|
|
174
174
|
* which guarantees the string values stay in sync on both sides.
|
|
175
175
|
*/
|
|
176
176
|
var IPlanKey;
|
|
@@ -1266,45 +1266,6 @@ const MetricChartProvider = ({ children, minHeight = CHART_MIN_HEIGHT, seriesCol
|
|
|
1266
1266
|
}, children: children })] }));
|
|
1267
1267
|
};
|
|
1268
1268
|
|
|
1269
|
-
const DEFAULT_PRICING_CONTEXT = {
|
|
1270
|
-
isLoading: false,
|
|
1271
|
-
activePlanKey: IPlanKey.PAGE_OPT,
|
|
1272
|
-
shopPlanState: IShopPlanState.LOADING_PLAN,
|
|
1273
|
-
isPathAnalysisEnabled: false,
|
|
1274
|
-
onOpenModalPricing: () => { },
|
|
1275
|
-
};
|
|
1276
|
-
const PricingContext = createContext(DEFAULT_PRICING_CONTEXT);
|
|
1277
|
-
const PricingProvider = ({ children, isLoading, activePlanKey, shopPlanState, isPathAnalysisEnabled, onOpenModalPricing, }) => {
|
|
1278
|
-
const value = useMemo(() => ({ isLoading, activePlanKey, shopPlanState, isPathAnalysisEnabled, onOpenModalPricing }), [isLoading, activePlanKey, shopPlanState, isPathAnalysisEnabled, onOpenModalPricing]);
|
|
1279
|
-
return jsx(PricingContext.Provider, { value: value, children: children });
|
|
1280
|
-
};
|
|
1281
|
-
const usePricingContext = () => useContext(PricingContext);
|
|
1282
|
-
/**
|
|
1283
|
-
* The hooks below mirror the host's `~/modules/pricing` API so existing SDK
|
|
1284
|
-
* components only need to swap their import path. Each one reads from the
|
|
1285
|
-
* injected `PricingContext`.
|
|
1286
|
-
*/
|
|
1287
|
-
const usePricingPlanActive = () => {
|
|
1288
|
-
const { isLoading, activePlanKey } = usePricingContext();
|
|
1289
|
-
return { isLoading, activePlanKey };
|
|
1290
|
-
};
|
|
1291
|
-
const usePricingPlanActiveState = () => {
|
|
1292
|
-
const { shopPlanState } = usePricingContext();
|
|
1293
|
-
return { shopPlanState };
|
|
1294
|
-
};
|
|
1295
|
-
/**
|
|
1296
|
-
* `planKey` is kept for API compatibility with the host hook. The SDK only ever
|
|
1297
|
-
* checks the active plan, so the enabled flag is taken straight from context.
|
|
1298
|
-
*/
|
|
1299
|
-
const useLimitPathAnalysis = (_props) => {
|
|
1300
|
-
const { isPathAnalysisEnabled } = usePricingContext();
|
|
1301
|
-
return { isEnabled: isPathAnalysisEnabled };
|
|
1302
|
-
};
|
|
1303
|
-
const usePricingModalMonitor = () => {
|
|
1304
|
-
const { onOpenModalPricing } = usePricingContext();
|
|
1305
|
-
return { onOpenModalPricing };
|
|
1306
|
-
};
|
|
1307
|
-
|
|
1308
1269
|
const useEnhancedEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
|
|
1309
1270
|
|
|
1310
1271
|
const NONE_VALUE = 'None';
|
|
@@ -2963,19 +2924,24 @@ const GTimePicker = (props) => {
|
|
|
2963
2924
|
return (jsxs(InlineStack, { gap: "200", children: [jsx(MainTimePicker, { ...timePickerProps }), isCompare && (jsx(CompareTimePicker, { rangeAddition: timePickerProps.rangeAddition, popoverProps: timePickerProps.popoverProps }))] }));
|
|
2964
2925
|
};
|
|
2965
2926
|
|
|
2966
|
-
const
|
|
2967
|
-
|
|
2927
|
+
const DEFAULT_CONFIG = {
|
|
2928
|
+
pricing: {
|
|
2929
|
+
isLoading: false,
|
|
2930
|
+
isPathAnalysisEnabled: false,
|
|
2931
|
+
onOpenModalPricing: () => { },
|
|
2932
|
+
},
|
|
2933
|
+
heatmap: {
|
|
2934
|
+
isEnabledV1: false,
|
|
2935
|
+
isEnabledV2: false,
|
|
2936
|
+
onView: () => { },
|
|
2937
|
+
},
|
|
2968
2938
|
};
|
|
2969
|
-
|
|
2970
|
-
const
|
|
2971
|
-
value
|
|
2972
|
-
});
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
});
|
|
2976
|
-
const getTotalSessionCompletedCheckoutMetric = ({ metric }) => ({
|
|
2977
|
-
value: metric?.totalSessionsThatCompletedCheckout ?? undefined,
|
|
2978
|
-
});
|
|
2939
|
+
const PathAnalysisConfigContext = createContext(DEFAULT_CONFIG);
|
|
2940
|
+
const PathAnalysisConfigProvider = ({ children, pricing, heatmap }) => {
|
|
2941
|
+
const value = useMemo(() => ({ pricing, heatmap }), [pricing, heatmap]);
|
|
2942
|
+
return jsx(PathAnalysisConfigContext.Provider, { value: value, children: children });
|
|
2943
|
+
};
|
|
2944
|
+
const usePathAnalysisConfig = () => useContext(PathAnalysisConfigContext);
|
|
2979
2945
|
|
|
2980
2946
|
var IPAMetricKey;
|
|
2981
2947
|
(function (IPAMetricKey) {
|
|
@@ -3004,10 +2970,31 @@ var IPAMetricKey;
|
|
|
3004
2970
|
|
|
3005
2971
|
const formatMetricByFormatter = (_params) => '';
|
|
3006
2972
|
const PA_METRIC_TOOLTIP = {};
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
}
|
|
2973
|
+
|
|
2974
|
+
const METRICS_COLUMNS = {
|
|
2975
|
+
[IPAMetricKey.PAGE_SESSIONS]: { label: 'Sessions' },
|
|
2976
|
+
[IPAMetricKey.PAGE_BR]: { label: 'Bounce rate' },
|
|
2977
|
+
[IPAMetricKey.PAGE_CTR]: { label: 'Click-through rate' },
|
|
2978
|
+
[IPAMetricKey.PAGE_CR]: { label: 'Conversion rate' },
|
|
2979
|
+
[IPAMetricKey.PAGE_VISITORS]: { label: 'Visitors' },
|
|
2980
|
+
[IPAMetricKey.PAGE_AVG_TIME]: { label: 'Avg time on page' },
|
|
2981
|
+
[IPAMetricKey.PAGE_VIEWS]: { label: 'Pageviews' },
|
|
2982
|
+
[IPAMetricKey.PAGE_REVENUE]: { label: 'Revenue' },
|
|
2983
|
+
[IPAMetricKey.PAGE_ADDED_TO_CART]: { label: 'Added to cart' },
|
|
2984
|
+
[IPAMetricKey.PAGE_REACHED_CHECKOUT]: { label: 'Sessions that reached checkout' },
|
|
2985
|
+
[IPAMetricKey.PAGE_COMPLETE_CHECKOUT]: { label: 'Sessions that completed checkout' },
|
|
2986
|
+
[IPAMetricKey.PAGE_RPV]: { label: 'Revenue per visitor' },
|
|
2987
|
+
[IPAMetricKey.PAGE_CART_ADDITION]: { label: 'Sessions with cart additions' },
|
|
2988
|
+
[IPAMetricKey.PAGE_ADD_TO_CART_RATE]: { label: 'Add to cart rate' },
|
|
2989
|
+
[IPAMetricKey.PAGE_ORDERS]: { label: 'Orders' },
|
|
2990
|
+
[IPAMetricKey.PAGE_AOV]: { label: 'Average order value' },
|
|
2991
|
+
[IPAMetricKey.PAGE_SESSIONS_BY_VISITOR]: { label: 'Visitor by type' },
|
|
2992
|
+
[IPAMetricKey.PAGE_SESSIONS_BY_TRAFFIC]: { label: 'Sessions by traffic source' },
|
|
2993
|
+
[IPAMetricKey.PAGE_PATH_ANALYSIS]: { label: 'Journey analysis' },
|
|
2994
|
+
[IPAMetricKey.PAGE_SESSIONS_BY_DEVICE]: { label: 'Sessions by device type' },
|
|
2995
|
+
[IPAMetricKey.PAGE_NEW_RETURNING_CUSTOMER]: { label: 'New vs returning visitors' },
|
|
2996
|
+
};
|
|
2997
|
+
const PAGE_ANALYTIC_MAPPING = Object.fromEntries(Object.values(IPAMetricKey).map((key) => [key, { heading: { title: METRICS_COLUMNS[key].label } }]));
|
|
3011
2998
|
|
|
3012
2999
|
const removeDuplicates = (data, keys) => {
|
|
3013
3000
|
if (!Array.isArray(data))
|
|
@@ -3036,10 +3023,6 @@ const buildTree = (items) => {
|
|
|
3036
3023
|
return tree;
|
|
3037
3024
|
};
|
|
3038
3025
|
|
|
3039
|
-
const SHOPIFY_PAGE_TYPE_KEY = 'shopify_page_type';
|
|
3040
|
-
const METRICS_COLUMNS = {};
|
|
3041
|
-
const PAGE_ANALYTIC_MAPPING = {};
|
|
3042
|
-
|
|
3043
3026
|
const processPathAnalytics = (analyticsData, locationPath) => {
|
|
3044
3027
|
if (!analyticsData)
|
|
3045
3028
|
return undefined;
|
|
@@ -3104,6 +3087,49 @@ const getFunnelChartTooltip = (data) => {
|
|
|
3104
3087
|
return baseInfo.concat(metricInfo);
|
|
3105
3088
|
};
|
|
3106
3089
|
|
|
3090
|
+
const usePathAnalysisStore = create()((set) => ({
|
|
3091
|
+
firstLevelLocationPath: undefined,
|
|
3092
|
+
setFirstLevelLocationPath: (firstLevelLocationPath) => set({ firstLevelLocationPath }),
|
|
3093
|
+
}));
|
|
3094
|
+
|
|
3095
|
+
var IVariantType;
|
|
3096
|
+
(function (IVariantType) {
|
|
3097
|
+
IVariantType["VARIANT_A"] = "A";
|
|
3098
|
+
IVariantType["VARIANT_B"] = "B";
|
|
3099
|
+
})(IVariantType || (IVariantType = {}));
|
|
3100
|
+
const usePathAnalysisCampaignStore = create()((set) => ({
|
|
3101
|
+
selectedVariantType: IVariantType.VARIANT_A,
|
|
3102
|
+
setSelectedVariantType: (selectedVariantType) => set({ selectedVariantType }),
|
|
3103
|
+
}));
|
|
3104
|
+
|
|
3105
|
+
const useFunnelChartStore = create()((set, get) => ({
|
|
3106
|
+
cachedFunnelChartData: {},
|
|
3107
|
+
setCachedFunnelChartData: (key, funnelChartData) => {
|
|
3108
|
+
const currentFunnelChartData = deepCopy(get().cachedFunnelChartData);
|
|
3109
|
+
currentFunnelChartData[key] = {
|
|
3110
|
+
...currentFunnelChartData[key],
|
|
3111
|
+
...funnelChartData,
|
|
3112
|
+
};
|
|
3113
|
+
set({ cachedFunnelChartData: currentFunnelChartData });
|
|
3114
|
+
},
|
|
3115
|
+
resetData: () => {
|
|
3116
|
+
set({ cachedFunnelChartData: {} });
|
|
3117
|
+
},
|
|
3118
|
+
}));
|
|
3119
|
+
|
|
3120
|
+
const MAX_FUNNEL_ADDITIONAL_LEVEL = 3;
|
|
3121
|
+
const FINAL_FUNNEL_FIXED_LEVEL = 3;
|
|
3122
|
+
|
|
3123
|
+
const getTotalSessionWithCartAdditionMetric = ({ metric }) => ({
|
|
3124
|
+
value: metric?.totalSessionsWithCartAdditions ?? undefined,
|
|
3125
|
+
});
|
|
3126
|
+
const getTotalSessionReachedCheckoutMetric = ({ metric }) => ({
|
|
3127
|
+
value: metric?.totalSessionsThatReachedCheckout ?? undefined,
|
|
3128
|
+
});
|
|
3129
|
+
const getTotalSessionCompletedCheckoutMetric = ({ metric }) => ({
|
|
3130
|
+
value: metric?.totalSessionsThatCompletedCheckout ?? undefined,
|
|
3131
|
+
});
|
|
3132
|
+
|
|
3107
3133
|
const calculateFunnelTrendChange = ({ currentValue, previousValue, }) => {
|
|
3108
3134
|
const shouldSkipComparison = typeof currentValue !== 'number' || typeof previousValue !== 'number' || previousValue === 0;
|
|
3109
3135
|
if (shouldSkipComparison)
|
|
@@ -3178,67 +3204,6 @@ const calculateConversionFunnelTrends = ({ pageWithMetric, previousPathAnalytics
|
|
|
3178
3204
|
return trends;
|
|
3179
3205
|
};
|
|
3180
3206
|
|
|
3181
|
-
const useHeatmapModalMonitor = () => ({
|
|
3182
|
-
onOpenModal: () => { },
|
|
3183
|
-
});
|
|
3184
|
-
|
|
3185
|
-
var EHeatmapBaseFilterType;
|
|
3186
|
-
(function (EHeatmapBaseFilterType) {
|
|
3187
|
-
EHeatmapBaseFilterType["DATE_RANGE"] = "date_range";
|
|
3188
|
-
EHeatmapBaseFilterType["URL_PATH"] = "url_path";
|
|
3189
|
-
EHeatmapBaseFilterType["ANALYTIC_MODE"] = "analytic_mode";
|
|
3190
|
-
EHeatmapBaseFilterType["OPERATOR"] = "operator";
|
|
3191
|
-
})(EHeatmapBaseFilterType || (EHeatmapBaseFilterType = {}));
|
|
3192
|
-
var EHeatmapFilterType;
|
|
3193
|
-
(function (EHeatmapFilterType) {
|
|
3194
|
-
EHeatmapFilterType["VISITOR_JOURNEY"] = "visitor_journey";
|
|
3195
|
-
EHeatmapFilterType["MARKET"] = "market";
|
|
3196
|
-
EHeatmapFilterType["VISITOR_TYPE"] = "visitor_type";
|
|
3197
|
-
EHeatmapFilterType["TRAFFIC_SOURCE"] = "traffic_source";
|
|
3198
|
-
EHeatmapFilterType["PURCHASE_TYPE"] = "purchase_type";
|
|
3199
|
-
EHeatmapFilterType["TIME_ON_PAGE"] = "time_on_page";
|
|
3200
|
-
EHeatmapFilterType["ORDER_VALUE"] = "order_value";
|
|
3201
|
-
EHeatmapFilterType["CAMPAIGN"] = "campaign_id";
|
|
3202
|
-
EHeatmapFilterType["REFERRAL_SOURCE"] = "referral_source";
|
|
3203
|
-
})(EHeatmapFilterType || (EHeatmapFilterType = {}));
|
|
3204
|
-
|
|
3205
|
-
const useHeatmapFilterBuildParams = () => ({
|
|
3206
|
-
buildSearchParams: () => ({ toString: () => '' }),
|
|
3207
|
-
});
|
|
3208
|
-
|
|
3209
|
-
const usePathAnalysisStore = create()((set) => ({
|
|
3210
|
-
firstLevelLocationPath: undefined,
|
|
3211
|
-
setFirstLevelLocationPath: (firstLevelLocationPath) => set({ firstLevelLocationPath }),
|
|
3212
|
-
}));
|
|
3213
|
-
|
|
3214
|
-
var IVariantType;
|
|
3215
|
-
(function (IVariantType) {
|
|
3216
|
-
IVariantType["VARIANT_A"] = "A";
|
|
3217
|
-
IVariantType["VARIANT_B"] = "B";
|
|
3218
|
-
})(IVariantType || (IVariantType = {}));
|
|
3219
|
-
const usePathAnalysisCampaignStore = create()((set) => ({
|
|
3220
|
-
selectedVariantType: IVariantType.VARIANT_A,
|
|
3221
|
-
setSelectedVariantType: (selectedVariantType) => set({ selectedVariantType }),
|
|
3222
|
-
}));
|
|
3223
|
-
|
|
3224
|
-
const useFunnelChartStore = create()((set, get) => ({
|
|
3225
|
-
cachedFunnelChartData: {},
|
|
3226
|
-
setCachedFunnelChartData: (key, funnelChartData) => {
|
|
3227
|
-
const currentFunnelChartData = deepCopy(get().cachedFunnelChartData);
|
|
3228
|
-
currentFunnelChartData[key] = {
|
|
3229
|
-
...currentFunnelChartData[key],
|
|
3230
|
-
...funnelChartData,
|
|
3231
|
-
};
|
|
3232
|
-
set({ cachedFunnelChartData: currentFunnelChartData });
|
|
3233
|
-
},
|
|
3234
|
-
resetData: () => {
|
|
3235
|
-
set({ cachedFunnelChartData: {} });
|
|
3236
|
-
},
|
|
3237
|
-
}));
|
|
3238
|
-
|
|
3239
|
-
const MAX_FUNNEL_ADDITIONAL_LEVEL = 3;
|
|
3240
|
-
const FINAL_FUNNEL_FIXED_LEVEL = 3;
|
|
3241
|
-
|
|
3242
3207
|
const usePathAnalysisFunnel = ({ pathAnalytics, pathAnalysisCacheKey, dataFirstLevels, locationPath, }) => {
|
|
3243
3208
|
const setFirstLevelLocationPath = usePathAnalysisStore((state) => state.setFirstLevelLocationPath);
|
|
3244
3209
|
const firstLevelLocationPath = usePathAnalysisStore((state) => state.firstLevelLocationPath) || locationPath;
|
|
@@ -3378,338 +3343,63 @@ const usePathAnalyticsMerger = ({ pathAnalytics, dataFirstLevels }) => {
|
|
|
3378
3343
|
}
|
|
3379
3344
|
return acc;
|
|
3380
3345
|
}, {
|
|
3381
|
-
firstLevelData: {},
|
|
3382
|
-
otherLevelsData: [],
|
|
3383
|
-
});
|
|
3384
|
-
}, [pathAnalytics]);
|
|
3385
|
-
const processedPathAnalytics = useMemo(() => {
|
|
3386
|
-
if (!dataFirstLevels)
|
|
3387
|
-
return pathAnalytics;
|
|
3388
|
-
const mergedFirstLevels = dataFirstLevels.map((item) => {
|
|
3389
|
-
const firstLevelDataItem = firstLevelData[item.locationPath];
|
|
3390
|
-
if (!firstLevelDataItem) {
|
|
3391
|
-
return item;
|
|
3392
|
-
}
|
|
3393
|
-
return firstLevelDataItem;
|
|
3394
|
-
});
|
|
3395
|
-
return [...mergedFirstLevels, ...otherLevelsData];
|
|
3396
|
-
}, [pathAnalytics, dataFirstLevels, firstLevelData, otherLevelsData]);
|
|
3397
|
-
return { processedPathAnalytics };
|
|
3398
|
-
};
|
|
3399
|
-
|
|
3400
|
-
const PathAnalysisContext = createContext(undefined);
|
|
3401
|
-
const PathAnalysisProvider = (props) => {
|
|
3402
|
-
const { children, campaignID, campaignGroupID, campaignVariantID, campaignVersionID, mode, campaignPathsData, analyticsData, } = props;
|
|
3403
|
-
const dataFirstLevels = campaignPathsData?.paths;
|
|
3404
|
-
const isFetchingFirstLevelPaths = campaignPathsData?.isLoading ?? false;
|
|
3405
|
-
const pathAnalytics = analyticsData?.pathAnalytics ?? [];
|
|
3406
|
-
const previousPathAnalyticsMap = analyticsData?.previousPathAnalyticsMap ?? {};
|
|
3407
|
-
const isLoadingMetric = analyticsData?.isLoading ?? false;
|
|
3408
|
-
const locationPath = analyticsData?.locationPath;
|
|
3409
|
-
const
|
|
3410
|
-
const
|
|
3411
|
-
const
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
}
|
|
3437
|
-
|
|
3438
|
-
const buildJourneyPage = (page, index, { heatmapLevel, campaignData }) => ({
|
|
3439
|
-
id: page.id,
|
|
3440
|
-
path: page.locationPath || '',
|
|
3441
|
-
level: index + 1,
|
|
3442
|
-
isHeatmap: index === heatmapLevel,
|
|
3443
|
-
...(heatmapLevel > 0 && index === 0 && campaignData && { subFilter: { campaignData } }),
|
|
3444
|
-
});
|
|
3445
|
-
const usePathAnalysisHeatmap = () => {
|
|
3446
|
-
const selectedVariantType = usePathAnalysisCampaignStore((state) => state.selectedVariantType);
|
|
3447
|
-
const { dateTimePicked } = useMetricsTimeFilter();
|
|
3448
|
-
const { mode, campaignID, campaignVariantID, campaignGroupID } = usePathAnalysisContext();
|
|
3449
|
-
const { onOpenModal } = useHeatmapModalMonitor();
|
|
3450
|
-
const { buildSearchParams } = useHeatmapFilterBuildParams();
|
|
3451
|
-
const handleViewHeatmap = useCallback((level, pages) => {
|
|
3452
|
-
const levelPages = pages.slice(0, level + 1);
|
|
3453
|
-
const clickedPage = levelPages[level];
|
|
3454
|
-
if (!clickedPage)
|
|
3455
|
-
return;
|
|
3456
|
-
const campaignData = campaignID
|
|
3457
|
-
? {
|
|
3458
|
-
campaignId: campaignID,
|
|
3459
|
-
campaignGroupId: campaignGroupID,
|
|
3460
|
-
campaignVariantId: campaignVariantID || '',
|
|
3461
|
-
campaignVariantType: selectedVariantType,
|
|
3462
|
-
}
|
|
3463
|
-
: undefined;
|
|
3464
|
-
const pageType = clickedPage.pageType;
|
|
3465
|
-
const locationPath = clickedPage.locationPath || '';
|
|
3466
|
-
const isViewFirstLevel = level === 0;
|
|
3467
|
-
const visitorJourney = {
|
|
3468
|
-
value: levelPages.map((page, index) => buildJourneyPage(page, index, { heatmapLevel: level, campaignData })),
|
|
3469
|
-
};
|
|
3470
|
-
const data = buildSearchParams({
|
|
3471
|
-
[EHeatmapFilterType.VISITOR_JOURNEY]: visitorJourney,
|
|
3472
|
-
...(isViewFirstLevel && campaignData && { [EHeatmapFilterType.CAMPAIGN]: { value: campaignData } }),
|
|
3473
|
-
}, {
|
|
3474
|
-
[EHeatmapBaseFilterType.ANALYTIC_MODE]: { value: mode },
|
|
3475
|
-
[EHeatmapBaseFilterType.DATE_RANGE]: { value: dateTimePicked },
|
|
3476
|
-
[EHeatmapBaseFilterType.URL_PATH]: {
|
|
3477
|
-
value: { path: locationPath, pageType },
|
|
3478
|
-
},
|
|
3479
|
-
});
|
|
3480
|
-
onOpenModal(data.toString());
|
|
3481
|
-
}, [
|
|
3482
|
-
mode,
|
|
3483
|
-
campaignID,
|
|
3484
|
-
dateTimePicked,
|
|
3485
|
-
campaignGroupID,
|
|
3486
|
-
campaignVariantID,
|
|
3487
|
-
selectedVariantType,
|
|
3488
|
-
onOpenModal,
|
|
3489
|
-
buildSearchParams,
|
|
3490
|
-
]);
|
|
3491
|
-
return {
|
|
3492
|
-
handleViewHeatmap,
|
|
3493
|
-
};
|
|
3494
|
-
};
|
|
3495
|
-
|
|
3496
|
-
const useConvertMoneyByCurrency = () => ({
|
|
3497
|
-
getTextPrice: () => '',
|
|
3498
|
-
});
|
|
3499
|
-
|
|
3500
|
-
const useFeatureFlagChecker = () => ({
|
|
3501
|
-
isEnabledHeatmapV1: false,
|
|
3502
|
-
isEnabledHeatmapV2: false,
|
|
3503
|
-
});
|
|
3504
|
-
|
|
3505
|
-
// Framework-agnostic replacement for @remix-run/react useSearchParams.
|
|
3506
|
-
// Returns a read-only URLSearchParams from window.location.search so the SDK
|
|
3507
|
-
// works outside of a Remix/React Router context (e.g. Next.js, plain React).
|
|
3508
|
-
const useSearchParams = () => {
|
|
3509
|
-
const params = typeof window !== 'undefined' ? new URLSearchParams(window.location.search) : new URLSearchParams();
|
|
3510
|
-
return [params];
|
|
3511
|
-
};
|
|
3512
|
-
|
|
3513
|
-
const FUNNEL_NAME = 'Conversion';
|
|
3514
|
-
// Checkout pages don't support heatmap viewing
|
|
3515
|
-
const NON_HEATMAP_PAGE_TYPES = new Set([TemplateType.CHECKOUT]);
|
|
3516
|
-
const usePathAnalysisChart = () => {
|
|
3517
|
-
const [searchParams] = useSearchParams();
|
|
3518
|
-
const { t } = useTranslation();
|
|
3519
|
-
const { getTextPrice } = useConvertMoneyByCurrency();
|
|
3520
|
-
const { handleViewHeatmap } = usePathAnalysisHeatmap();
|
|
3521
|
-
const shopifyPageType = searchParams.get(SHOPIFY_PAGE_TYPE_KEY);
|
|
3522
|
-
const { pageWithMetric, nextLevelPages, dynamicLevels, previousPathAnalyticsMap, handleAddNextLevel, handleChangeLevel, getPagesByParentID, handleDeleteLevel, } = usePathAnalysisContext();
|
|
3523
|
-
const orderedPages = useMemo(() => [pageWithMetric, ...dynamicLevels].filter(Boolean), [pageWithMetric, dynamicLevels]);
|
|
3524
|
-
const { isEnabledHeatmapV1, isEnabledHeatmapV2 } = useFeatureFlagChecker();
|
|
3525
|
-
const chartTooltipPrimaryAction = useMemo(() => {
|
|
3526
|
-
if (!isEnabledHeatmapV1)
|
|
3527
|
-
return undefined;
|
|
3528
|
-
return {
|
|
3529
|
-
content: t('View heatmap'),
|
|
3530
|
-
onClick: (item) => {
|
|
3531
|
-
if (!item?.id)
|
|
3532
|
-
return;
|
|
3533
|
-
const level = orderedPages.findIndex((page) => page?.id === item.id);
|
|
3534
|
-
if (level === -1)
|
|
3535
|
-
return;
|
|
3536
|
-
handleViewHeatmap(level, orderedPages);
|
|
3537
|
-
},
|
|
3538
|
-
};
|
|
3539
|
-
}, [handleViewHeatmap, orderedPages, t, isEnabledHeatmapV1]);
|
|
3540
|
-
const lengthDisplayedLevels = dynamicLevels.length;
|
|
3541
|
-
const isDisabledAddICon = !nextLevelPages.length || lengthDisplayedLevels >= MAX_FUNNEL_ADDITIONAL_LEVEL;
|
|
3542
|
-
const lastLevel = useMemo(() => {
|
|
3543
|
-
return dynamicLevels[dynamicLevels.length - 1] || pageWithMetric;
|
|
3544
|
-
}, [dynamicLevels, pageWithMetric]);
|
|
3545
|
-
const getTooltipAction = useCallback((pageType) => {
|
|
3546
|
-
if (pageType && NON_HEATMAP_PAGE_TYPES.has(pageType))
|
|
3547
|
-
return undefined;
|
|
3548
|
-
return chartTooltipPrimaryAction;
|
|
3549
|
-
}, [chartTooltipPrimaryAction]);
|
|
3550
|
-
const onDeleteFunnel = useCallback((id) => {
|
|
3551
|
-
handleDeleteLevel(id);
|
|
3552
|
-
}, [handleDeleteLevel]);
|
|
3553
|
-
const getConversionFunnelData = useCallback((item) => {
|
|
3554
|
-
const metric = item?.metric;
|
|
3555
|
-
const totalAddedToCart = getTotalSessionWithCartAdditionMetric({ metric }).value;
|
|
3556
|
-
const totalReachedCheckout = getTotalSessionReachedCheckoutMetric({ metric }).value;
|
|
3557
|
-
const totalCompletedCheckout = getTotalSessionCompletedCheckoutMetric({ metric }).value;
|
|
3558
|
-
return [
|
|
3559
|
-
{
|
|
3560
|
-
value: Number(totalAddedToCart ?? 0),
|
|
3561
|
-
key: METRICS_COLUMNS[IPAMetricKey.PAGE_ADDED_TO_CART]?.label ?? t('Added to cart'),
|
|
3562
|
-
labelTooltip: PA_METRIC_TOOLTIP[IPAMetricKey.PAGE_CART_ADDITION],
|
|
3563
|
-
},
|
|
3564
|
-
{
|
|
3565
|
-
value: Number(totalReachedCheckout ?? 0),
|
|
3566
|
-
key: t('Reached checkout'),
|
|
3567
|
-
labelTooltip: PA_METRIC_TOOLTIP[IPAMetricKey.PAGE_REACHED_CHECKOUT],
|
|
3568
|
-
},
|
|
3569
|
-
{
|
|
3570
|
-
value: Number(totalCompletedCheckout ?? 0),
|
|
3571
|
-
key: t('Completed checkout'),
|
|
3572
|
-
labelTooltip: PA_METRIC_TOOLTIP[IPAMetricKey.PAGE_COMPLETE_CHECKOUT],
|
|
3573
|
-
},
|
|
3574
|
-
];
|
|
3575
|
-
}, [t]);
|
|
3576
|
-
const listFunnelDataMiddle = useMemo(() => dynamicLevels.reduce((acc, item) => {
|
|
3577
|
-
const key = parseTemplateType(item?.pageType) + `-${item.id}` || 'unknown';
|
|
3578
|
-
// Current data
|
|
3579
|
-
acc.currentData.push({
|
|
3580
|
-
value: item.metric?.totalSessions || 0,
|
|
3581
|
-
key,
|
|
3582
|
-
parentID: item.parentID,
|
|
3583
|
-
id: item.id,
|
|
3584
|
-
chartTooltip: getFunnelChartTooltip({
|
|
3585
|
-
page: item,
|
|
3586
|
-
getTextPrice,
|
|
3587
|
-
}),
|
|
3588
|
-
chartTooltipPrimaryAction: isEnabledHeatmapV2 ? getTooltipAction(item?.pageType ?? undefined) : undefined,
|
|
3589
|
-
secondaryActions: [
|
|
3590
|
-
{
|
|
3591
|
-
onAction: () => onDeleteFunnel(item.id),
|
|
3592
|
-
icon: SvgDeleteIcon,
|
|
3593
|
-
},
|
|
3594
|
-
],
|
|
3595
|
-
title: item.pageTitle ?? undefined,
|
|
3596
|
-
});
|
|
3597
|
-
// Previous data
|
|
3598
|
-
acc.previousData.push({
|
|
3599
|
-
value: previousPathAnalyticsMap[item.id]?.metric?.totalSessions || 0,
|
|
3600
|
-
key,
|
|
3601
|
-
title: item.pageTitle ?? undefined,
|
|
3602
|
-
});
|
|
3603
|
-
return acc;
|
|
3604
|
-
}, { currentData: [], previousData: [] }), [dynamicLevels, previousPathAnalyticsMap, onDeleteFunnel, getTextPrice, getTooltipAction, isEnabledHeatmapV2]);
|
|
3605
|
-
const lastLevelPreviousData = previousPathAnalyticsMap[lastLevel?.id ?? ''];
|
|
3606
|
-
const funnelData = useMemo(() => {
|
|
3607
|
-
const firstLevelKey = pageWithMetric?.pageTitle ||
|
|
3608
|
-
parseTemplateType(pageWithMetric?.pageType ?? shopifyPageType) ||
|
|
3609
|
-
'unknown';
|
|
3610
|
-
return [
|
|
3611
|
-
{
|
|
3612
|
-
data: [
|
|
3613
|
-
{
|
|
3614
|
-
value: pageWithMetric?.metric?.totalSessions || 0,
|
|
3615
|
-
key: firstLevelKey,
|
|
3616
|
-
title: pageWithMetric?.pageTitle,
|
|
3617
|
-
id: pageWithMetric?.id,
|
|
3618
|
-
chartTooltip: getFunnelChartTooltip({ page: pageWithMetric, getTextPrice }),
|
|
3619
|
-
chartTooltipPrimaryAction: getTooltipAction(pageWithMetric?.pageType ?? undefined),
|
|
3620
|
-
},
|
|
3621
|
-
...listFunnelDataMiddle.currentData,
|
|
3622
|
-
...getConversionFunnelData(lastLevel),
|
|
3623
|
-
],
|
|
3624
|
-
name: FUNNEL_NAME,
|
|
3625
|
-
metadata: {
|
|
3626
|
-
trends: calculateConversionFunnelTrends({
|
|
3627
|
-
pageWithMetric,
|
|
3628
|
-
previousPathAnalyticsMap,
|
|
3629
|
-
dynamicLevels,
|
|
3630
|
-
}),
|
|
3631
|
-
},
|
|
3632
|
-
},
|
|
3633
|
-
{
|
|
3634
|
-
name: FUNNEL_NAME,
|
|
3635
|
-
data: [
|
|
3636
|
-
{
|
|
3637
|
-
value: previousPathAnalyticsMap[pageWithMetric?.id || '']?.metric?.totalSessions || 0,
|
|
3638
|
-
key: firstLevelKey,
|
|
3639
|
-
},
|
|
3640
|
-
...listFunnelDataMiddle.previousData,
|
|
3641
|
-
...getConversionFunnelData(lastLevelPreviousData),
|
|
3642
|
-
],
|
|
3643
|
-
isComparison: true,
|
|
3644
|
-
isEmptyData: !lastLevelPreviousData || lastLevelPreviousData.metric?.totalSessions === 0,
|
|
3645
|
-
},
|
|
3646
|
-
];
|
|
3647
|
-
}, [
|
|
3648
|
-
dynamicLevels,
|
|
3649
|
-
pageWithMetric,
|
|
3650
|
-
shopifyPageType,
|
|
3651
|
-
getTextPrice,
|
|
3652
|
-
previousPathAnalyticsMap,
|
|
3653
|
-
listFunnelDataMiddle,
|
|
3654
|
-
getConversionFunnelData,
|
|
3655
|
-
lastLevel,
|
|
3656
|
-
lastLevelPreviousData,
|
|
3657
|
-
getTooltipAction,
|
|
3658
|
-
]);
|
|
3659
|
-
const formatFunnelSelection = (item) => {
|
|
3660
|
-
const childrenSessions = item.metric?.totalSessions || 0;
|
|
3661
|
-
return {
|
|
3662
|
-
id: item.id,
|
|
3663
|
-
title: item.pageTitle || parseTemplateType(item.pageType),
|
|
3664
|
-
path: item.locationPath ?? undefined,
|
|
3665
|
-
percentage: numberWithCommas(childrenSessions.toString()),
|
|
3666
|
-
parentID: item.parentID,
|
|
3667
|
-
};
|
|
3668
|
-
};
|
|
3669
|
-
const sortByPercentage = (a, b) => {
|
|
3670
|
-
const numericPattern = /[^0-9.-]/g;
|
|
3671
|
-
const aPercentage = Number(a.percentage.replace(numericPattern, ''));
|
|
3672
|
-
const bPercentage = Number(b.percentage.replace(numericPattern, ''));
|
|
3673
|
-
return bPercentage - aPercentage;
|
|
3674
|
-
};
|
|
3675
|
-
// const sortByTitle = (a: IFunnelSelectionItem, b: IFunnelSelectionItem) => {
|
|
3676
|
-
// const aTitle = a.title || '';
|
|
3677
|
-
// const bTitle = b.title || '';
|
|
3678
|
-
// return aTitle.localeCompare(bTitle);
|
|
3679
|
-
// };
|
|
3680
|
-
//list funnel selection to add new funnel
|
|
3681
|
-
const listFunnelSelection = useMemo(() => {
|
|
3682
|
-
if (!nextLevelPages)
|
|
3683
|
-
return [];
|
|
3684
|
-
return nextLevelPages.map(formatFunnelSelection).sort(sortByPercentage);
|
|
3685
|
-
}, [nextLevelPages]);
|
|
3686
|
-
//list funnel selection to change funnel
|
|
3687
|
-
const getListFunnelByID = (data) => {
|
|
3688
|
-
const { level, parentID } = data;
|
|
3689
|
-
const availableChildPages = getPagesByParentID({ level, parentID });
|
|
3690
|
-
// if (level === 0) {
|
|
3691
|
-
// return availableChildPages.map(formatFunnelSelection).sort(sortByTitle);
|
|
3692
|
-
// }
|
|
3693
|
-
return availableChildPages.map(formatFunnelSelection).sort(sortByPercentage);
|
|
3694
|
-
};
|
|
3695
|
-
const onAddNextFunnel = (id) => {
|
|
3696
|
-
handleAddNextLevel(id);
|
|
3697
|
-
};
|
|
3698
|
-
const onChangeFunnel = (data) => {
|
|
3699
|
-
if (!data.selectedID)
|
|
3700
|
-
return;
|
|
3701
|
-
handleChangeLevel(data);
|
|
3702
|
-
};
|
|
3703
|
-
return {
|
|
3704
|
-
lengthDisplayedLevels,
|
|
3705
|
-
listFunnelSelection,
|
|
3706
|
-
isDisabledAddICon,
|
|
3707
|
-
funnelData,
|
|
3708
|
-
onDeleteFunnel,
|
|
3709
|
-
onAddNextFunnel,
|
|
3710
|
-
onChangeFunnel,
|
|
3711
|
-
getListFunnelByID,
|
|
3712
|
-
};
|
|
3346
|
+
firstLevelData: {},
|
|
3347
|
+
otherLevelsData: [],
|
|
3348
|
+
});
|
|
3349
|
+
}, [pathAnalytics]);
|
|
3350
|
+
const processedPathAnalytics = useMemo(() => {
|
|
3351
|
+
if (!dataFirstLevels)
|
|
3352
|
+
return pathAnalytics;
|
|
3353
|
+
const mergedFirstLevels = dataFirstLevels.map((item) => {
|
|
3354
|
+
const firstLevelDataItem = firstLevelData[item.locationPath];
|
|
3355
|
+
if (!firstLevelDataItem) {
|
|
3356
|
+
return item;
|
|
3357
|
+
}
|
|
3358
|
+
return firstLevelDataItem;
|
|
3359
|
+
});
|
|
3360
|
+
return [...mergedFirstLevels, ...otherLevelsData];
|
|
3361
|
+
}, [pathAnalytics, dataFirstLevels, firstLevelData, otherLevelsData]);
|
|
3362
|
+
return { processedPathAnalytics };
|
|
3363
|
+
};
|
|
3364
|
+
|
|
3365
|
+
const PathAnalysisContext = createContext(undefined);
|
|
3366
|
+
const PathAnalysisProvider = (props) => {
|
|
3367
|
+
const { children, campaignID, campaignGroupID, campaignVariantID, campaignVersionID, mode, campaignPathsData, analyticsData, } = props;
|
|
3368
|
+
const dataFirstLevels = campaignPathsData?.paths;
|
|
3369
|
+
const isFetchingFirstLevelPaths = campaignPathsData?.isLoading ?? false;
|
|
3370
|
+
const pathAnalytics = analyticsData?.pathAnalytics ?? [];
|
|
3371
|
+
const previousPathAnalyticsMap = analyticsData?.previousPathAnalyticsMap ?? {};
|
|
3372
|
+
const isLoadingMetric = analyticsData?.isLoading ?? false;
|
|
3373
|
+
const locationPath = analyticsData?.locationPath;
|
|
3374
|
+
const shopifyPageType = analyticsData?.shopifyPageType;
|
|
3375
|
+
const pathAnalysisCacheKey = JSON.stringify({ mode, campaignVariantID, campaignVersionID });
|
|
3376
|
+
const { processedPathAnalytics } = usePathAnalyticsMerger({ pathAnalytics, dataFirstLevels });
|
|
3377
|
+
const pathAnalysisFunnelData = usePathAnalysisFunnel({
|
|
3378
|
+
pathAnalytics: processedPathAnalytics,
|
|
3379
|
+
pathAnalysisCacheKey,
|
|
3380
|
+
dataFirstLevels,
|
|
3381
|
+
locationPath,
|
|
3382
|
+
});
|
|
3383
|
+
const isLoading = isLoadingMetric || isFetchingFirstLevelPaths;
|
|
3384
|
+
return (jsx(PathAnalysisContext.Provider, { value: {
|
|
3385
|
+
mode,
|
|
3386
|
+
campaignID,
|
|
3387
|
+
campaignGroupID,
|
|
3388
|
+
campaignVariantID,
|
|
3389
|
+
campaignVersionID,
|
|
3390
|
+
shopifyPageType,
|
|
3391
|
+
pathAnalytics: processedPathAnalytics,
|
|
3392
|
+
previousPathAnalyticsMap,
|
|
3393
|
+
isLoadingMetric: isLoading,
|
|
3394
|
+
...pathAnalysisFunnelData,
|
|
3395
|
+
}, children: children }));
|
|
3396
|
+
};
|
|
3397
|
+
const usePathAnalysisContext = () => {
|
|
3398
|
+
const context = useContext(PathAnalysisContext);
|
|
3399
|
+
if (!context) {
|
|
3400
|
+
throw new Error('usePathAnalysisContext must be used within a PathAnalysisProvider');
|
|
3401
|
+
}
|
|
3402
|
+
return context;
|
|
3713
3403
|
};
|
|
3714
3404
|
|
|
3715
3405
|
var variables = {
|
|
@@ -23945,6 +23635,209 @@ const MOCK_DATA_PATH_ANALYSIS = [
|
|
|
23945
23635
|
},
|
|
23946
23636
|
];
|
|
23947
23637
|
|
|
23638
|
+
const useConvertMoneyByCurrency = () => ({
|
|
23639
|
+
getTextPrice: () => '',
|
|
23640
|
+
});
|
|
23641
|
+
|
|
23642
|
+
const FUNNEL_NAME = 'Conversion';
|
|
23643
|
+
// Checkout pages don't support heatmap viewing
|
|
23644
|
+
const NON_HEATMAP_PAGE_TYPES = new Set([TemplateType.CHECKOUT]);
|
|
23645
|
+
const usePathAnalysisChart = () => {
|
|
23646
|
+
const { t } = useTranslation();
|
|
23647
|
+
const { getTextPrice } = useConvertMoneyByCurrency();
|
|
23648
|
+
const { heatmap } = usePathAnalysisConfig();
|
|
23649
|
+
const { shopifyPageType, pageWithMetric, nextLevelPages, dynamicLevels, previousPathAnalyticsMap, handleAddNextLevel, handleChangeLevel, getPagesByParentID, handleDeleteLevel, } = usePathAnalysisContext();
|
|
23650
|
+
const orderedPages = useMemo(() => [pageWithMetric, ...dynamicLevels].filter(Boolean), [pageWithMetric, dynamicLevels]);
|
|
23651
|
+
const chartTooltipPrimaryAction = useMemo(() => {
|
|
23652
|
+
if (!heatmap.isEnabledV1)
|
|
23653
|
+
return undefined;
|
|
23654
|
+
return {
|
|
23655
|
+
content: t('View heatmap'),
|
|
23656
|
+
onClick: (item) => {
|
|
23657
|
+
if (!item?.id)
|
|
23658
|
+
return;
|
|
23659
|
+
const level = orderedPages.findIndex((page) => page?.id === item.id);
|
|
23660
|
+
if (level === -1)
|
|
23661
|
+
return;
|
|
23662
|
+
heatmap.onView(level, orderedPages);
|
|
23663
|
+
},
|
|
23664
|
+
};
|
|
23665
|
+
}, [heatmap, orderedPages, t]);
|
|
23666
|
+
const lengthDisplayedLevels = dynamicLevels.length;
|
|
23667
|
+
const isDisabledAddICon = !nextLevelPages.length || lengthDisplayedLevels >= MAX_FUNNEL_ADDITIONAL_LEVEL;
|
|
23668
|
+
const lastLevel = useMemo(() => {
|
|
23669
|
+
return dynamicLevels[dynamicLevels.length - 1] || pageWithMetric;
|
|
23670
|
+
}, [dynamicLevels, pageWithMetric]);
|
|
23671
|
+
const getTooltipAction = useCallback((pageType) => {
|
|
23672
|
+
if (pageType && NON_HEATMAP_PAGE_TYPES.has(pageType))
|
|
23673
|
+
return undefined;
|
|
23674
|
+
return chartTooltipPrimaryAction;
|
|
23675
|
+
}, [chartTooltipPrimaryAction]);
|
|
23676
|
+
const onDeleteFunnel = useCallback((id) => {
|
|
23677
|
+
handleDeleteLevel(id);
|
|
23678
|
+
}, [handleDeleteLevel]);
|
|
23679
|
+
const getConversionFunnelData = useCallback((item) => {
|
|
23680
|
+
const metric = item?.metric;
|
|
23681
|
+
const totalAddedToCart = getTotalSessionWithCartAdditionMetric({ metric }).value;
|
|
23682
|
+
const totalReachedCheckout = getTotalSessionReachedCheckoutMetric({ metric }).value;
|
|
23683
|
+
const totalCompletedCheckout = getTotalSessionCompletedCheckoutMetric({ metric }).value;
|
|
23684
|
+
return [
|
|
23685
|
+
{
|
|
23686
|
+
value: Number(totalAddedToCart ?? 0),
|
|
23687
|
+
key: METRICS_COLUMNS[IPAMetricKey.PAGE_ADDED_TO_CART]?.label ?? t('Added to cart'),
|
|
23688
|
+
labelTooltip: PA_METRIC_TOOLTIP[IPAMetricKey.PAGE_CART_ADDITION],
|
|
23689
|
+
},
|
|
23690
|
+
{
|
|
23691
|
+
value: Number(totalReachedCheckout ?? 0),
|
|
23692
|
+
key: t('Reached checkout'),
|
|
23693
|
+
labelTooltip: PA_METRIC_TOOLTIP[IPAMetricKey.PAGE_REACHED_CHECKOUT],
|
|
23694
|
+
},
|
|
23695
|
+
{
|
|
23696
|
+
value: Number(totalCompletedCheckout ?? 0),
|
|
23697
|
+
key: t('Completed checkout'),
|
|
23698
|
+
labelTooltip: PA_METRIC_TOOLTIP[IPAMetricKey.PAGE_COMPLETE_CHECKOUT],
|
|
23699
|
+
},
|
|
23700
|
+
];
|
|
23701
|
+
}, [t]);
|
|
23702
|
+
const listFunnelDataMiddle = useMemo(() => dynamicLevels.reduce((acc, item) => {
|
|
23703
|
+
const key = parseTemplateType(item?.pageType) + `-${item.id}` || 'unknown';
|
|
23704
|
+
// Current data
|
|
23705
|
+
acc.currentData.push({
|
|
23706
|
+
value: item.metric?.totalSessions || 0,
|
|
23707
|
+
key,
|
|
23708
|
+
parentID: item.parentID,
|
|
23709
|
+
id: item.id,
|
|
23710
|
+
chartTooltip: getFunnelChartTooltip({
|
|
23711
|
+
page: item,
|
|
23712
|
+
getTextPrice,
|
|
23713
|
+
}),
|
|
23714
|
+
chartTooltipPrimaryAction: heatmap.isEnabledV2 ? getTooltipAction(item?.pageType ?? undefined) : undefined,
|
|
23715
|
+
secondaryActions: [
|
|
23716
|
+
{
|
|
23717
|
+
onAction: () => onDeleteFunnel(item.id),
|
|
23718
|
+
icon: SvgDeleteIcon,
|
|
23719
|
+
},
|
|
23720
|
+
],
|
|
23721
|
+
title: item.pageTitle ?? undefined,
|
|
23722
|
+
});
|
|
23723
|
+
// Previous data
|
|
23724
|
+
acc.previousData.push({
|
|
23725
|
+
value: previousPathAnalyticsMap[item.id]?.metric?.totalSessions || 0,
|
|
23726
|
+
key,
|
|
23727
|
+
title: item.pageTitle ?? undefined,
|
|
23728
|
+
});
|
|
23729
|
+
return acc;
|
|
23730
|
+
}, { currentData: [], previousData: [] }), [dynamicLevels, previousPathAnalyticsMap, onDeleteFunnel, getTextPrice, getTooltipAction, heatmap.isEnabledV2]);
|
|
23731
|
+
const lastLevelPreviousData = previousPathAnalyticsMap[lastLevel?.id ?? ''];
|
|
23732
|
+
const funnelData = useMemo(() => {
|
|
23733
|
+
const firstLevelKey = pageWithMetric?.pageTitle ||
|
|
23734
|
+
parseTemplateType(pageWithMetric?.pageType ?? shopifyPageType) ||
|
|
23735
|
+
'unknown';
|
|
23736
|
+
return [
|
|
23737
|
+
{
|
|
23738
|
+
data: [
|
|
23739
|
+
{
|
|
23740
|
+
value: pageWithMetric?.metric?.totalSessions || 0,
|
|
23741
|
+
key: firstLevelKey,
|
|
23742
|
+
title: pageWithMetric?.pageTitle,
|
|
23743
|
+
id: pageWithMetric?.id,
|
|
23744
|
+
chartTooltip: getFunnelChartTooltip({ page: pageWithMetric, getTextPrice }),
|
|
23745
|
+
chartTooltipPrimaryAction: getTooltipAction(pageWithMetric?.pageType ?? undefined),
|
|
23746
|
+
},
|
|
23747
|
+
...listFunnelDataMiddle.currentData,
|
|
23748
|
+
...getConversionFunnelData(lastLevel),
|
|
23749
|
+
],
|
|
23750
|
+
name: FUNNEL_NAME,
|
|
23751
|
+
metadata: {
|
|
23752
|
+
trends: calculateConversionFunnelTrends({
|
|
23753
|
+
pageWithMetric,
|
|
23754
|
+
previousPathAnalyticsMap,
|
|
23755
|
+
dynamicLevels,
|
|
23756
|
+
}),
|
|
23757
|
+
},
|
|
23758
|
+
},
|
|
23759
|
+
{
|
|
23760
|
+
name: FUNNEL_NAME,
|
|
23761
|
+
data: [
|
|
23762
|
+
{
|
|
23763
|
+
value: previousPathAnalyticsMap[pageWithMetric?.id || '']?.metric?.totalSessions || 0,
|
|
23764
|
+
key: firstLevelKey,
|
|
23765
|
+
},
|
|
23766
|
+
...listFunnelDataMiddle.previousData,
|
|
23767
|
+
...getConversionFunnelData(lastLevelPreviousData),
|
|
23768
|
+
],
|
|
23769
|
+
isComparison: true,
|
|
23770
|
+
isEmptyData: !lastLevelPreviousData || lastLevelPreviousData.metric?.totalSessions === 0,
|
|
23771
|
+
},
|
|
23772
|
+
];
|
|
23773
|
+
}, [
|
|
23774
|
+
dynamicLevels,
|
|
23775
|
+
pageWithMetric,
|
|
23776
|
+
shopifyPageType,
|
|
23777
|
+
getTextPrice,
|
|
23778
|
+
previousPathAnalyticsMap,
|
|
23779
|
+
listFunnelDataMiddle,
|
|
23780
|
+
getConversionFunnelData,
|
|
23781
|
+
lastLevel,
|
|
23782
|
+
lastLevelPreviousData,
|
|
23783
|
+
getTooltipAction,
|
|
23784
|
+
]);
|
|
23785
|
+
const formatFunnelSelection = (item) => {
|
|
23786
|
+
const childrenSessions = item.metric?.totalSessions || 0;
|
|
23787
|
+
return {
|
|
23788
|
+
id: item.id,
|
|
23789
|
+
title: item.pageTitle || parseTemplateType(item.pageType),
|
|
23790
|
+
path: item.locationPath ?? undefined,
|
|
23791
|
+
percentage: numberWithCommas(childrenSessions.toString()),
|
|
23792
|
+
parentID: item.parentID,
|
|
23793
|
+
};
|
|
23794
|
+
};
|
|
23795
|
+
const sortByPercentage = (a, b) => {
|
|
23796
|
+
const numericPattern = /[^0-9.-]/g;
|
|
23797
|
+
const aPercentage = Number(a.percentage.replace(numericPattern, ''));
|
|
23798
|
+
const bPercentage = Number(b.percentage.replace(numericPattern, ''));
|
|
23799
|
+
return bPercentage - aPercentage;
|
|
23800
|
+
};
|
|
23801
|
+
// const sortByTitle = (a: IFunnelSelectionItem, b: IFunnelSelectionItem) => {
|
|
23802
|
+
// const aTitle = a.title || '';
|
|
23803
|
+
// const bTitle = b.title || '';
|
|
23804
|
+
// return aTitle.localeCompare(bTitle);
|
|
23805
|
+
// };
|
|
23806
|
+
//list funnel selection to add new funnel
|
|
23807
|
+
const listFunnelSelection = useMemo(() => {
|
|
23808
|
+
if (!nextLevelPages)
|
|
23809
|
+
return [];
|
|
23810
|
+
return nextLevelPages.map(formatFunnelSelection).sort(sortByPercentage);
|
|
23811
|
+
}, [nextLevelPages]);
|
|
23812
|
+
//list funnel selection to change funnel
|
|
23813
|
+
const getListFunnelByID = (data) => {
|
|
23814
|
+
const { level, parentID } = data;
|
|
23815
|
+
const availableChildPages = getPagesByParentID({ level, parentID });
|
|
23816
|
+
// if (level === 0) {
|
|
23817
|
+
// return availableChildPages.map(formatFunnelSelection).sort(sortByTitle);
|
|
23818
|
+
// }
|
|
23819
|
+
return availableChildPages.map(formatFunnelSelection).sort(sortByPercentage);
|
|
23820
|
+
};
|
|
23821
|
+
const onAddNextFunnel = (id) => {
|
|
23822
|
+
handleAddNextLevel(id);
|
|
23823
|
+
};
|
|
23824
|
+
const onChangeFunnel = (data) => {
|
|
23825
|
+
if (!data.selectedID)
|
|
23826
|
+
return;
|
|
23827
|
+
handleChangeLevel(data);
|
|
23828
|
+
};
|
|
23829
|
+
return {
|
|
23830
|
+
lengthDisplayedLevels,
|
|
23831
|
+
listFunnelSelection,
|
|
23832
|
+
isDisabledAddICon,
|
|
23833
|
+
funnelData,
|
|
23834
|
+
onDeleteFunnel,
|
|
23835
|
+
onAddNextFunnel,
|
|
23836
|
+
onChangeFunnel,
|
|
23837
|
+
getListFunnelByID,
|
|
23838
|
+
};
|
|
23839
|
+
};
|
|
23840
|
+
|
|
23948
23841
|
const PathAnalysisChart = ({ funnelColors, isEnabled }) => {
|
|
23949
23842
|
const { lengthDisplayedLevels, listFunnelSelection, isDisabledAddICon, funnelData, getListFunnelByID, onAddNextFunnel, onChangeFunnel, } = usePathAnalysisChart();
|
|
23950
23843
|
const dataSeries = useMemo(() => {
|
|
@@ -23978,20 +23871,23 @@ const CardPathAnalysisEmpty = ({ funnelColors }) => {
|
|
|
23978
23871
|
}, children: jsx(CardAnalyticEmpty, { description: t('GemX is collecting data and will display it as soon as possible') }) }), jsx(PathAnalysisChart, { funnelColors: funnelColors, isEnabled: false })] }));
|
|
23979
23872
|
};
|
|
23980
23873
|
|
|
23874
|
+
const CardPathAnalysisSkeleton = () => {
|
|
23875
|
+
return (jsxs(BlockStack, { gap: "200", children: [jsx(MetricInfoSkeleton, {}), jsx(GSkeletonDisplayText, { height: "350px" })] }));
|
|
23876
|
+
};
|
|
23877
|
+
|
|
23981
23878
|
const CardPathAnalysisContent = ({ showBadge = true, funnelColors }) => {
|
|
23982
23879
|
const { pathAnalytics, isLoadingMetric } = usePathAnalysisContext();
|
|
23983
|
-
|
|
23984
|
-
|
|
23985
|
-
if (!isEnabled)
|
|
23880
|
+
const { pricing } = usePathAnalysisConfig();
|
|
23881
|
+
if (!pricing.isPathAnalysisEnabled)
|
|
23986
23882
|
return jsx(CardPathAnalysisLocked, { funnelColors: funnelColors });
|
|
23987
23883
|
if (isLoadingMetric || !pathAnalytics)
|
|
23988
23884
|
return jsx(CardPathAnalysisSkeleton, {});
|
|
23989
23885
|
if (!pathAnalytics.length)
|
|
23990
23886
|
return jsx(CardPathAnalysisEmpty, { funnelColors: funnelColors });
|
|
23991
|
-
return (jsx("div", { className: cls('relative pr-1', { 'GAnalytic-Badge-Logo GPath-Badge-Logo': showBadge }), children: jsx(PathAnalysisChart, { funnelColors: funnelColors, isEnabled:
|
|
23887
|
+
return (jsx("div", { className: cls('relative pr-1', { 'GAnalytic-Badge-Logo GPath-Badge-Logo': showBadge }), children: jsx(PathAnalysisChart, { funnelColors: funnelColors, isEnabled: pricing.isPathAnalysisEnabled }) }));
|
|
23992
23888
|
};
|
|
23993
23889
|
const CardPathAnalysisLocked = ({ funnelColors }) => {
|
|
23994
|
-
const {
|
|
23890
|
+
const { pricing } = usePathAnalysisConfig();
|
|
23995
23891
|
return (jsxs("div", { className: cls('relative pr-1'), children: [jsx("div", { className: "absolute z-[1000] h-full w-full", children: jsx(GFeatureLocked, { title: t$1('See your customer journey and where they leave'), description: t$1('Upgrade to {{planName}} to focus on key steps in the journey', {
|
|
23996
23892
|
planName: 'Funnel Optimize',
|
|
23997
23893
|
}), inlineAlign: "end", type: IGFeatureLocked.PathAnalysis, boxProps: {
|
|
@@ -24005,7 +23901,7 @@ const CardPathAnalysisLocked = ({ funnelColors }) => {
|
|
|
24005
23901
|
width: '635px',
|
|
24006
23902
|
maxWidth: '100%',
|
|
24007
23903
|
}, buttonProps: {
|
|
24008
|
-
onClick: onOpenModalPricing,
|
|
23904
|
+
onClick: pricing.onOpenModalPricing,
|
|
24009
23905
|
} }) }), jsx(PathAnalysisChart, { funnelColors: funnelColors, isEnabled: false })] }));
|
|
24010
23906
|
};
|
|
24011
23907
|
|
|
@@ -24015,15 +23911,15 @@ const CardPathAnalysisWrapper = ({ children, campaignID, campaignGroupID, campai
|
|
|
24015
23911
|
|
|
24016
23912
|
const CardPathAnalysis = (props) => {
|
|
24017
23913
|
const { campaignID, campaignGroupID, campaignVariantID, analyticMode, children, campaignPathsData, campaignVersionID, analyticsData, } = props;
|
|
24018
|
-
const {
|
|
24019
|
-
if (isLoading)
|
|
23914
|
+
const { pricing } = usePathAnalysisConfig();
|
|
23915
|
+
if (pricing.isLoading)
|
|
24020
23916
|
return null;
|
|
24021
23917
|
return (jsxs(CardPathAnalysisWrapper, { campaignID: campaignID, campaignGroupID: campaignGroupID, campaignVariantID: campaignVariantID, analyticMode: analyticMode, campaignPathsData: campaignPathsData, campaignVersionID: campaignVersionID, analyticsData: analyticsData, children: [jsx(Box, { children: children }), jsx(CardPathAnalysisContent, { ...props })] }));
|
|
24022
23918
|
};
|
|
24023
23919
|
|
|
24024
|
-
const CardJourneyAnalysis = ({ analyticMode, ...props }) => {
|
|
23920
|
+
const CardJourneyAnalysis = ({ analyticMode, config, ...props }) => {
|
|
24025
23921
|
const { t } = useTranslation();
|
|
24026
|
-
return (jsx(CardPathAnalysis, { analyticMode: analyticMode || EAnalyticMode.ALL_SESSION, ...props, children: jsx(InlineStack, { gap: "200", children: jsx(GTooltipCard, { tooltip: ANALYTICS_METRIC_TOOLTIP[EMetricKey.PAGE_PATH_ANALYSIS], children: jsx(Text, { as: "h3", variant: "headingMd", children: t('Journey analysis') }) }) }) }));
|
|
23922
|
+
return (jsx(PathAnalysisConfigProvider, { ...config, children: jsx(CardPathAnalysis, { analyticMode: analyticMode || EAnalyticMode.ALL_SESSION, ...props, children: jsx(InlineStack, { gap: "200", children: jsx(GTooltipCard, { tooltip: ANALYTICS_METRIC_TOOLTIP[EMetricKey.PAGE_PATH_ANALYSIS], children: jsx(Text, { as: "h3", variant: "headingMd", children: t('Journey analysis') }) }) }) }) }));
|
|
24027
23923
|
};
|
|
24028
23924
|
|
|
24029
23925
|
function isBrowser() {
|
|
@@ -24069,4 +23965,4 @@ const useStickyFilterBoxProps = ({ id }) => {
|
|
|
24069
23965
|
};
|
|
24070
23966
|
};
|
|
24071
23967
|
|
|
24072
|
-
export { ANALYTICS_METRIC_TOOLTIP, AnalyticModeSelector, CAMPAIGN_BACKGROUND_MAIN, CHART_MIN_HEIGHT, COMPARE_DATE_TIME_FILTERS_MAP, CardJourneyAnalysis, CardPathAnalysis, CompareDateTimePickerAlias, ConvertMoneyProvider, CurrencySelector, DATE_TIME_COMPARISON_FILTERS, DEFAULT_CURRENCY_ANALYTIC, DEFAULT_CURRENT_PERIOD_LABEL, DEFAULT_PREVIOUS_PERIOD_LABEL, DateTimeFilterInputs, DateTimeFilters, DateTimePickerContext, DateTimePickerProvider, FUNNEL_POPOVER_KEY, GSelectableMetricChartCard, GTimePicker, IVariantType, MOCK_DATA_PATH_ANALYSIS, MainDateTimePickerAlias, MetricChartProvider, MetricDonutChartCard, PLACEHOLDER_VALUE$1 as PLACEHOLDER_VALUE, PREVIOUS_PERIOD_FILTER, PathAnalysisContext, PathAnalysisProvider,
|
|
23968
|
+
export { ANALYTICS_METRIC_TOOLTIP, AnalyticModeSelector, CAMPAIGN_BACKGROUND_MAIN, CHART_MIN_HEIGHT, COMPARE_DATE_TIME_FILTERS_MAP, CardJourneyAnalysis, CardPathAnalysis, CompareDateTimePickerAlias, ConvertMoneyProvider, CurrencySelector, DATE_TIME_COMPARISON_FILTERS, DEFAULT_CURRENCY_ANALYTIC, DEFAULT_CURRENT_PERIOD_LABEL, DEFAULT_PREVIOUS_PERIOD_LABEL, DateTimeFilterInputs, DateTimeFilters, DateTimePickerContext, DateTimePickerProvider, FUNNEL_POPOVER_KEY, GSelectableMetricChartCard, GTimePicker, IVariantType, MOCK_DATA_PATH_ANALYSIS, MainDateTimePickerAlias, MetricChartProvider, MetricDonutChartCard, PLACEHOLDER_VALUE$1 as PLACEHOLDER_VALUE, PREVIOUS_PERIOD_FILTER, PathAnalysisConfigProvider, PathAnalysisContext, PathAnalysisProvider, SERIES_COLORS, SingleMetricChartCard, TARGET_CHANNEL, TARGET_DEVICES, TARGET_VISITOR, THUMB_PRODUCT_DEFAULT, TREND_TONE, convertDateToTz, convertToDateTimeFilters, createLastDaysRange, dayjsTz, dayjsTzToDate, dayjsTzToLocalTZ, formatDate, formatDateTimeRange, formatDayjs, formatMs, formatTime, formatTimeRange, getDateRangeTitle, getDateTimeFilterBase, getDateTimeFilterByAlias, getDateTimeFilterMapping, getEndOfDayBy, getInitialTimezone, getLast12Months, getLast30Days, getLast365Days, getLast7Days, getLast90Days, getLastMonth, getLastYear, getMonthAndYearByDateFilter, getNoComparison, getPreviousMonth, getPreviousPeriod, getPreviousQuarter, getPreviousWeek, getPreviousYear, getToday, getVersionDateDescription, getVersionDateRangeTitle, getYesterday, isDate, isMidnight, isSameDayTimestamp, isValidDate, isValidYearMonthDayDateString, parseYearMonthDayDateString, setTz, useConvertMoneyContext, useCurrencyRatesStore, useDateTimeFilter, useDateTimePicker, useDateTimePickerContext, useFunnelChartStore, useIsStickyById, usePathAnalysisCampaignStore, usePathAnalysisConfig, usePathAnalysisContext, usePathAnalysisStore, useStickyFilterBoxProps, useVersionDateTimeFilters };
|