@levi-gemcommerce/analytics 1.0.0-dev.15 → 1.0.0-dev.16

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.
@@ -1,4 +1,3 @@
1
- import type { IGetTextPrice } from '../helpers/formatAnalyticData';
2
1
  import type { AnalyticValueType } from '../types';
3
2
  interface IFormatDataParams {
4
3
  value: AnalyticValueType;
@@ -20,5 +19,5 @@ interface IUseAnalyticDataReturn {
20
19
  formatData: (params: IFormatDataParams) => AnalyticValueType;
21
20
  computeMetric: (params: IComputeMetricParams) => IComputeMetricResult;
22
21
  }
23
- export declare const useAnalyticData: (getTextPrice?: IGetTextPrice) => IUseAnalyticDataReturn;
22
+ export declare const useAnalyticData: () => IUseAnalyticDataReturn;
24
23
  export {};
@@ -3,7 +3,9 @@ import quarterOfYear from 'dayjs/plugin/quarterOfYear.js';
3
3
  import timezone from 'dayjs/plugin/timezone.js';
4
4
  import utc from 'dayjs/plugin/utc.js';
5
5
  import { useQuery } from '@tanstack/react-query';
6
- import { useState, useRef, useCallback, useEffect } from 'react';
6
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
7
+ import { createContext, useContext, useState, useRef, useCallback, useEffect } from 'react';
8
+ import { create } from 'zustand';
7
9
 
8
10
  const NONE_VALUE = 'None';
9
11
  const PLACEHOLDER_VALUE = '-';
@@ -947,7 +949,186 @@ const useGemxQlNamedQuery = ({ name, variables, fetcher }, options) => {
947
949
  };
948
950
  useGemxQlNamedQuery.getKey = (name, variables) => [name, variables];
949
951
 
950
- const useAnalyticData = (getTextPrice) => {
952
+ var EMetricKey;
953
+ (function (EMetricKey) {
954
+ EMetricKey["SESSION"] = "sessions";
955
+ EMetricKey["ORDERS"] = "orders";
956
+ EMetricKey["PAGE_VIEWS"] = "pageviews";
957
+ EMetricKey["VISITORS"] = "visitors";
958
+ EMetricKey["BOUNCE_RATE"] = "bounce_rate";
959
+ EMetricKey["CTR"] = "ctr";
960
+ EMetricKey["CONVERSION_RATE"] = "conversion_rate";
961
+ EMetricKey["AVG_TIME_ON_PAGE"] = "average_time_on_page";
962
+ EMetricKey["ADDED_TO_CART"] = "added_to_cart";
963
+ EMetricKey["ADD_TO_CART_RATE"] = "added_to_cart_rate";
964
+ EMetricKey["REACHED_CHECKOUT"] = "sessions_that_reached_checkout";
965
+ EMetricKey["COMPLETE_CHECKOUT"] = "sessions_that_completed_checkout";
966
+ EMetricKey["CART_ADDITION"] = "sessions_with_cart_additions";
967
+ EMetricKey["AOV"] = "aov";
968
+ EMetricKey["REVENUE"] = "revenue";
969
+ EMetricKey["RPV"] = "revenue_per_visitor";
970
+ EMetricKey["VISITOR_ITEMS"] = "visitor_items";
971
+ EMetricKey["DEVICE_ITEMS"] = "device_items";
972
+ EMetricKey["TRAFFIC_SOURCE_ITEMS"] = "traffic_source_items";
973
+ })(EMetricKey || (EMetricKey = {}));
974
+
975
+ ({
976
+ [EMetricKey.SESSION]: {
977
+ title: 'Sessions',
978
+ content: 'A period during which a visitor interacts with your online store',
979
+ },
980
+ [EMetricKey.VISITORS]: {
981
+ title: 'Visitors',
982
+ content: 'Number of unique individuals who visit your online store',
983
+ },
984
+ [EMetricKey.BOUNCE_RATE]: {
985
+ title: 'Bounce rate',
986
+ content: 'Percentage of visitors who leave your store after viewing only one page, without interacting further',
987
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Bounce rate" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "sessions with a pageview" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "total sessions" })] })),
988
+ },
989
+ [EMetricKey.CTR]: {
990
+ title: 'Click-through rate',
991
+ content: 'Percentage of clicks to open new page, compared to the number of times the page was viewed',
992
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Click-through rate" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "total clicks" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "total pageviews" })] })),
993
+ },
994
+ [EMetricKey.AVG_TIME_ON_PAGE]: {
995
+ title: 'Average time on page',
996
+ content: 'Average duration that visitors spend on a page before clicking to open new page',
997
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Average time on page" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "total time on page" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "(total pageviews - total exits)" })] })),
998
+ },
999
+ [EMetricKey.PAGE_VIEWS]: {
1000
+ title: 'Pageviews',
1001
+ content: 'Number of times a page on your online store has been viewed by visitors',
1002
+ },
1003
+ [EMetricKey.RPV]: {
1004
+ title: 'Revenue per visitor',
1005
+ content: 'Average revenue generated from each visitor',
1006
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Revenue per visitor" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "total revenue" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "total visitors" })] })),
1007
+ },
1008
+ [EMetricKey.ADDED_TO_CART]: {
1009
+ title: 'Added to cart',
1010
+ content: 'Total number of the event when a customer adds a product to their cart on your online store',
1011
+ },
1012
+ [EMetricKey.REACHED_CHECKOUT]: {
1013
+ title: 'Sessions that reached checkout',
1014
+ content: 'Sessions in your online store in which the checkout page was reached',
1015
+ },
1016
+ [EMetricKey.COMPLETE_CHECKOUT]: {
1017
+ title: 'Sessions that completed checkout',
1018
+ content: 'Sessions in your online store in which a purchase was completed',
1019
+ },
1020
+ [EMetricKey.ORDERS]: {
1021
+ title: 'Orders',
1022
+ content: 'Number of orders that went through this pages',
1023
+ },
1024
+ [EMetricKey.CONVERSION_RATE]: {
1025
+ title: 'Conversion rate',
1026
+ content: 'Percentage of online store sessions that completed an order',
1027
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Conversion rate" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "sessions that completed checkout" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "total sessions" })] })),
1028
+ },
1029
+ [EMetricKey.AOV]: {
1030
+ title: 'Average order value',
1031
+ content: 'Average value of orders placed in your online store',
1032
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Average order value" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "total revenue" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "total orders" })] })),
1033
+ },
1034
+ [EMetricKey.REVENUE]: {
1035
+ title: 'Revenue',
1036
+ content: 'Total income generated from sales after discounts',
1037
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Revenue" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "gross sales" }), jsx("span", { className: "formula-operator", children: " - " }), jsx("span", { className: "formula-input", children: "discounts" })] })),
1038
+ },
1039
+ [EMetricKey.ADD_TO_CART_RATE]: {
1040
+ title: 'Add to cart rate',
1041
+ content: 'Percentage of sessions in which the customer added item to the cart',
1042
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Added to cart rate" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "sessions with cart additions" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "total sessions" })] })),
1043
+ },
1044
+ [EMetricKey.CART_ADDITION]: {
1045
+ title: 'Sessions with cart additions',
1046
+ content: 'Sessions in your online store in which a visitor added item to the cart',
1047
+ },
1048
+ [EMetricKey.VISITOR_ITEMS]: {
1049
+ title: 'Sessions by visitor type',
1050
+ content: '<p>Numbers of new and returning visitors</p>',
1051
+ contentList: [
1052
+ 'New visitor: who accesses your store for the first time after GemX installation',
1053
+ 'Returning visitor: who comes back to your store after GemX installation',
1054
+ ],
1055
+ },
1056
+ [EMetricKey.DEVICE_ITEMS]: {
1057
+ title: 'Sessions by device type',
1058
+ content: `Sessions in your online store by the visitor's device type`,
1059
+ },
1060
+ [EMetricKey.TRAFFIC_SOURCE_ITEMS]: {
1061
+ title: 'Sessions by traffic source',
1062
+ content: 'Sessions on your page by where visitors come from',
1063
+ },
1064
+ });
1065
+
1066
+ var EAnalyticMode;
1067
+ (function (EAnalyticMode) {
1068
+ EAnalyticMode["ALL_SESSION"] = "ALL_SESSION";
1069
+ EAnalyticMode["FIRST_SESSION"] = "FIRST_SESSION";
1070
+ EAnalyticMode["PAGE_ONLY"] = "PAGE_ONLY";
1071
+ })(EAnalyticMode || (EAnalyticMode = {}));
1072
+
1073
+ var EVisitorType;
1074
+ (function (EVisitorType) {
1075
+ EVisitorType["NEW"] = "new";
1076
+ EVisitorType["RETURNING"] = "returning";
1077
+ })(EVisitorType || (EVisitorType = {}));
1078
+ var EDeviceType;
1079
+ (function (EDeviceType) {
1080
+ EDeviceType["DESKTOP"] = "desktop";
1081
+ EDeviceType["MOBILE"] = "mobile";
1082
+ EDeviceType["TABLET"] = "tablet";
1083
+ })(EDeviceType || (EDeviceType = {}));
1084
+ var ETrafficSourceType;
1085
+ (function (ETrafficSourceType) {
1086
+ ETrafficSourceType["DIRECT"] = "direct";
1087
+ ETrafficSourceType["EMAIL"] = "email";
1088
+ ETrafficSourceType["REFERRAL"] = "referral";
1089
+ ETrafficSourceType["ORGANIC_SOCIAL"] = "organic-social";
1090
+ ETrafficSourceType["ORGANIC_SEARCH"] = "organic-search";
1091
+ ETrafficSourceType["PAID_SOCIAL"] = "paid-social";
1092
+ ETrafficSourceType["PAID_SEARCH"] = "paid-search";
1093
+ ETrafficSourceType["SMS"] = "sms";
1094
+ })(ETrafficSourceType || (ETrafficSourceType = {}));
1095
+
1096
+ [
1097
+ { value: EVisitorType.NEW, label: 'New' },
1098
+ { value: EVisitorType.RETURNING, label: 'Returning' },
1099
+ ];
1100
+ [
1101
+ { value: EDeviceType.DESKTOP, label: 'Desktop' },
1102
+ { value: EDeviceType.TABLET, label: 'Tablet' },
1103
+ { value: EDeviceType.MOBILE, label: 'Mobile' },
1104
+ ];
1105
+ [
1106
+ { value: ETrafficSourceType.DIRECT, label: 'Direct' },
1107
+ { value: ETrafficSourceType.EMAIL, label: 'Email' },
1108
+ { value: ETrafficSourceType.REFERRAL, label: 'Referral' },
1109
+ { value: ETrafficSourceType.ORGANIC_SOCIAL, label: 'Organic social' },
1110
+ { value: ETrafficSourceType.ORGANIC_SEARCH, label: 'Organic search' },
1111
+ { value: ETrafficSourceType.PAID_SOCIAL, label: 'Paid social' },
1112
+ { value: ETrafficSourceType.PAID_SEARCH, label: 'Paid search' },
1113
+ { value: ETrafficSourceType.SMS, label: 'SMS' },
1114
+ ];
1115
+
1116
+ create((set) => ({
1117
+ currencyRates: null,
1118
+ setCurrencyRates: (rates) => set({ currencyRates: rates }),
1119
+ }));
1120
+
1121
+ const ConvertMoneyContext = createContext({
1122
+ getTextPrice: (price) => {
1123
+ if (typeof price === 'string')
1124
+ return price;
1125
+ return `${price ?? 0}`;
1126
+ },
1127
+ });
1128
+ const useConvertMoneyContext = () => useContext(ConvertMoneyContext);
1129
+
1130
+ const useAnalyticData = () => {
1131
+ const { getTextPrice } = useConvertMoneyContext();
951
1132
  const formatData = ({ value, formatter, name }) => {
952
1133
  return formatAnalyticData({ value, formatter, getTextPrice, name });
953
1134
  };
@@ -3,7 +3,9 @@ import quarterOfYear from 'dayjs/plugin/quarterOfYear.js';
3
3
  import timezone from 'dayjs/plugin/timezone.js';
4
4
  import utc from 'dayjs/plugin/utc.js';
5
5
  import { useQuery } from '@tanstack/react-query';
6
- import { useState, useRef, useCallback, useEffect } from 'react';
6
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
7
+ import { createContext, useContext, useState, useRef, useCallback, useEffect } from 'react';
8
+ import { create } from 'zustand';
7
9
 
8
10
  const NONE_VALUE = 'None';
9
11
  const PLACEHOLDER_VALUE = '-';
@@ -947,7 +949,186 @@ const useGemxQlNamedQuery = ({ name, variables, fetcher }, options) => {
947
949
  };
948
950
  useGemxQlNamedQuery.getKey = (name, variables) => [name, variables];
949
951
 
950
- const useAnalyticData = (getTextPrice) => {
952
+ var EMetricKey;
953
+ (function (EMetricKey) {
954
+ EMetricKey["SESSION"] = "sessions";
955
+ EMetricKey["ORDERS"] = "orders";
956
+ EMetricKey["PAGE_VIEWS"] = "pageviews";
957
+ EMetricKey["VISITORS"] = "visitors";
958
+ EMetricKey["BOUNCE_RATE"] = "bounce_rate";
959
+ EMetricKey["CTR"] = "ctr";
960
+ EMetricKey["CONVERSION_RATE"] = "conversion_rate";
961
+ EMetricKey["AVG_TIME_ON_PAGE"] = "average_time_on_page";
962
+ EMetricKey["ADDED_TO_CART"] = "added_to_cart";
963
+ EMetricKey["ADD_TO_CART_RATE"] = "added_to_cart_rate";
964
+ EMetricKey["REACHED_CHECKOUT"] = "sessions_that_reached_checkout";
965
+ EMetricKey["COMPLETE_CHECKOUT"] = "sessions_that_completed_checkout";
966
+ EMetricKey["CART_ADDITION"] = "sessions_with_cart_additions";
967
+ EMetricKey["AOV"] = "aov";
968
+ EMetricKey["REVENUE"] = "revenue";
969
+ EMetricKey["RPV"] = "revenue_per_visitor";
970
+ EMetricKey["VISITOR_ITEMS"] = "visitor_items";
971
+ EMetricKey["DEVICE_ITEMS"] = "device_items";
972
+ EMetricKey["TRAFFIC_SOURCE_ITEMS"] = "traffic_source_items";
973
+ })(EMetricKey || (EMetricKey = {}));
974
+
975
+ ({
976
+ [EMetricKey.SESSION]: {
977
+ title: 'Sessions',
978
+ content: 'A period during which a visitor interacts with your online store',
979
+ },
980
+ [EMetricKey.VISITORS]: {
981
+ title: 'Visitors',
982
+ content: 'Number of unique individuals who visit your online store',
983
+ },
984
+ [EMetricKey.BOUNCE_RATE]: {
985
+ title: 'Bounce rate',
986
+ content: 'Percentage of visitors who leave your store after viewing only one page, without interacting further',
987
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Bounce rate" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "sessions with a pageview" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "total sessions" })] })),
988
+ },
989
+ [EMetricKey.CTR]: {
990
+ title: 'Click-through rate',
991
+ content: 'Percentage of clicks to open new page, compared to the number of times the page was viewed',
992
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Click-through rate" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "total clicks" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "total pageviews" })] })),
993
+ },
994
+ [EMetricKey.AVG_TIME_ON_PAGE]: {
995
+ title: 'Average time on page',
996
+ content: 'Average duration that visitors spend on a page before clicking to open new page',
997
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Average time on page" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "total time on page" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "(total pageviews - total exits)" })] })),
998
+ },
999
+ [EMetricKey.PAGE_VIEWS]: {
1000
+ title: 'Pageviews',
1001
+ content: 'Number of times a page on your online store has been viewed by visitors',
1002
+ },
1003
+ [EMetricKey.RPV]: {
1004
+ title: 'Revenue per visitor',
1005
+ content: 'Average revenue generated from each visitor',
1006
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Revenue per visitor" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "total revenue" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "total visitors" })] })),
1007
+ },
1008
+ [EMetricKey.ADDED_TO_CART]: {
1009
+ title: 'Added to cart',
1010
+ content: 'Total number of the event when a customer adds a product to their cart on your online store',
1011
+ },
1012
+ [EMetricKey.REACHED_CHECKOUT]: {
1013
+ title: 'Sessions that reached checkout',
1014
+ content: 'Sessions in your online store in which the checkout page was reached',
1015
+ },
1016
+ [EMetricKey.COMPLETE_CHECKOUT]: {
1017
+ title: 'Sessions that completed checkout',
1018
+ content: 'Sessions in your online store in which a purchase was completed',
1019
+ },
1020
+ [EMetricKey.ORDERS]: {
1021
+ title: 'Orders',
1022
+ content: 'Number of orders that went through this pages',
1023
+ },
1024
+ [EMetricKey.CONVERSION_RATE]: {
1025
+ title: 'Conversion rate',
1026
+ content: 'Percentage of online store sessions that completed an order',
1027
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Conversion rate" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "sessions that completed checkout" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "total sessions" })] })),
1028
+ },
1029
+ [EMetricKey.AOV]: {
1030
+ title: 'Average order value',
1031
+ content: 'Average value of orders placed in your online store',
1032
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Average order value" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "total revenue" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "total orders" })] })),
1033
+ },
1034
+ [EMetricKey.REVENUE]: {
1035
+ title: 'Revenue',
1036
+ content: 'Total income generated from sales after discounts',
1037
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Revenue" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "gross sales" }), jsx("span", { className: "formula-operator", children: " - " }), jsx("span", { className: "formula-input", children: "discounts" })] })),
1038
+ },
1039
+ [EMetricKey.ADD_TO_CART_RATE]: {
1040
+ title: 'Add to cart rate',
1041
+ content: 'Percentage of sessions in which the customer added item to the cart',
1042
+ formula: (jsxs(Fragment, { children: [jsx("span", { className: "formula-variable", children: "Added to cart rate" }), jsx("span", { children: " = " }), jsx("span", { className: "formula-input", children: "sessions with cart additions" }), jsx("span", { className: "formula-operator", children: " / " }), jsx("span", { className: "formula-input", children: "total sessions" })] })),
1043
+ },
1044
+ [EMetricKey.CART_ADDITION]: {
1045
+ title: 'Sessions with cart additions',
1046
+ content: 'Sessions in your online store in which a visitor added item to the cart',
1047
+ },
1048
+ [EMetricKey.VISITOR_ITEMS]: {
1049
+ title: 'Sessions by visitor type',
1050
+ content: '<p>Numbers of new and returning visitors</p>',
1051
+ contentList: [
1052
+ 'New visitor: who accesses your store for the first time after GemX installation',
1053
+ 'Returning visitor: who comes back to your store after GemX installation',
1054
+ ],
1055
+ },
1056
+ [EMetricKey.DEVICE_ITEMS]: {
1057
+ title: 'Sessions by device type',
1058
+ content: `Sessions in your online store by the visitor's device type`,
1059
+ },
1060
+ [EMetricKey.TRAFFIC_SOURCE_ITEMS]: {
1061
+ title: 'Sessions by traffic source',
1062
+ content: 'Sessions on your page by where visitors come from',
1063
+ },
1064
+ });
1065
+
1066
+ var EAnalyticMode;
1067
+ (function (EAnalyticMode) {
1068
+ EAnalyticMode["ALL_SESSION"] = "ALL_SESSION";
1069
+ EAnalyticMode["FIRST_SESSION"] = "FIRST_SESSION";
1070
+ EAnalyticMode["PAGE_ONLY"] = "PAGE_ONLY";
1071
+ })(EAnalyticMode || (EAnalyticMode = {}));
1072
+
1073
+ var EVisitorType;
1074
+ (function (EVisitorType) {
1075
+ EVisitorType["NEW"] = "new";
1076
+ EVisitorType["RETURNING"] = "returning";
1077
+ })(EVisitorType || (EVisitorType = {}));
1078
+ var EDeviceType;
1079
+ (function (EDeviceType) {
1080
+ EDeviceType["DESKTOP"] = "desktop";
1081
+ EDeviceType["MOBILE"] = "mobile";
1082
+ EDeviceType["TABLET"] = "tablet";
1083
+ })(EDeviceType || (EDeviceType = {}));
1084
+ var ETrafficSourceType;
1085
+ (function (ETrafficSourceType) {
1086
+ ETrafficSourceType["DIRECT"] = "direct";
1087
+ ETrafficSourceType["EMAIL"] = "email";
1088
+ ETrafficSourceType["REFERRAL"] = "referral";
1089
+ ETrafficSourceType["ORGANIC_SOCIAL"] = "organic-social";
1090
+ ETrafficSourceType["ORGANIC_SEARCH"] = "organic-search";
1091
+ ETrafficSourceType["PAID_SOCIAL"] = "paid-social";
1092
+ ETrafficSourceType["PAID_SEARCH"] = "paid-search";
1093
+ ETrafficSourceType["SMS"] = "sms";
1094
+ })(ETrafficSourceType || (ETrafficSourceType = {}));
1095
+
1096
+ [
1097
+ { value: EVisitorType.NEW, label: 'New' },
1098
+ { value: EVisitorType.RETURNING, label: 'Returning' },
1099
+ ];
1100
+ [
1101
+ { value: EDeviceType.DESKTOP, label: 'Desktop' },
1102
+ { value: EDeviceType.TABLET, label: 'Tablet' },
1103
+ { value: EDeviceType.MOBILE, label: 'Mobile' },
1104
+ ];
1105
+ [
1106
+ { value: ETrafficSourceType.DIRECT, label: 'Direct' },
1107
+ { value: ETrafficSourceType.EMAIL, label: 'Email' },
1108
+ { value: ETrafficSourceType.REFERRAL, label: 'Referral' },
1109
+ { value: ETrafficSourceType.ORGANIC_SOCIAL, label: 'Organic social' },
1110
+ { value: ETrafficSourceType.ORGANIC_SEARCH, label: 'Organic search' },
1111
+ { value: ETrafficSourceType.PAID_SOCIAL, label: 'Paid social' },
1112
+ { value: ETrafficSourceType.PAID_SEARCH, label: 'Paid search' },
1113
+ { value: ETrafficSourceType.SMS, label: 'SMS' },
1114
+ ];
1115
+
1116
+ create((set) => ({
1117
+ currencyRates: null,
1118
+ setCurrencyRates: (rates) => set({ currencyRates: rates }),
1119
+ }));
1120
+
1121
+ const ConvertMoneyContext = createContext({
1122
+ getTextPrice: (price) => {
1123
+ if (typeof price === 'string')
1124
+ return price;
1125
+ return `${price ?? 0}`;
1126
+ },
1127
+ });
1128
+ const useConvertMoneyContext = () => useContext(ConvertMoneyContext);
1129
+
1130
+ const useAnalyticData = () => {
1131
+ const { getTextPrice } = useConvertMoneyContext();
951
1132
  const formatData = ({ value, formatter, name }) => {
952
1133
  return formatAnalyticData({ value, formatter, getTextPrice, name });
953
1134
  };
@@ -1,3 +1,4 @@
1
1
  export * from './components';
2
2
  export * from './constants';
3
+ export * from './providers';
3
4
  export * from './utils/dayjs';
package/dist/esm/index.js CHANGED
@@ -8,8 +8,9 @@ import quarterOfYear from 'dayjs/plugin/quarterOfYear.js';
8
8
  import timezone from 'dayjs/plugin/timezone.js';
9
9
  import utc from 'dayjs/plugin/utc.js';
10
10
  import { useTranslation } from 'react-i18next';
11
+ import { create } from 'zustand';
12
+ import { useQuery } from '@tanstack/react-query';
11
13
  import { PolarisVizProvider, LineChart, DonutChart } from '@shopify/polaris-viz';
12
- import '@tanstack/react-query';
13
14
 
14
15
  var EMetricKey;
15
16
  (function (EMetricKey) {
@@ -879,6 +880,118 @@ const GChartSkeleton = () => {
879
880
  return jsx(GSkeletonDisplayText, { height: "188px" });
880
881
  };
881
882
 
883
+ const getPriceByCurrency = (price, currency = DEFAULT_CURRENCY_ANALYTIC, options) => {
884
+ if (typeof price === 'string')
885
+ return price;
886
+ if (typeof price !== 'number')
887
+ return;
888
+ // Support legacy 3rd arg as locale string
889
+ const opts = typeof options === 'string' ? { locale: options } : options;
890
+ const locale = opts?.locale ?? 'en-US';
891
+ if (price >= 1_000_000_000) {
892
+ return `${new Intl.NumberFormat(locale, {
893
+ style: 'currency',
894
+ currency,
895
+ minimumFractionDigits: 2,
896
+ maximumFractionDigits: 2,
897
+ }).format(price / 1_000_000_000)}B`;
898
+ }
899
+ if (price >= 1_000_000) {
900
+ return `${new Intl.NumberFormat(locale, {
901
+ style: 'currency',
902
+ currency,
903
+ minimumFractionDigits: 2,
904
+ maximumFractionDigits: 2,
905
+ }).format(price / 1_000_000)}M`;
906
+ }
907
+ if (opts?.compact && Math.abs(price) >= 1_000) {
908
+ return `${new Intl.NumberFormat(locale, {
909
+ style: 'currency',
910
+ currency,
911
+ minimumFractionDigits: 1,
912
+ maximumFractionDigits: 1,
913
+ }).format(price / 1_000)}K`;
914
+ }
915
+ return new Intl.NumberFormat(locale, {
916
+ style: 'currency',
917
+ currency,
918
+ }).format(price);
919
+ };
920
+
921
+ const useCurrencyRatesStore = create((set) => ({
922
+ currencyRates: null,
923
+ setCurrencyRates: (rates) => set({ currencyRates: rates }),
924
+ }));
925
+
926
+ const SHOPIFY_CURRENCIES_URL = 'https://cdn.shopify.com/s/javascripts/currencies.js';
927
+ const parseCurrencyRates = (scriptText) => {
928
+ const rates = {};
929
+ const match = /var Currency=\{rates:\{(.*?)\}\};/s.exec(scriptText);
930
+ const ratesStr = match?.[1];
931
+ if (!ratesStr)
932
+ return rates;
933
+ const ratePattern = /([A-Z]+):\s*([\d.e+-]+),/g;
934
+ let m;
935
+ while ((m = ratePattern.exec(ratesStr)) !== null) {
936
+ const [, code, value] = m;
937
+ if (code && value)
938
+ rates[code] = parseFloat(value);
939
+ }
940
+ return rates;
941
+ };
942
+ const fetchCurrencyRates = async () => {
943
+ const res = await fetch(SHOPIFY_CURRENCIES_URL);
944
+ if (!res.ok)
945
+ throw new Error('Failed to fetch currency rates');
946
+ const text = await res.text();
947
+ return parseCurrencyRates(text);
948
+ };
949
+ const useFetchCurrencyRates = () => {
950
+ const setCurrencyRates = useCurrencyRatesStore((state) => state.setCurrencyRates);
951
+ const { data } = useQuery({
952
+ queryKey: ['sdk-currency-rates'],
953
+ queryFn: fetchCurrencyRates,
954
+ staleTime: 1000 * 60 * 60, // 1 hour — rates don't change often
955
+ });
956
+ useEffect(() => {
957
+ if (data)
958
+ setCurrencyRates(data);
959
+ }, [data, setCurrencyRates]);
960
+ };
961
+
962
+ const ConvertMoneyContext = createContext({
963
+ getTextPrice: (price) => {
964
+ if (typeof price === 'string')
965
+ return price;
966
+ return `${price ?? 0}`;
967
+ },
968
+ });
969
+ const convertAmount = (amount, from, to, rates) => {
970
+ if (from === to || !rates[from] || !rates[to])
971
+ return amount;
972
+ const converted = (amount * rates[from]) / rates[to];
973
+ return converted ? Number(converted.toFixed(2)) : amount;
974
+ };
975
+ const ConvertMoneyProvider = ({ children, currency, locale = 'en-US' }) => {
976
+ useFetchCurrencyRates();
977
+ const currencyRates = useCurrencyRatesStore((state) => state.currencyRates);
978
+ const getTextPrice = useCallback((price, _hasCurrency, options) => {
979
+ if (typeof price === 'string')
980
+ return price;
981
+ if (typeof price !== 'number')
982
+ return '0';
983
+ if (!currency)
984
+ return price.toString();
985
+ const converted = currencyRates
986
+ ? convertAmount(price, DEFAULT_CURRENCY_ANALYTIC, currency, currencyRates)
987
+ : price;
988
+ return trimDecimalZeros(getPriceByCurrency(converted, currency, { locale, compact: options?.compact }) ?? '0');
989
+ }, [currency, locale, currencyRates]);
990
+ const value = useMemo(() => ({ getTextPrice }), [getTextPrice]);
991
+ return jsx(ConvertMoneyContext.Provider, { value: value, children: children });
992
+ };
993
+ const useConvertMoneyContext = () => useContext(ConvertMoneyContext);
994
+
882
995
  const LINE_SERIES_COLORS = {
883
996
  comparison: SERIES_COLORS.comparison,
884
997
  single: SERIES_COLORS.current,
@@ -1169,7 +1282,8 @@ const readNumeric = (metric, key) => {
1169
1282
  return typeof raw === 'number' ? raw : 0;
1170
1283
  };
1171
1284
 
1172
- const useAnalyticData = (getTextPrice) => {
1285
+ const useAnalyticData = () => {
1286
+ const { getTextPrice } = useConvertMoneyContext();
1173
1287
  const formatData = ({ value, formatter, name }) => {
1174
1288
  return formatAnalyticData({ value, formatter, getTextPrice, name });
1175
1289
  };
@@ -2525,4 +2639,4 @@ const GTimePicker = (props) => {
2525
2639
  return (jsxs(InlineStack, { gap: "200", children: [jsx(MainTimePicker, { ...timePickerProps }), isCompare && (jsx(CompareTimePicker, { rangeAddition: timePickerProps.rangeAddition, popoverProps: timePickerProps.popoverProps }))] }));
2526
2640
  };
2527
2641
 
2528
- export { ANALYTICS_METRIC_TOOLTIP, AnalyticModeSelector, CAMPAIGN_BACKGROUND_MAIN, CHART_MIN_HEIGHT, COMPARE_DATE_TIME_FILTERS_MAP, CompareDateTimePickerAlias, CurrencySelector, DATE_TIME_COMPARISON_FILTERS, DEFAULT_CURRENCY_ANALYTIC, DEFAULT_CURRENT_PERIOD_LABEL, DEFAULT_PREVIOUS_PERIOD_LABEL, DateTimeFilterInputs, DateTimeFilters, DateTimePickerContext, DateTimePickerProvider, GSelectableMetricChartCard, GTimePicker, MainDateTimePickerAlias, MetricDonutChartCard, PLACEHOLDER_VALUE$1 as PLACEHOLDER_VALUE, PREVIOUS_PERIOD_FILTER, 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, useDateTimeFilter, useDateTimePicker, useDateTimePickerContext, useVersionDateTimeFilters };
2642
+ export { ANALYTICS_METRIC_TOOLTIP, AnalyticModeSelector, CAMPAIGN_BACKGROUND_MAIN, CHART_MIN_HEIGHT, COMPARE_DATE_TIME_FILTERS_MAP, CompareDateTimePickerAlias, ConvertMoneyProvider, CurrencySelector, DATE_TIME_COMPARISON_FILTERS, DEFAULT_CURRENCY_ANALYTIC, DEFAULT_CURRENT_PERIOD_LABEL, DEFAULT_PREVIOUS_PERIOD_LABEL, DateTimeFilterInputs, DateTimeFilters, DateTimePickerContext, DateTimePickerProvider, GSelectableMetricChartCard, GTimePicker, MainDateTimePickerAlias, MetricChartProvider, MetricDonutChartCard, PLACEHOLDER_VALUE$1 as PLACEHOLDER_VALUE, PREVIOUS_PERIOD_FILTER, 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, useFetchCurrencyRates, useVersionDateTimeFilters };