@capillarytech/creatives-library 8.0.136-beta.4 → 8.0.136

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.
@@ -157,6 +157,9 @@ const MobilePushNew = ({
157
157
  const prevUploadedAssetDataRef = useRef(null);
158
158
  const prevVideoDataRef = useRef(null);
159
159
 
160
+ // Add ref to track current template name value
161
+ const templateNameRef = useRef("");
162
+
160
163
  const videoData = useMemo(
161
164
  () => {
162
165
  const videoDataId = `vd_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
@@ -326,6 +329,7 @@ const MobilePushNew = ({
326
329
  // Define resetFormData early to avoid initialization errors
327
330
  const resetFormData = useCallback(() => {
328
331
  setTemplateName("");
332
+ templateNameRef.current = "";
329
333
  setAndroidContent({
330
334
  title: "",
331
335
  message: "",
@@ -559,7 +563,10 @@ const MobilePushNew = ({
559
563
  const stateUpdates = [];
560
564
 
561
565
  // Template name
562
- stateUpdates.push(() => setTemplateName(name));
566
+ stateUpdates.push(() => {
567
+ setTemplateName(name);
568
+ templateNameRef.current = name;
569
+ });
563
570
 
564
571
  // Process Android content
565
572
  const androidContentType = editContent?.ANDROID;
@@ -630,18 +637,23 @@ const MobilePushNew = ({
630
637
  let deepLinkKeys = button?.deepLinkKeys || [];
631
638
  if (!deepLinkKeys.length && button?.type === DEEP_LINK && button?.actionLink) {
632
639
  try {
633
- const url = new URL(button?.actionLink);
634
- const extractedKeys = [];
635
- url.searchParams.forEach((value, key) => {
636
- if (value === key) { // Only extract keys where value equals key
637
- extractedKeys.push(key);
640
+ // Extract query parameters from deep link URL using the same approach as main content
641
+ const deepLinkValue = button?.actionLink;
642
+ if (deepLinkValue && deepLinkValue.includes('?')) {
643
+ const queryString = deepLinkValue.split('?')[1];
644
+ const searchParams = new URLSearchParams(queryString);
645
+ const extractedKeys = [];
646
+ searchParams.forEach((value, key) => {
647
+ if (value === key) { // Only extract keys where value equals key
648
+ extractedKeys.push(key);
649
+ }
650
+ });
651
+ if (extractedKeys?.length > 0) {
652
+ deepLinkKeys = extractedKeys;
638
653
  }
639
- });
640
- if (extractedKeys?.length > 0) {
641
- deepLinkKeys = extractedKeys;
642
654
  }
643
655
  } catch (error) {
644
- console.error("[MobilePushNew] Error extracting deep link keys:", error);
656
+ console.error("[MobilePushNew] Error extracting deep link keys from CTA button:", error);
645
657
  }
646
658
  }
647
659
 
@@ -677,6 +689,45 @@ const MobilePushNew = ({
677
689
  }
678
690
  }
679
691
 
692
+ // Determine actionOnClick and linkType for Android - prioritize CTA buttons for video, root level CTA for others, carousel data as fallback
693
+ const androidActionOnClick = (() => {
694
+ // For video templates, prioritize CTA buttons over root level CTA
695
+ if (androidMediaType === VIDEO && androidButtons.length > 0) {
696
+ return true;
697
+ }
698
+ // If there's a root level CTA, use it
699
+ if (!!androidMainCta || !!androidContentType?.cta) {
700
+ return true;
701
+ }
702
+ // Otherwise, check carousel data
703
+ if (androidMediaType === CAROUSEL) {
704
+ const carouselLinkInfo = processCarouselDataForDeepLinks(androidCarouselData);
705
+ return carouselLinkInfo.deepLinkValue || carouselLinkInfo.externalLinkValue;
706
+ }
707
+ return false;
708
+ })();
709
+
710
+ const androidLinkType = (() => {
711
+ // For video templates, prioritize CTA buttons over root level CTA
712
+ if (androidMediaType === VIDEO && androidButtons.length > 0) {
713
+ const firstButton = androidButtons[0];
714
+ return firstButton?.type === EXTERNAL_URL ? EXTERNAL_LINK : DEEP_LINK;
715
+ }
716
+ // If there's a root level CTA, use its type
717
+ if (androidMainCta?.type === EXTERNAL_URL || androidContentType?.cta?.type === EXTERNAL_URL) {
718
+ return EXTERNAL_LINK;
719
+ }
720
+ if (androidMainCta?.type === DEEP_LINK || androidContentType?.cta?.type === DEEP_LINK) {
721
+ return DEEP_LINK;
722
+ }
723
+ // Otherwise, check carousel data
724
+ if (androidMediaType === CAROUSEL) {
725
+ const carouselLinkInfo = processCarouselDataForDeepLinks(androidCarouselData);
726
+ return carouselLinkInfo.externalLinkValue ? EXTERNAL_LINK : DEEP_LINK;
727
+ }
728
+ return DEEP_LINK;
729
+ })();
730
+
680
731
  // Process Android content
681
732
  const androidContentData = {
682
733
  title: androidTitle,
@@ -686,53 +737,145 @@ const MobilePushNew = ({
686
737
  videoSrc: androidVideoSrc,
687
738
  videoPreview: androidVideoPreview,
688
739
  carouselData: androidCarouselData,
689
- // Handle root level CTA
690
- actionOnClick: !!androidMainCta || !!androidContentType?.cta,
691
- linkType: (androidMainCta?.type === EXTERNAL_URL ? EXTERNAL_LINK : DEEP_LINK) || (androidContentType?.cta?.type === EXTERNAL_URL ? EXTERNAL_LINK : DEEP_LINK),
740
+ // Handle root level CTA or carousel data
741
+ actionOnClick: androidActionOnClick,
742
+ linkType: androidLinkType,
692
743
  deepLinkValue: (() => {
693
- // Get the deep link value
694
- const deepLinkValue = androidMainCta?.type === DEEP_LINK ? androidMainCta?.actionLink : (androidContentType?.cta?.type === DEEP_LINK ? androidContentType?.cta?.actionLink : "");
744
+ // For video templates, prioritize CTA buttons over root level CTA
745
+ if (androidMediaType === VIDEO && androidButtons.length > 0) {
746
+ const firstButton = androidButtons[0];
747
+ if (firstButton?.type === DEEP_LINK && firstButton?.actionLink) {
748
+ const deepLinkValue = firstButton.actionLink;
749
+
750
+ // If we have deep links available, find the matching one
751
+ if (deepLink?.length > 0 && deepLinkValue) {
752
+ // Try to find exact match first
753
+ const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
754
+ if (exactMatch) {
755
+ return exactMatch.value;
756
+ }
695
757
 
696
- // If we have deep links available, find the matching one
697
- if (deepLink?.length > 0 && deepLinkValue) {
698
- // Try to find exact match first
699
- const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
700
- if (exactMatch) {
701
- return exactMatch.value;
702
- }
758
+ // Try to find match without query params
759
+ const baseDeepLinkValue = deepLinkValue.split('?')[0];
760
+ const partialMatch = deepLink.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
761
+ if (partialMatch) {
762
+ return partialMatch.value;
763
+ }
764
+ }
703
765
 
704
- // Try to find match without query params
705
- const baseDeepLinkValue = deepLinkValue.split('?')[0];
706
- const partialMatch = deepLink.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
707
- if (partialMatch) {
708
- return partialMatch.value;
766
+ // If no match found, return the base URL without query parameters
767
+ return deepLinkValue ? deepLinkValue.split('?')[0] : "";
709
768
  }
769
+ return "";
710
770
  }
771
+ // If there's a root level CTA, use it
772
+ if (androidMainCta?.type === DEEP_LINK || androidContentType?.cta?.type === DEEP_LINK) {
773
+ const deepLinkValue = androidMainCta?.type === DEEP_LINK ? androidMainCta?.actionLink : androidContentType?.cta?.actionLink;
774
+
775
+ // If we have deep links available, find the matching one
776
+ if (deepLink?.length > 0 && deepLinkValue) {
777
+ // Try to find exact match first
778
+ const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
779
+ if (exactMatch) {
780
+ return exactMatch.value;
781
+ }
711
782
 
712
- // If no match found, return the base URL without query parameters
713
- return deepLinkValue ? deepLinkValue.split('?')[0] : "";
783
+ // Try to find match without query params
784
+ const baseDeepLinkValue = deepLinkValue.split('?')[0];
785
+ const partialMatch = deepLink.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
786
+ if (partialMatch) {
787
+ return partialMatch.value;
788
+ }
789
+ }
790
+
791
+ // If no match found, return the base URL without query parameters
792
+ return deepLinkValue ? deepLinkValue.split('?')[0] : "";
793
+ }
794
+ // Otherwise, check carousel data
795
+ if (androidMediaType === CAROUSEL) {
796
+ const carouselLinkInfo = processCarouselDataForDeepLinks(androidCarouselData);
797
+ return carouselLinkInfo.deepLinkValue;
798
+ }
799
+ return "";
714
800
  })(),
715
801
  deepLinkKeysValue: (() => {
716
- // Extract deep link keys from the URL
717
- const deepLinkValue = androidMainCta?.type === DEEP_LINK ? androidMainCta?.actionLink : (androidContentType?.cta?.type === DEEP_LINK ? androidContentType?.cta?.actionLink : "");
718
- if (deepLinkValue) {
719
- try {
720
- const url = new URL(deepLinkValue);
721
- const extractedKeys = [];
722
- url.searchParams.forEach((value, key) => {
723
- if (value === key) { // Only extract keys where value equals key
724
- extractedKeys.push(key);
802
+ // For video templates, prioritize CTA buttons over root level CTA
803
+ if (androidMediaType === VIDEO && androidButtons.length > 0) {
804
+ const firstButton = androidButtons[0];
805
+ if (firstButton?.type === DEEP_LINK && firstButton?.actionLink) {
806
+ const deepLinkValue = firstButton.actionLink;
807
+
808
+ if (deepLinkValue && deepLinkValue.includes('?')) {
809
+ try {
810
+ // Extract query parameters from deep link URL
811
+ const queryString = deepLinkValue.split('?')[1];
812
+ const searchParams = new URLSearchParams(queryString);
813
+ const extractedKeys = [];
814
+ searchParams.forEach((value, key) => {
815
+ if (value === key) { // Only extract keys where value equals key
816
+ extractedKeys.push(key);
817
+ }
818
+ });
819
+ return extractedKeys;
820
+ } catch (error) {
821
+ console.error("[MobilePushNew] Error extracting deep link keys:", error);
822
+ return [];
725
823
  }
726
- });
727
- return extractedKeys;
728
- } catch (error) {
729
- console.error("[MobilePushNew] Error extracting deep link keys:", error);
824
+ }
730
825
  return [];
731
826
  }
827
+ return [];
828
+ }
829
+ // If there's a root level CTA, extract keys from URL
830
+ if (androidMainCta?.type === DEEP_LINK || androidContentType?.cta?.type === DEEP_LINK) {
831
+ const deepLinkValue = androidMainCta?.type === DEEP_LINK ? androidMainCta?.actionLink : androidContentType?.cta?.actionLink;
832
+
833
+ if (deepLinkValue && deepLinkValue.includes('?')) {
834
+ try {
835
+ // Extract query parameters from deep link URL
836
+ const queryString = deepLinkValue.split('?')[1];
837
+ const searchParams = new URLSearchParams(queryString);
838
+ const extractedKeys = [];
839
+ searchParams.forEach((value, key) => {
840
+ if (value === key) { // Only extract keys where value equals key
841
+ extractedKeys.push(key);
842
+ }
843
+ });
844
+ return extractedKeys;
845
+ } catch (error) {
846
+ console.error("[MobilePushNew] Error extracting deep link keys:", error);
847
+ return [];
848
+ }
849
+ }
850
+ return [];
851
+ }
852
+ // Otherwise, check carousel data
853
+ if (androidMediaType === CAROUSEL) {
854
+ const carouselLinkInfo = processCarouselDataForDeepLinks(androidCarouselData);
855
+ return carouselLinkInfo.deepLinkKeysValue;
732
856
  }
733
857
  return [];
734
858
  })(),
735
- externalLinkValue: androidMainCta?.type === EXTERNAL_URL ? androidMainCta?.actionLink : (androidContentType?.cta?.type === EXTERNAL_URL ? androidContentType?.cta?.actionLink : ""),
859
+ externalLinkValue: (() => {
860
+ // For video templates, prioritize CTA buttons over root level CTA
861
+ if (androidMediaType === VIDEO && androidButtons.length > 0) {
862
+ const firstButton = androidButtons[0];
863
+ if (firstButton?.type === EXTERNAL_URL) {
864
+ return firstButton?.actionLink || "";
865
+ }
866
+ return "";
867
+ }
868
+ // If there's a root level CTA, use it
869
+ if (androidMainCta?.type === EXTERNAL_URL || androidContentType?.cta?.type === EXTERNAL_URL) {
870
+ return androidMainCta?.type === EXTERNAL_URL ? androidMainCta?.actionLink : androidContentType?.cta?.actionLink;
871
+ }
872
+ // Otherwise, check carousel data
873
+ if (androidMediaType === CAROUSEL) {
874
+ const carouselLinkInfo = processCarouselDataForDeepLinks(androidCarouselData);
875
+ return carouselLinkInfo.externalLinkValue;
876
+ }
877
+ return "";
878
+ })(),
736
879
  };
737
880
 
738
881
  stateUpdates.push(() => setAndroidContent(androidContentData));
@@ -826,18 +969,23 @@ const MobilePushNew = ({
826
969
  let deepLinkKeys = button?.deepLinkKeys || [];
827
970
  if (!deepLinkKeys?.length && button?.type === DEEP_LINK && button?.actionLink) {
828
971
  try {
829
- const url = new URL(button?.actionLink);
830
- const extractedKeys = [];
831
- url.searchParams.forEach((value, key) => {
832
- if (value === key) { // Only extract keys where value equals key
833
- extractedKeys.push(key);
972
+ // Extract query parameters from deep link URL using the same approach as main content
973
+ const deepLinkValue = button?.actionLink;
974
+ if (deepLinkValue && deepLinkValue.includes('?')) {
975
+ const queryString = deepLinkValue.split('?')[1];
976
+ const searchParams = new URLSearchParams(queryString);
977
+ const extractedKeys = [];
978
+ searchParams.forEach((value, key) => {
979
+ if (value === key) { // Only extract keys where value equals key
980
+ extractedKeys.push(key);
981
+ }
982
+ });
983
+ if (extractedKeys?.length > 0) {
984
+ deepLinkKeys = extractedKeys;
834
985
  }
835
- });
836
- if (extractedKeys?.length > 0) {
837
- deepLinkKeys = extractedKeys;
838
986
  }
839
987
  } catch (error) {
840
- console.error("[MobilePushNew] Error extracting deep link keys:", error);
988
+ console.error("[MobilePushNew] Error extracting deep link keys from CTA button:", error);
841
989
  }
842
990
  }
843
991
 
@@ -873,6 +1021,45 @@ const MobilePushNew = ({
873
1021
  }
874
1022
  }
875
1023
 
1024
+ // Determine actionOnClick and linkType for iOS - prioritize CTA buttons for video, root level CTA for others, carousel data as fallback
1025
+ const iosActionOnClick = (() => {
1026
+ // For video templates, prioritize CTA buttons over root level CTA
1027
+ if (iosMediaType === VIDEO && iosButtons.length > 0) {
1028
+ return true;
1029
+ }
1030
+ // If there's a root level CTA, use it
1031
+ if (!!iosMainCta || !!iosContentType?.cta) {
1032
+ return true;
1033
+ }
1034
+ // Otherwise, check carousel data
1035
+ if (iosMediaType === CAROUSEL) {
1036
+ const iosCarouselLinkInfo = processCarouselDataForDeepLinks(iosCarouselData);
1037
+ return iosCarouselLinkInfo.deepLinkValue || iosCarouselLinkInfo.externalLinkValue;
1038
+ }
1039
+ return false;
1040
+ })();
1041
+
1042
+ const iosLinkType = (() => {
1043
+ // For video templates, prioritize CTA buttons over root level CTA
1044
+ if (iosMediaType === VIDEO && iosButtons.length > 0) {
1045
+ const firstButton = iosButtons[0];
1046
+ return firstButton?.type === EXTERNAL_URL ? EXTERNAL_LINK : DEEP_LINK;
1047
+ }
1048
+ // If there's a root level CTA, use its type
1049
+ if (iosMainCta?.type === EXTERNAL_URL || iosContentType?.cta?.type === EXTERNAL_URL) {
1050
+ return EXTERNAL_LINK;
1051
+ }
1052
+ if (iosMainCta?.type === DEEP_LINK || iosContentType?.cta?.type === DEEP_LINK) {
1053
+ return DEEP_LINK;
1054
+ }
1055
+ // Otherwise, check carousel data
1056
+ if (iosMediaType === CAROUSEL) {
1057
+ const iosCarouselLinkInfo = processCarouselDataForDeepLinks(iosCarouselData);
1058
+ return iosCarouselLinkInfo.externalLinkValue ? EXTERNAL_LINK : DEEP_LINK;
1059
+ }
1060
+ return DEEP_LINK;
1061
+ })();
1062
+
876
1063
  // iOS content
877
1064
  const iosContentData = {
878
1065
  title: iosTitle,
@@ -882,53 +1069,83 @@ const MobilePushNew = ({
882
1069
  videoSrc: iosVideoSrc,
883
1070
  videoPreview: iosVideoPreview,
884
1071
  carouselData: iosCarouselData,
885
- // Handle root level CTA
886
- actionOnClick: !!iosMainCta || !!iosContentType?.cta,
887
- linkType: (iosMainCta?.type === EXTERNAL_URL ? EXTERNAL_LINK : DEEP_LINK) || (iosContentType?.cta?.type === EXTERNAL_URL ? EXTERNAL_LINK : DEEP_LINK),
1072
+ // Handle root level CTA or carousel data
1073
+ actionOnClick: iosActionOnClick,
1074
+ linkType: iosLinkType,
888
1075
  deepLinkValue: (() => {
889
- // Get the deep link value
890
- const deepLinkValue = iosMainCta?.type === DEEP_LINK ? iosMainCta?.actionLink : (iosContentType?.cta?.type === DEEP_LINK ? iosContentType?.cta?.actionLink : "");
1076
+ // If there's a root level CTA, use it
1077
+ if (iosMainCta?.type === DEEP_LINK || iosContentType?.cta?.type === DEEP_LINK) {
1078
+ const deepLinkValue = iosMainCta?.type === DEEP_LINK ? iosMainCta?.actionLink : iosContentType?.cta?.actionLink;
1079
+
1080
+ // If we have deep links available, find the matching one
1081
+ if (deepLink?.length > 0 && deepLinkValue) {
1082
+ // Try to find exact match first
1083
+ const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
1084
+ if (exactMatch) {
1085
+ return exactMatch.value;
1086
+ }
891
1087
 
892
- // If we have deep links available, find the matching one
893
- if (deepLink?.length > 0 && deepLinkValue) {
894
- // Try to find exact match first
895
- const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
896
- if (exactMatch) {
897
- return exactMatch.value;
1088
+ // Try to find match without query params
1089
+ const baseDeepLinkValue = deepLinkValue.split('?')[0];
1090
+ const partialMatch = deepLink.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
1091
+ if (partialMatch) {
1092
+ return partialMatch.value;
1093
+ }
898
1094
  }
899
1095
 
900
- // Try to find match without query params
901
- const baseDeepLinkValue = deepLinkValue.split('?')[0];
902
- const partialMatch = deepLink.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
903
- if (partialMatch) {
904
- return partialMatch.value;
905
- }
1096
+ // If no match found, return the base URL without query parameters
1097
+ return deepLinkValue ? deepLinkValue.split('?')[0] : "";
906
1098
  }
907
-
908
- // If no match found, return the base URL without query parameters
909
- return deepLinkValue ? deepLinkValue.split('?')[0] : "";
1099
+ // Otherwise, check carousel data
1100
+ if (iosMediaType === CAROUSEL) {
1101
+ const iosCarouselLinkInfo = processCarouselDataForDeepLinks(iosCarouselData);
1102
+ return iosCarouselLinkInfo.deepLinkValue;
1103
+ }
1104
+ return "";
910
1105
  })(),
911
1106
  deepLinkKeysValue: (() => {
912
- // Extract deep link keys from the URL
913
- const deepLinkValue = iosMainCta?.type === DEEP_LINK ? iosMainCta?.actionLink : (iosContentType?.cta?.type === DEEP_LINK ? iosContentType?.cta?.actionLink : "");
914
- if (deepLinkValue) {
915
- try {
916
- const url = new URL(deepLinkValue);
917
- const extractedKeys = [];
918
- url.searchParams.forEach((value, key) => {
919
- if (value === key) { // Only extract keys where value equals key
920
- extractedKeys.push(key);
921
- }
922
- });
923
- return extractedKeys;
924
- } catch (error) {
925
- console.error("[MobilePushNew] Error extracting deep link keys:", error);
926
- return [];
1107
+ // If there's a root level CTA, extract keys from URL
1108
+ if (iosMainCta?.type === DEEP_LINK || iosContentType?.cta?.type === DEEP_LINK) {
1109
+ const deepLinkValue = iosMainCta?.type === DEEP_LINK ? iosMainCta?.actionLink : iosContentType?.cta?.actionLink;
1110
+
1111
+ if (deepLinkValue && deepLinkValue.includes('?')) {
1112
+ try {
1113
+ // Extract query parameters from deep link URL
1114
+ const queryString = deepLinkValue.split('?')[1];
1115
+ const searchParams = new URLSearchParams(queryString);
1116
+ const extractedKeys = [];
1117
+ searchParams.forEach((value, key) => {
1118
+ if (value === key) { // Only extract keys where value equals key
1119
+ extractedKeys.push(key);
1120
+ }
1121
+ });
1122
+ return extractedKeys;
1123
+ } catch (error) {
1124
+ console.error("[MobilePushNew] Error extracting deep link keys:", error);
1125
+ return [];
1126
+ }
927
1127
  }
1128
+ return [];
1129
+ }
1130
+ // Otherwise, check carousel data
1131
+ if (iosMediaType === CAROUSEL) {
1132
+ const iosCarouselLinkInfo = processCarouselDataForDeepLinks(iosCarouselData);
1133
+ return iosCarouselLinkInfo.deepLinkKeysValue;
928
1134
  }
929
1135
  return [];
930
1136
  })(),
931
- externalLinkValue: iosMainCta?.type === EXTERNAL_URL ? iosMainCta?.actionLink : (iosContentType?.cta?.type === EXTERNAL_URL ? iosContentType?.cta?.actionLink : ""),
1137
+ externalLinkValue: (() => {
1138
+ // If there's a root level CTA, use it
1139
+ if (iosMainCta?.type === EXTERNAL_URL || iosContentType?.cta?.type === EXTERNAL_URL) {
1140
+ return iosMainCta?.type === EXTERNAL_URL ? iosMainCta?.actionLink : iosContentType?.cta?.actionLink;
1141
+ }
1142
+ // Otherwise, check carousel data
1143
+ if (iosMediaType === CAROUSEL) {
1144
+ const iosCarouselLinkInfo = processCarouselDataForDeepLinks(iosCarouselData);
1145
+ return iosCarouselLinkInfo.externalLinkValue;
1146
+ }
1147
+ return "";
1148
+ })(),
932
1149
  };
933
1150
 
934
1151
  stateUpdates.push(() => setIosContent(iosContentData));
@@ -974,7 +1191,10 @@ const MobilePushNew = ({
974
1191
  const stateUpdates = [];
975
1192
 
976
1193
  // Template name
977
- stateUpdates.push(() => setTemplateName(name));
1194
+ stateUpdates.push(() => {
1195
+ setTemplateName(name);
1196
+ templateNameRef.current = name;
1197
+ });
978
1198
 
979
1199
  // Process Android content
980
1200
  const androidContentType = templateContent?.ANDROID;
@@ -1045,18 +1265,23 @@ const MobilePushNew = ({
1045
1265
  let deepLinkKeys = button?.deepLinkKeys || [];
1046
1266
  if (!deepLinkKeys.length && button?.type === DEEP_LINK && button?.actionLink) {
1047
1267
  try {
1048
- const url = new URL(button?.actionLink);
1049
- const extractedKeys = [];
1050
- url.searchParams.forEach((value, key) => {
1051
- if (value === key) { // Only extract keys where value equals key
1052
- extractedKeys.push(key);
1268
+ // Extract query parameters from deep link URL using the same approach as main content
1269
+ const deepLinkValue = button?.actionLink;
1270
+ if (deepLinkValue && deepLinkValue.includes('?')) {
1271
+ const queryString = deepLinkValue.split('?')[1];
1272
+ const searchParams = new URLSearchParams(queryString);
1273
+ const extractedKeys = [];
1274
+ searchParams.forEach((value, key) => {
1275
+ if (value === key) { // Only extract keys where value equals key
1276
+ extractedKeys.push(key);
1277
+ }
1278
+ });
1279
+ if (extractedKeys?.length > 0) {
1280
+ deepLinkKeys = extractedKeys;
1053
1281
  }
1054
- });
1055
- if (extractedKeys?.length > 0) {
1056
- deepLinkKeys = extractedKeys;
1057
1282
  }
1058
1283
  } catch (error) {
1059
- console.error("[MobilePushNew] Error extracting deep link keys:", error);
1284
+ console.error("[MobilePushNew] Error extracting deep link keys from CTA button:", error);
1060
1285
  }
1061
1286
  }
1062
1287
 
@@ -1092,6 +1317,45 @@ const MobilePushNew = ({
1092
1317
  }
1093
1318
  }
1094
1319
 
1320
+ // Determine actionOnClick and linkType for Android - prioritize CTA buttons for video, root level CTA for others, carousel data as fallback
1321
+ const androidActionOnClick = (() => {
1322
+ // For video templates, prioritize CTA buttons over root level CTA
1323
+ if (androidMediaType === VIDEO && androidButtons.length > 0) {
1324
+ return true;
1325
+ }
1326
+ // If there's a root level CTA, use it
1327
+ if (!!androidMainCta || !!androidContentType?.cta) {
1328
+ return true;
1329
+ }
1330
+ // Otherwise, check carousel data
1331
+ if (androidMediaType === CAROUSEL) {
1332
+ const carouselLinkInfo = processCarouselDataForDeepLinks(androidCarouselData);
1333
+ return carouselLinkInfo.deepLinkValue || carouselLinkInfo.externalLinkValue;
1334
+ }
1335
+ return false;
1336
+ })();
1337
+
1338
+ const androidLinkType = (() => {
1339
+ // For video templates, prioritize CTA buttons over root level CTA
1340
+ if (androidMediaType === VIDEO && androidButtons.length > 0) {
1341
+ const firstButton = androidButtons[0];
1342
+ return firstButton?.type === EXTERNAL_URL ? EXTERNAL_LINK : DEEP_LINK;
1343
+ }
1344
+ // If there's a root level CTA, use its type
1345
+ if (androidMainCta?.type === EXTERNAL_URL || androidContentType?.cta?.type === EXTERNAL_URL) {
1346
+ return EXTERNAL_LINK;
1347
+ }
1348
+ if (androidMainCta?.type === DEEP_LINK || androidContentType?.cta?.type === DEEP_LINK) {
1349
+ return DEEP_LINK;
1350
+ }
1351
+ // Otherwise, check carousel data
1352
+ if (androidMediaType === CAROUSEL) {
1353
+ const carouselLinkInfo = processCarouselDataForDeepLinks(androidCarouselData);
1354
+ return carouselLinkInfo.externalLinkValue ? EXTERNAL_LINK : DEEP_LINK;
1355
+ }
1356
+ return DEEP_LINK;
1357
+ })();
1358
+
1095
1359
  // Process Android content
1096
1360
  const androidContentData = {
1097
1361
  title: androidTitle,
@@ -1101,53 +1365,145 @@ const MobilePushNew = ({
1101
1365
  videoSrc: androidVideoSrc,
1102
1366
  videoPreview: androidVideoPreview,
1103
1367
  carouselData: androidCarouselData,
1104
- // Handle root level CTA
1105
- actionOnClick: !!androidMainCta || !!androidContentType?.cta,
1106
- linkType: (androidMainCta?.type === EXTERNAL_URL ? EXTERNAL_LINK : DEEP_LINK) || (androidContentType?.cta?.type === EXTERNAL_URL ? EXTERNAL_LINK : DEEP_LINK),
1368
+ // Handle root level CTA or carousel data
1369
+ actionOnClick: androidActionOnClick,
1370
+ linkType: androidLinkType,
1107
1371
  deepLinkValue: (() => {
1108
- // Get the deep link value
1109
- const deepLinkValue = androidMainCta?.type === DEEP_LINK ? androidMainCta?.actionLink : (androidContentType?.cta?.type === DEEP_LINK ? androidContentType?.cta?.actionLink : "");
1110
-
1111
- // If we have deep links available, find the matching one
1112
- if (deepLink?.length > 0 && deepLinkValue) {
1113
- // Try to find exact match first
1114
- const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
1115
- if (exactMatch) {
1116
- return exactMatch.value;
1117
- }
1372
+ // For video templates, prioritize CTA buttons over root level CTA
1373
+ if (androidMediaType === VIDEO && androidButtons.length > 0) {
1374
+ const firstButton = androidButtons[0];
1375
+ if (firstButton?.type === DEEP_LINK && firstButton?.actionLink) {
1376
+ const deepLinkValue = firstButton.actionLink;
1377
+
1378
+ // If we have deep links available, find the matching one
1379
+ if (deepLink?.length > 0 && deepLinkValue) {
1380
+ // Try to find exact match first
1381
+ const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
1382
+ if (exactMatch) {
1383
+ return exactMatch.value;
1384
+ }
1385
+
1386
+ // Try to find match without query params
1387
+ const baseDeepLinkValue = deepLinkValue.split('?')[0];
1388
+ const partialMatch = deepLink.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
1389
+ if (partialMatch) {
1390
+ return partialMatch.value;
1391
+ }
1392
+ }
1118
1393
 
1119
- // Try to find match without query params
1120
- const baseDeepLinkValue = deepLinkValue.split('?')[0];
1121
- const partialMatch = deepLink.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
1122
- if (partialMatch) {
1123
- return partialMatch.value;
1394
+ // If no match found, return the base URL without query parameters
1395
+ return deepLinkValue ? deepLinkValue.split('?')[0] : "";
1124
1396
  }
1397
+ return "";
1125
1398
  }
1399
+ // If there's a root level CTA, use it
1400
+ if (androidMainCta?.type === DEEP_LINK || androidContentType?.cta?.type === DEEP_LINK) {
1401
+ const deepLinkValue = androidMainCta?.type === DEEP_LINK ? androidMainCta?.actionLink : androidContentType?.cta?.actionLink;
1402
+
1403
+ // If we have deep links available, find the matching one
1404
+ if (deepLink?.length > 0 && deepLinkValue) {
1405
+ // Try to find exact match first
1406
+ const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
1407
+ if (exactMatch) {
1408
+ return exactMatch.value;
1409
+ }
1126
1410
 
1127
- // If no match found, return the base URL without query parameters
1128
- return deepLinkValue ? deepLinkValue.split('?')[0] : "";
1411
+ // Try to find match without query params
1412
+ const baseDeepLinkValue = deepLinkValue.split('?')[0];
1413
+ const partialMatch = deepLink.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
1414
+ if (partialMatch) {
1415
+ return partialMatch.value;
1416
+ }
1417
+ }
1418
+
1419
+ // If no match found, return the base URL without query parameters
1420
+ return deepLinkValue ? deepLinkValue.split('?')[0] : "";
1421
+ }
1422
+ // Otherwise, check carousel data
1423
+ if (androidMediaType === CAROUSEL) {
1424
+ const carouselLinkInfo = processCarouselDataForDeepLinks(androidCarouselData);
1425
+ return carouselLinkInfo.deepLinkValue;
1426
+ }
1427
+ return "";
1129
1428
  })(),
1130
1429
  deepLinkKeysValue: (() => {
1131
- // Extract deep link keys from the URL
1132
- const deepLinkValue = androidMainCta?.type === DEEP_LINK ? androidMainCta?.actionLink : (androidContentType?.cta?.type === DEEP_LINK ? androidContentType?.cta?.actionLink : "");
1133
- if (deepLinkValue) {
1134
- try {
1135
- const url = new URL(deepLinkValue);
1136
- const extractedKeys = [];
1137
- url.searchParams.forEach((value, key) => {
1138
- if (value === key) { // Only extract keys where value equals key
1139
- extractedKeys.push(key);
1430
+ // For video templates, prioritize CTA buttons over root level CTA
1431
+ if (androidMediaType === VIDEO && androidButtons.length > 0) {
1432
+ const firstButton = androidButtons[0];
1433
+ if (firstButton?.type === DEEP_LINK && firstButton?.actionLink) {
1434
+ const deepLinkValue = firstButton.actionLink;
1435
+
1436
+ if (deepLinkValue && deepLinkValue.includes('?')) {
1437
+ try {
1438
+ // Extract query parameters from deep link URL
1439
+ const queryString = deepLinkValue.split('?')[1];
1440
+ const searchParams = new URLSearchParams(queryString);
1441
+ const extractedKeys = [];
1442
+ searchParams.forEach((value, key) => {
1443
+ if (value === key) { // Only extract keys where value equals key
1444
+ extractedKeys.push(key);
1445
+ }
1446
+ });
1447
+ return extractedKeys;
1448
+ } catch (error) {
1449
+ console.error("[MobilePushNew] Error extracting deep link keys:", error);
1450
+ return [];
1140
1451
  }
1141
- });
1142
- return extractedKeys;
1143
- } catch (error) {
1144
- console.error("[MobilePushNew] Error extracting deep link keys:", error);
1452
+ }
1145
1453
  return [];
1146
1454
  }
1455
+ return [];
1456
+ }
1457
+ // If there's a root level CTA, extract keys from URL
1458
+ if (androidMainCta?.type === DEEP_LINK || androidContentType?.cta?.type === DEEP_LINK) {
1459
+ const deepLinkValue = androidMainCta?.type === DEEP_LINK ? androidMainCta?.actionLink : androidContentType?.cta?.actionLink;
1460
+
1461
+ if (deepLinkValue && deepLinkValue.includes('?')) {
1462
+ try {
1463
+ // Extract query parameters from deep link URL
1464
+ const queryString = deepLinkValue.split('?')[1];
1465
+ const searchParams = new URLSearchParams(queryString);
1466
+ const extractedKeys = [];
1467
+ searchParams.forEach((value, key) => {
1468
+ if (value === key) { // Only extract keys where value equals key
1469
+ extractedKeys.push(key);
1470
+ }
1471
+ });
1472
+ return extractedKeys;
1473
+ } catch (error) {
1474
+ console.error("[MobilePushNew] Error extracting deep link keys:", error);
1475
+ return [];
1476
+ }
1477
+ }
1478
+ return [];
1479
+ }
1480
+ // Otherwise, check carousel data
1481
+ if (androidMediaType === CAROUSEL) {
1482
+ const carouselLinkInfo = processCarouselDataForDeepLinks(androidCarouselData);
1483
+ return carouselLinkInfo.deepLinkKeysValue;
1147
1484
  }
1148
1485
  return [];
1149
1486
  })(),
1150
- externalLinkValue: androidMainCta?.type === EXTERNAL_URL ? androidMainCta?.actionLink : (androidContentType?.cta?.type === EXTERNAL_URL ? androidContentType?.cta?.actionLink : ""),
1487
+ externalLinkValue: (() => {
1488
+ // For video templates, prioritize CTA buttons over root level CTA
1489
+ if (androidMediaType === VIDEO && androidButtons.length > 0) {
1490
+ const firstButton = androidButtons[0];
1491
+ if (firstButton?.type === EXTERNAL_URL) {
1492
+ return firstButton?.actionLink || "";
1493
+ }
1494
+ return "";
1495
+ }
1496
+ // If there's a root level CTA, use it
1497
+ if (androidMainCta?.type === EXTERNAL_URL || androidContentType?.cta?.type === EXTERNAL_URL) {
1498
+ return androidMainCta?.type === EXTERNAL_URL ? androidMainCta?.actionLink : androidContentType?.cta?.actionLink;
1499
+ }
1500
+ // Otherwise, check carousel data
1501
+ if (androidMediaType === CAROUSEL) {
1502
+ const carouselLinkInfo = processCarouselDataForDeepLinks(androidCarouselData);
1503
+ return carouselLinkInfo.externalLinkValue;
1504
+ }
1505
+ return "";
1506
+ })(),
1151
1507
  };
1152
1508
 
1153
1509
  stateUpdates.push(() => setAndroidContent(androidContentData));
@@ -1241,18 +1597,23 @@ const MobilePushNew = ({
1241
1597
  let deepLinkKeys = button?.deepLinkKeys || [];
1242
1598
  if (!deepLinkKeys?.length && button?.type === DEEP_LINK && button?.actionLink) {
1243
1599
  try {
1244
- const url = new URL(button?.actionLink);
1245
- const extractedKeys = [];
1246
- url.searchParams.forEach((value, key) => {
1247
- if (value === key) { // Only extract keys where value equals key
1248
- extractedKeys.push(key);
1600
+ // Extract query parameters from deep link URL using the same approach as main content
1601
+ const deepLinkValue = button?.actionLink;
1602
+ if (deepLinkValue && deepLinkValue.includes('?')) {
1603
+ const queryString = deepLinkValue.split('?')[1];
1604
+ const searchParams = new URLSearchParams(queryString);
1605
+ const extractedKeys = [];
1606
+ searchParams.forEach((value, key) => {
1607
+ if (value === key) { // Only extract keys where value equals key
1608
+ extractedKeys.push(key);
1609
+ }
1610
+ });
1611
+ if (extractedKeys?.length > 0) {
1612
+ deepLinkKeys = extractedKeys;
1249
1613
  }
1250
- });
1251
- if (extractedKeys?.length > 0) {
1252
- deepLinkKeys = extractedKeys;
1253
1614
  }
1254
1615
  } catch (error) {
1255
- console.error("[MobilePushNew] Error extracting deep link keys:", error);
1616
+ console.error("[MobilePushNew] Error extracting deep link keys from CTA button:", error);
1256
1617
  }
1257
1618
  }
1258
1619
 
@@ -1288,6 +1649,45 @@ const MobilePushNew = ({
1288
1649
  }
1289
1650
  }
1290
1651
 
1652
+ // Determine actionOnClick and linkType for iOS - prioritize CTA buttons for video, root level CTA for others, carousel data as fallback
1653
+ const iosActionOnClick = (() => {
1654
+ // For video templates, prioritize CTA buttons over root level CTA
1655
+ if (iosMediaType === VIDEO && iosButtons.length > 0) {
1656
+ return true;
1657
+ }
1658
+ // If there's a root level CTA, use it
1659
+ if (!!iosMainCta || !!iosContentType?.cta) {
1660
+ return true;
1661
+ }
1662
+ // Otherwise, check carousel data
1663
+ if (iosMediaType === CAROUSEL) {
1664
+ const iosCarouselLinkInfo = processCarouselDataForDeepLinks(iosCarouselData);
1665
+ return iosCarouselLinkInfo.deepLinkValue || iosCarouselLinkInfo.externalLinkValue;
1666
+ }
1667
+ return false;
1668
+ })();
1669
+
1670
+ const iosLinkType = (() => {
1671
+ // For video templates, prioritize CTA buttons over root level CTA
1672
+ if (iosMediaType === VIDEO && iosButtons.length > 0) {
1673
+ const firstButton = iosButtons[0];
1674
+ return firstButton?.type === EXTERNAL_URL ? EXTERNAL_LINK : DEEP_LINK;
1675
+ }
1676
+ // If there's a root level CTA, use its type
1677
+ if (iosMainCta?.type === EXTERNAL_URL || iosContentType?.cta?.type === EXTERNAL_URL) {
1678
+ return EXTERNAL_LINK;
1679
+ }
1680
+ if (iosMainCta?.type === DEEP_LINK || iosContentType?.cta?.type === DEEP_LINK) {
1681
+ return DEEP_LINK;
1682
+ }
1683
+ // Otherwise, check carousel data
1684
+ if (iosMediaType === CAROUSEL) {
1685
+ const iosCarouselLinkInfo = processCarouselDataForDeepLinks(iosCarouselData);
1686
+ return iosCarouselLinkInfo.externalLinkValue ? EXTERNAL_LINK : DEEP_LINK;
1687
+ }
1688
+ return DEEP_LINK;
1689
+ })();
1690
+
1291
1691
  // Process iOS content
1292
1692
  const iosContentData = {
1293
1693
  title: iosTitle,
@@ -1297,53 +1697,145 @@ const MobilePushNew = ({
1297
1697
  videoSrc: iosVideoSrc,
1298
1698
  videoPreview: iosVideoPreview,
1299
1699
  carouselData: iosCarouselData,
1300
- // Handle root level CTA
1301
- actionOnClick: !!iosMainCta || !!iosContentType?.cta,
1302
- linkType: (iosMainCta?.type === EXTERNAL_URL ? EXTERNAL_LINK : DEEP_LINK) || (iosContentType?.cta?.type === EXTERNAL_URL ? EXTERNAL_LINK : DEEP_LINK),
1700
+ // Handle root level CTA or carousel data
1701
+ actionOnClick: iosActionOnClick,
1702
+ linkType: iosLinkType,
1303
1703
  deepLinkValue: (() => {
1304
- // Get the deep link value
1305
- const deepLinkValue = iosMainCta?.type === DEEP_LINK ? iosMainCta?.actionLink : (iosContentType?.cta?.type === DEEP_LINK ? iosContentType?.cta?.actionLink : "");
1306
-
1307
- // If we have deep links available, find the matching one
1308
- if (deepLink?.length > 0 && deepLinkValue) {
1309
- // Try to find exact match first
1310
- const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
1311
- if (exactMatch) {
1312
- return exactMatch.value;
1313
- }
1704
+ // For video templates, prioritize CTA buttons over root level CTA
1705
+ if (iosMediaType === VIDEO && iosButtons.length > 0) {
1706
+ const firstButton = iosButtons[0];
1707
+ if (firstButton?.type === DEEP_LINK && firstButton?.actionLink) {
1708
+ const deepLinkValue = firstButton.actionLink;
1709
+
1710
+ // If we have deep links available, find the matching one
1711
+ if (deepLink?.length > 0 && deepLinkValue) {
1712
+ // Try to find exact match first
1713
+ const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
1714
+ if (exactMatch) {
1715
+ return exactMatch.value;
1716
+ }
1314
1717
 
1315
- // Try to find match without query params
1316
- const baseDeepLinkValue = deepLinkValue.split('?')[0];
1317
- const partialMatch = deepLink.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
1318
- if (partialMatch) {
1319
- return partialMatch.value;
1718
+ // Try to find match without query params
1719
+ const baseDeepLinkValue = deepLinkValue.split('?')[0];
1720
+ const partialMatch = deepLink.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
1721
+ if (partialMatch) {
1722
+ return partialMatch.value;
1723
+ }
1724
+ }
1725
+
1726
+ // If no match found, return the base URL without query parameters
1727
+ return deepLinkValue ? deepLinkValue.split('?')[0] : "";
1320
1728
  }
1729
+ return "";
1321
1730
  }
1731
+ // If there's a root level CTA, use it
1732
+ if (iosMainCta?.type === DEEP_LINK || iosContentType?.cta?.type === DEEP_LINK) {
1733
+ const deepLinkValue = iosMainCta?.type === DEEP_LINK ? iosMainCta?.actionLink : iosContentType?.cta?.actionLink;
1734
+
1735
+ // If we have deep links available, find the matching one
1736
+ if (deepLink?.length > 0 && deepLinkValue) {
1737
+ // Try to find exact match first
1738
+ const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
1739
+ if (exactMatch) {
1740
+ return exactMatch.value;
1741
+ }
1742
+
1743
+ // Try to find match without query params
1744
+ const baseDeepLinkValue = deepLinkValue.split('?')[0];
1745
+ const partialMatch = deepLink.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
1746
+ if (partialMatch) {
1747
+ return partialMatch.value;
1748
+ }
1749
+ }
1322
1750
 
1323
- // If no match found, return the base URL without query parameters
1324
- return deepLinkValue ? deepLinkValue.split('?')[0] : "";
1751
+ // If no match found, return the base URL without query parameters
1752
+ return deepLinkValue ? deepLinkValue.split('?')[0] : "";
1753
+ }
1754
+ // Otherwise, check carousel data
1755
+ if (iosMediaType === CAROUSEL) {
1756
+ const iosCarouselLinkInfo = processCarouselDataForDeepLinks(iosCarouselData);
1757
+ return iosCarouselLinkInfo.deepLinkValue;
1758
+ }
1759
+ return "";
1325
1760
  })(),
1326
1761
  deepLinkKeysValue: (() => {
1327
- // Extract deep link keys from the URL
1328
- const deepLinkValue = iosMainCta?.type === DEEP_LINK ? iosMainCta?.actionLink : (iosContentType?.cta?.type === DEEP_LINK ? iosContentType?.cta?.actionLink : "");
1329
- if (deepLinkValue) {
1330
- try {
1331
- const url = new URL(deepLinkValue);
1332
- const extractedKeys = [];
1333
- url.searchParams.forEach((value, key) => {
1334
- if (value === key) { // Only extract keys where value equals key
1335
- extractedKeys.push(key);
1762
+ // For video templates, prioritize CTA buttons over root level CTA
1763
+ if (iosMediaType === VIDEO && iosButtons.length > 0) {
1764
+ const firstButton = iosButtons[0];
1765
+ if (firstButton?.type === DEEP_LINK && firstButton?.actionLink) {
1766
+ const deepLinkValue = firstButton.actionLink;
1767
+
1768
+ if (deepLinkValue && deepLinkValue.includes('?')) {
1769
+ try {
1770
+ // Extract query parameters from deep link URL
1771
+ const queryString = deepLinkValue.split('?')[1];
1772
+ const searchParams = new URLSearchParams(queryString);
1773
+ const extractedKeys = [];
1774
+ searchParams.forEach((value, key) => {
1775
+ if (value === key) { // Only extract keys where value equals key
1776
+ extractedKeys.push(key);
1777
+ }
1778
+ });
1779
+ return extractedKeys;
1780
+ } catch (error) {
1781
+ console.error("[MobilePushNew] Error extracting deep link keys:", error);
1782
+ return [];
1336
1783
  }
1337
- });
1338
- return extractedKeys;
1339
- } catch (error) {
1340
- console.error("[MobilePushNew] Error extracting deep link keys:", error);
1784
+ }
1341
1785
  return [];
1342
1786
  }
1787
+ return [];
1788
+ }
1789
+ // If there's a root level CTA, extract keys from URL
1790
+ if (iosMainCta?.type === DEEP_LINK || iosContentType?.cta?.type === DEEP_LINK) {
1791
+ const deepLinkValue = iosMainCta?.type === DEEP_LINK ? iosMainCta?.actionLink : iosContentType?.cta?.actionLink;
1792
+
1793
+ if (deepLinkValue && deepLinkValue.includes('?')) {
1794
+ try {
1795
+ // Extract query parameters from deep link URL
1796
+ const queryString = deepLinkValue.split('?')[1];
1797
+ const searchParams = new URLSearchParams(queryString);
1798
+ const extractedKeys = [];
1799
+ searchParams.forEach((value, key) => {
1800
+ if (value === key) { // Only extract keys where value equals key
1801
+ extractedKeys.push(key);
1802
+ }
1803
+ });
1804
+ return extractedKeys;
1805
+ } catch (error) {
1806
+ console.error("[MobilePushNew] Error extracting deep link keys:", error);
1807
+ return [];
1808
+ }
1809
+ }
1810
+ return [];
1811
+ }
1812
+ // Otherwise, check carousel data
1813
+ if (iosMediaType === CAROUSEL) {
1814
+ const iosCarouselLinkInfo = processCarouselDataForDeepLinks(iosCarouselData);
1815
+ return iosCarouselLinkInfo.deepLinkKeysValue;
1343
1816
  }
1344
1817
  return [];
1345
1818
  })(),
1346
- externalLinkValue: iosMainCta?.type === EXTERNAL_URL ? iosMainCta?.actionLink : (iosContentType?.cta?.type === EXTERNAL_URL ? iosContentType?.cta?.actionLink : ""),
1819
+ externalLinkValue: (() => {
1820
+ // For video templates, prioritize CTA buttons over root level CTA
1821
+ if (iosMediaType === VIDEO && iosButtons.length > 0) {
1822
+ const firstButton = iosButtons[0];
1823
+ if (firstButton?.type === EXTERNAL_URL) {
1824
+ return firstButton?.actionLink || "";
1825
+ }
1826
+ return "";
1827
+ }
1828
+ // If there's a root level CTA, use it
1829
+ if (iosMainCta?.type === EXTERNAL_URL || iosContentType?.cta?.type === EXTERNAL_URL) {
1830
+ return iosMainCta?.type === EXTERNAL_URL ? iosMainCta?.actionLink : iosContentType?.cta?.actionLink;
1831
+ }
1832
+ // Otherwise, check carousel data
1833
+ if (iosMediaType === CAROUSEL) {
1834
+ const iosCarouselLinkInfo = processCarouselDataForDeepLinks(iosCarouselData);
1835
+ return iosCarouselLinkInfo.externalLinkValue;
1836
+ }
1837
+ return "";
1838
+ })(),
1347
1839
  };
1348
1840
 
1349
1841
  stateUpdates.push(() => setIosContent(iosContentData));
@@ -1802,7 +2294,9 @@ const MobilePushNew = ({
1802
2294
  return;
1803
2295
  }
1804
2296
  // Only require templateName in full mode
1805
- if (isFullMode && !templateName?.trim()) {
2297
+ // Use ref to get the latest template name value for validation
2298
+ const currentTemplateName = templateNameRef.current || templateName;
2299
+ if (isFullMode && !currentTemplateName?.trim()) {
1806
2300
  CapNotification.error({
1807
2301
  message: formatMessage(messages.emptyTemplateErrorMessage),
1808
2302
  });
@@ -1810,7 +2304,8 @@ const MobilePushNew = ({
1810
2304
  }
1811
2305
 
1812
2306
  // In library mode, set templateName programmatically if empty
1813
- let finalTemplateName = templateName;
2307
+ // Use ref to get the latest template name value to avoid closure issues
2308
+ let finalTemplateName = templateNameRef.current || templateName;
1814
2309
  if (!isFullMode && (!finalTemplateName || !finalTemplateName.trim())) {
1815
2310
  if (androidContent?.title && androidContent.title.trim()) {
1816
2311
  finalTemplateName = androidContent.title.trim();
@@ -1840,10 +2335,10 @@ const MobilePushNew = ({
1840
2335
  if (androidContent?.linkType === DEEP_LINK && androidContent?.deepLinkValue) {
1841
2336
  // Use the same matching logic as deep link value extraction
1842
2337
  let selectedDeepLink = null;
1843
-
2338
+
1844
2339
  // Try to find exact match first
1845
2340
  selectedDeepLink = deepLink?.find((link) => link.value === androidContent?.deepLinkValue);
1846
-
2341
+
1847
2342
  // If no exact match, try to find match without query params
1848
2343
  if (!selectedDeepLink && androidContent?.deepLinkValue) {
1849
2344
  const baseDeepLinkValue = androidContent?.deepLinkValue.split('?')[0];
@@ -1873,7 +2368,7 @@ const MobilePushNew = ({
1873
2368
  const baseDeepLinkValue = iosContent?.deepLinkValue.split('?')[0];
1874
2369
  selectedDeepLink = deepLink?.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
1875
2370
  }
1876
-
2371
+
1877
2372
  const hasKeysDefined = selectedDeepLink?.keys && selectedDeepLink.keys.length > 0;
1878
2373
 
1879
2374
  // Only require keys if the selected deep link has keys defined
@@ -1941,7 +2436,7 @@ const MobilePushNew = ({
1941
2436
  ...processedIosContent.expandableDetails,
1942
2437
  ctas: savedCtas.map((cta) => {
1943
2438
  let actionLink = cta?.url;
1944
-
2439
+
1945
2440
  // Append deep link keys to URL if they exist
1946
2441
  if (cta?.urlType === DEEP_LINK && cta?.deepLinkKeys?.length > 0) {
1947
2442
  const deepLinkKeysArray = Array.isArray(cta?.deepLinkKeys) ? cta?.deepLinkKeys : [cta?.deepLinkKeys];
@@ -2126,7 +2621,6 @@ const MobilePushNew = ({
2126
2621
  }, [
2127
2622
  templateNameError,
2128
2623
  formatMessage,
2129
- templateName,
2130
2624
  androidContent,
2131
2625
  iosContent,
2132
2626
  imageSrc,
@@ -2183,6 +2677,8 @@ const MobilePushNew = ({
2183
2677
  (ev) => {
2184
2678
  const { value } = ev.target;
2185
2679
  setTemplateName(value);
2680
+ // Update ref to always have the latest value
2681
+ templateNameRef.current = value;
2186
2682
  const isInvalid = !value || value.trim() === "";
2187
2683
  setTemplateNameError(isInvalid);
2188
2684
  if (value && onEnterTemplateName) {
@@ -2443,6 +2939,66 @@ const MobilePushNew = ({
2443
2939
  };
2444
2940
  }, [handleSave]);
2445
2941
 
2942
+ // Function to process carousel data and extract deep link information
2943
+ const processCarouselDataForDeepLinks = useCallback((carouselData = []) => {
2944
+ if (!carouselData || carouselData?.length === 0) {
2945
+ return { deepLinkValue: "", deepLinkKeysValue: [], externalLinkValue: "" };
2946
+ }
2947
+
2948
+ // Find the first carousel card with actionOnClick enabled
2949
+ const activeCard = carouselData.find((card) => card?.buttons
2950
+ && card?.buttons?.length > 0
2951
+ && card?.buttons[0]?.actionOnClick);
2952
+
2953
+ if (!activeCard || !activeCard?.buttons || activeCard?.buttons?.length === 0) {
2954
+ return { deepLinkValue: "", deepLinkKeysValue: [], externalLinkValue: "" };
2955
+ }
2956
+
2957
+ const button = activeCard?.buttons[0];
2958
+
2959
+ if (button?.linkType === DEEP_LINK) {
2960
+ const deepLinkValue = button?.deepLinkValue || "";
2961
+ const deepLinkKeys = button.deepLinkKeys || [];
2962
+
2963
+ // Find matching deep link from available options
2964
+ let finalDeepLinkValue = deepLinkValue;
2965
+ if (deepLink?.length > 0 && deepLinkValue) {
2966
+ // Try to find exact match first
2967
+ const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
2968
+ if (exactMatch) {
2969
+ finalDeepLinkValue = exactMatch.value;
2970
+ } else {
2971
+ // Try to find match without query params
2972
+ const baseDeepLinkValue = deepLinkValue.split('?')[0];
2973
+ const partialMatch = deepLink.find((link) => link.value === baseDeepLinkValue
2974
+ || link.value.split('?')[0] === baseDeepLinkValue);
2975
+ if (partialMatch) {
2976
+ // Return the selected deep link option from dropdown, like other media types
2977
+ finalDeepLinkValue = partialMatch.value;
2978
+ } else {
2979
+ // If no match found, return the original value (this handles custom deep links)
2980
+ finalDeepLinkValue = deepLinkValue;
2981
+ }
2982
+ }
2983
+ }
2984
+
2985
+ return {
2986
+ deepLinkValue: finalDeepLinkValue,
2987
+ deepLinkKeysValue: deepLinkKeys,
2988
+ externalLinkValue: "",
2989
+ };
2990
+ } if (button?.linkType === EXTERNAL_LINK) {
2991
+ return {
2992
+ deepLinkValue: "",
2993
+ deepLinkKeysValue: [],
2994
+ externalLinkValue: button.externalLinkValue || "",
2995
+ };
2996
+ }
2997
+
2998
+ return { deepLinkValue: "", deepLinkKeysValue: [], externalLinkValue: "" };
2999
+ }, [deepLink]);
3000
+
3001
+
2446
3002
  return (
2447
3003
  <CapSpin
2448
3004
  spinning={spin || editData?.editTemplateInProgress || fetchingLiquidValidation || getTemplateDetailsInProgress}