@sonordev/site-kit 5.3.1 → 5.3.2

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.
Files changed (236) hide show
  1. package/agent-manifest.json +1 -1
  2. package/dist/AnalyticsProvider-2XK54UZW.mjs +11 -0
  3. package/dist/{AnalyticsProvider-NA7EMJCA.mjs.map → AnalyticsProvider-2XK54UZW.mjs.map} +1 -1
  4. package/dist/AnalyticsProvider-PM7SOGOS.js +32 -0
  5. package/dist/{AnalyticsProvider-XE3ADUUH.js.map → AnalyticsProvider-PM7SOGOS.js.map} +1 -1
  6. package/dist/{BlogViewTracker-DVJHZ7CM.js → BlogViewTracker-3BIUF5TI.js} +6 -6
  7. package/dist/{BlogViewTracker-DVJHZ7CM.js.map → BlogViewTracker-3BIUF5TI.js.map} +1 -1
  8. package/dist/{BlogViewTracker-MKJYTTJQ.mjs → BlogViewTracker-KFUDRDQK.mjs} +5 -5
  9. package/dist/{BlogViewTracker-MKJYTTJQ.mjs.map → BlogViewTracker-KFUDRDQK.mjs.map} +1 -1
  10. package/dist/ChatWidget-4PHZHGG5.mjs +11 -0
  11. package/dist/{ChatWidget-BD4F4XLD.mjs.map → ChatWidget-4PHZHGG5.mjs.map} +1 -1
  12. package/dist/ChatWidget-7BYSGNO2.js +20 -0
  13. package/dist/{ChatWidget-BZ3KOSXG.js.map → ChatWidget-7BYSGNO2.js.map} +1 -1
  14. package/dist/EngageWidget-D6M6QWEC.mjs +9 -0
  15. package/dist/{EngageWidget-L7B6PCM3.mjs.map → EngageWidget-D6M6QWEC.mjs.map} +1 -1
  16. package/dist/EngageWidget-Q4ITKTMJ.js +18 -0
  17. package/dist/{EngageWidget-JPP6EDCJ.js.map → EngageWidget-Q4ITKTMJ.js.map} +1 -1
  18. package/dist/{FileField-7WPRONDS.mjs → FileField-PQQDX4IR.mjs} +5 -5
  19. package/dist/{FileField-7WPRONDS.mjs.map → FileField-PQQDX4IR.mjs.map} +1 -1
  20. package/dist/{FileField-GHT7444Y.js → FileField-YBBIJOCK.js} +6 -6
  21. package/dist/{FileField-GHT7444Y.js.map → FileField-YBBIJOCK.js.map} +1 -1
  22. package/dist/{FormSpotlight-WZVS6HHR.mjs → FormSpotlight-7TIIWFTP.mjs} +3 -3
  23. package/dist/{FormSpotlight-WZVS6HHR.mjs.map → FormSpotlight-7TIIWFTP.mjs.map} +1 -1
  24. package/dist/{FormSpotlight-BB2IB7IX.js → FormSpotlight-WUN24F3P.js} +15 -15
  25. package/dist/{FormSpotlight-BB2IB7IX.js.map → FormSpotlight-WUN24F3P.js.map} +1 -1
  26. package/dist/{FormStage-FLBLXENZ.js → FormStage-CM7OVLUT.js} +13 -13
  27. package/dist/{FormStage-FLBLXENZ.js.map → FormStage-CM7OVLUT.js.map} +1 -1
  28. package/dist/{FormStage-Y3NHHMV2.mjs → FormStage-TFN2GIBO.mjs} +3 -3
  29. package/dist/{FormStage-Y3NHHMV2.mjs.map → FormStage-TFN2GIBO.mjs.map} +1 -1
  30. package/dist/ManagedForm-N63YGVNY.js +23 -0
  31. package/dist/{ManagedForm-2OPCHDNJ.js.map → ManagedForm-N63YGVNY.js.map} +1 -1
  32. package/dist/ManagedForm-ZUXLHEQU.mjs +14 -0
  33. package/dist/{ManagedForm-AJM6D4SK.mjs.map → ManagedForm-ZUXLHEQU.mjs.map} +1 -1
  34. package/dist/{ManagedNewsletterForm-MJI2JXIB.mjs → ManagedNewsletterForm-4AVKTZ2A.mjs} +7 -7
  35. package/dist/{ManagedNewsletterForm-MJI2JXIB.mjs.map → ManagedNewsletterForm-4AVKTZ2A.mjs.map} +1 -1
  36. package/dist/{ManagedNewsletterForm-L2ZHJ7F4.js → ManagedNewsletterForm-PIVJTU5L.js} +8 -8
  37. package/dist/{ManagedNewsletterForm-L2ZHJ7F4.js.map → ManagedNewsletterForm-PIVJTU5L.js.map} +1 -1
  38. package/dist/{SignalCore-G2VM7NUP.js → SignalCore-2M5TISM7.js} +11 -11
  39. package/dist/{SignalCore-G2VM7NUP.js.map → SignalCore-2M5TISM7.js.map} +1 -1
  40. package/dist/{SignalCore-23YDDSWO.mjs → SignalCore-LT4NCPOR.mjs} +5 -5
  41. package/dist/{SignalCore-23YDDSWO.mjs.map → SignalCore-LT4NCPOR.mjs.map} +1 -1
  42. package/dist/SitemapSync-7OBOJG2L.js +18 -0
  43. package/dist/{SitemapSync-T2N3TCWF.js.map → SitemapSync-7OBOJG2L.js.map} +1 -1
  44. package/dist/SitemapSync-G3OLECFI.mjs +9 -0
  45. package/dist/{SitemapSync-YLWMU6J3.mjs.map → SitemapSync-G3OLECFI.mjs.map} +1 -1
  46. package/dist/SitemapSync.d.ts.map +1 -1
  47. package/dist/analytics/AnalyticsProvider.d.ts +11 -1
  48. package/dist/analytics/AnalyticsProvider.d.ts.map +1 -1
  49. package/dist/analytics/WebVitals.d.ts +7 -1
  50. package/dist/analytics/WebVitals.d.ts.map +1 -1
  51. package/dist/analytics/index.d.ts +1 -0
  52. package/dist/analytics/index.d.ts.map +1 -1
  53. package/dist/analytics/index.js +25 -12
  54. package/dist/analytics/index.mjs +6 -5
  55. package/dist/analytics/send-gate.d.ts +119 -0
  56. package/dist/analytics/send-gate.d.ts.map +1 -0
  57. package/dist/analytics/send-gate.test.d.ts +20 -0
  58. package/dist/analytics/send-gate.test.d.ts.map +1 -0
  59. package/dist/blog/index.js +20 -20
  60. package/dist/blog/index.mjs +3 -3
  61. package/dist/blog/server-ui.js +14 -14
  62. package/dist/blog/server-ui.mjs +2 -2
  63. package/dist/blog/types.d.ts +3 -0
  64. package/dist/blog/types.d.ts.map +1 -1
  65. package/dist/{chunk-EDZWNCSE.js → chunk-3EPMDPWI.js} +2 -2
  66. package/dist/{chunk-EDZWNCSE.js.map → chunk-3EPMDPWI.js.map} +1 -1
  67. package/dist/{chunk-7UPPYERC.mjs → chunk-42F5EK24.mjs} +4 -4
  68. package/dist/{chunk-7UPPYERC.mjs.map → chunk-42F5EK24.mjs.map} +1 -1
  69. package/dist/{chunk-5HMN3FXL.js → chunk-4DE2KJ7R.js} +8 -8
  70. package/dist/{chunk-5HMN3FXL.js.map → chunk-4DE2KJ7R.js.map} +1 -1
  71. package/dist/{chunk-DTX4R45S.js → chunk-5BZDHZCN.js} +4 -4
  72. package/dist/{chunk-DTX4R45S.js.map → chunk-5BZDHZCN.js.map} +1 -1
  73. package/dist/{chunk-I72AUITZ.mjs → chunk-67CHHDBL.mjs} +3 -3
  74. package/dist/{chunk-I72AUITZ.mjs.map → chunk-67CHHDBL.mjs.map} +1 -1
  75. package/dist/{chunk-UJOEN4X6.js → chunk-6AZTRTCG.js} +15 -15
  76. package/dist/{chunk-UJOEN4X6.js.map → chunk-6AZTRTCG.js.map} +1 -1
  77. package/dist/{chunk-PA5ZVCW2.mjs → chunk-6QABCGM6.mjs} +3 -3
  78. package/dist/{chunk-PA5ZVCW2.mjs.map → chunk-6QABCGM6.mjs.map} +1 -1
  79. package/dist/{chunk-77HT6TYK.mjs → chunk-6VG65AIA.mjs} +3 -3
  80. package/dist/{chunk-77HT6TYK.mjs.map → chunk-6VG65AIA.mjs.map} +1 -1
  81. package/dist/{chunk-2MPOO6QJ.js → chunk-757HXAYX.js} +3 -3
  82. package/dist/{chunk-2MPOO6QJ.js.map → chunk-757HXAYX.js.map} +1 -1
  83. package/dist/{chunk-ZMFJXFUY.js → chunk-A3NNUKFA.js} +3 -3
  84. package/dist/{chunk-ZMFJXFUY.js.map → chunk-A3NNUKFA.js.map} +1 -1
  85. package/dist/{chunk-NW5CBNRU.mjs → chunk-AVM4OZHR.mjs} +3 -3
  86. package/dist/{chunk-NW5CBNRU.mjs.map → chunk-AVM4OZHR.mjs.map} +1 -1
  87. package/dist/{chunk-FH4LLJFL.mjs → chunk-AXAIUCSF.mjs} +9 -8
  88. package/dist/chunk-AXAIUCSF.mjs.map +1 -0
  89. package/dist/{chunk-AKQA5ZYZ.mjs → chunk-CQUA2AUA.mjs} +3 -3
  90. package/dist/{chunk-AKQA5ZYZ.mjs.map → chunk-CQUA2AUA.mjs.map} +1 -1
  91. package/dist/chunk-D37M7MIH.js +8 -0
  92. package/dist/{chunk-TMQKZ4DO.js.map → chunk-D37M7MIH.js.map} +1 -1
  93. package/dist/{chunk-ISKJLXB4.mjs → chunk-DVH3JHZ3.mjs} +4 -4
  94. package/dist/{chunk-ISKJLXB4.mjs.map → chunk-DVH3JHZ3.mjs.map} +1 -1
  95. package/dist/{chunk-LHD45PGP.js → chunk-DYKFC7WY.js} +8 -8
  96. package/dist/{chunk-LHD45PGP.js.map → chunk-DYKFC7WY.js.map} +1 -1
  97. package/dist/{chunk-X4PL7R63.mjs → chunk-DZDWBQKA.mjs} +3 -3
  98. package/dist/{chunk-X4PL7R63.mjs.map → chunk-DZDWBQKA.mjs.map} +1 -1
  99. package/dist/{chunk-GTK3CGWF.js → chunk-E33HJMRP.js} +6 -6
  100. package/dist/{chunk-GTK3CGWF.js.map → chunk-E33HJMRP.js.map} +1 -1
  101. package/dist/{chunk-4S7BHFGT.js → chunk-FDVE56JS.js} +3 -3
  102. package/dist/{chunk-4S7BHFGT.js.map → chunk-FDVE56JS.js.map} +1 -1
  103. package/dist/{chunk-SHZXSIRH.js → chunk-FFJVQWKO.js} +4 -4
  104. package/dist/{chunk-SHZXSIRH.js.map → chunk-FFJVQWKO.js.map} +1 -1
  105. package/dist/{chunk-HIV5YK5G.js → chunk-G3YUSRCL.js} +4 -4
  106. package/dist/{chunk-HIV5YK5G.js.map → chunk-G3YUSRCL.js.map} +1 -1
  107. package/dist/{chunk-APL44ZVK.js → chunk-GFNXWS3I.js} +5 -5
  108. package/dist/{chunk-APL44ZVK.js.map → chunk-GFNXWS3I.js.map} +1 -1
  109. package/dist/{chunk-GPH3VVLP.js → chunk-GPNBBUEN.js} +3 -3
  110. package/dist/{chunk-GPH3VVLP.js.map → chunk-GPNBBUEN.js.map} +1 -1
  111. package/dist/{chunk-VGX6G3TA.mjs → chunk-HDQTZAGE.mjs} +3 -3
  112. package/dist/{chunk-VGX6G3TA.mjs.map → chunk-HDQTZAGE.mjs.map} +1 -1
  113. package/dist/{chunk-COAVBUMS.mjs → chunk-HVFXFPUJ.mjs} +3 -3
  114. package/dist/{chunk-COAVBUMS.mjs.map → chunk-HVFXFPUJ.mjs.map} +1 -1
  115. package/dist/{chunk-XR47TOGW.mjs → chunk-JSLYNYTB.mjs} +3 -3
  116. package/dist/{chunk-XR47TOGW.mjs.map → chunk-JSLYNYTB.mjs.map} +1 -1
  117. package/dist/{chunk-W47J6ZZG.mjs → chunk-JTO3K5B7.mjs} +4 -4
  118. package/dist/{chunk-W47J6ZZG.mjs.map → chunk-JTO3K5B7.mjs.map} +1 -1
  119. package/dist/{chunk-QG7WHAGD.js → chunk-K37JPEQW.js} +15 -15
  120. package/dist/{chunk-QG7WHAGD.js.map → chunk-K37JPEQW.js.map} +1 -1
  121. package/dist/{chunk-DBJRJ2Q2.mjs → chunk-KOP3DPIR.mjs} +4 -4
  122. package/dist/{chunk-DBJRJ2Q2.mjs.map → chunk-KOP3DPIR.mjs.map} +1 -1
  123. package/dist/{chunk-LFJRMY4V.js → chunk-KPFPSOYS.js} +12 -12
  124. package/dist/{chunk-LFJRMY4V.js.map → chunk-KPFPSOYS.js.map} +1 -1
  125. package/dist/{chunk-KP56C66Z.js → chunk-M7FWXEXC.js} +126 -188
  126. package/dist/chunk-M7FWXEXC.js.map +1 -0
  127. package/dist/{chunk-UYR22S67.js → chunk-MANX6422.js} +7 -7
  128. package/dist/{chunk-UYR22S67.js.map → chunk-MANX6422.js.map} +1 -1
  129. package/dist/{chunk-WZZYTFDV.mjs → chunk-N3C323NY.mjs} +8 -3
  130. package/dist/chunk-N3C323NY.mjs.map +1 -0
  131. package/dist/{chunk-R4PFWVGZ.mjs → chunk-NSLYY62T.mjs} +4 -4
  132. package/dist/{chunk-R4PFWVGZ.mjs.map → chunk-NSLYY62T.mjs.map} +1 -1
  133. package/dist/chunk-NVSWTDWU.mjs +25 -0
  134. package/dist/chunk-NVSWTDWU.mjs.map +1 -0
  135. package/dist/{chunk-WD57YWY5.mjs → chunk-OC6PU7U2.mjs} +3 -3
  136. package/dist/{chunk-WD57YWY5.mjs.map → chunk-OC6PU7U2.mjs.map} +1 -1
  137. package/dist/{chunk-2VQ5YXOD.js → chunk-OIJ435IZ.js} +18 -18
  138. package/dist/{chunk-2VQ5YXOD.js.map → chunk-OIJ435IZ.js.map} +1 -1
  139. package/dist/chunk-OL2QBWAU.js +29 -0
  140. package/dist/chunk-OL2QBWAU.js.map +1 -0
  141. package/dist/chunk-OUERH2T4.mjs +6 -0
  142. package/dist/{chunk-HRQ4367C.mjs.map → chunk-OUERH2T4.mjs.map} +1 -1
  143. package/dist/{chunk-VLR2UYO4.js → chunk-PEEQMI7U.js} +12 -11
  144. package/dist/chunk-PEEQMI7U.js.map +1 -0
  145. package/dist/{chunk-47566YF4.js → chunk-PZXKFHPO.js} +14 -14
  146. package/dist/{chunk-47566YF4.js.map → chunk-PZXKFHPO.js.map} +1 -1
  147. package/dist/{chunk-SI7R3IJX.mjs → chunk-QZ54OCWD.mjs} +7 -7
  148. package/dist/{chunk-SI7R3IJX.mjs.map → chunk-QZ54OCWD.mjs.map} +1 -1
  149. package/dist/{chunk-GQTSQR63.js → chunk-R3LYTIVN.js} +10 -5
  150. package/dist/chunk-R3LYTIVN.js.map +1 -0
  151. package/dist/{chunk-26JXNW7B.mjs → chunk-RO55G3OA.mjs} +2 -2
  152. package/dist/{chunk-26JXNW7B.mjs.map → chunk-RO55G3OA.mjs.map} +1 -1
  153. package/dist/{chunk-4IMZ45YA.mjs → chunk-TS3N3LGZ.mjs} +4 -4
  154. package/dist/{chunk-4IMZ45YA.mjs.map → chunk-TS3N3LGZ.mjs.map} +1 -1
  155. package/dist/{chunk-TAIGHH5J.js → chunk-W23TMUKB.js} +9 -9
  156. package/dist/{chunk-TAIGHH5J.js.map → chunk-W23TMUKB.js.map} +1 -1
  157. package/dist/{chunk-5TGSM5EQ.js → chunk-XQZTOWS3.js} +14 -14
  158. package/dist/{chunk-5TGSM5EQ.js.map → chunk-XQZTOWS3.js.map} +1 -1
  159. package/dist/{chunk-GM5E6R5W.mjs → chunk-XW5KNCWJ.mjs} +3 -3
  160. package/dist/{chunk-GM5E6R5W.mjs.map → chunk-XW5KNCWJ.mjs.map} +1 -1
  161. package/dist/{chunk-AJBJH3BA.mjs → chunk-Y7SRO7MJ.mjs} +127 -189
  162. package/dist/chunk-Y7SRO7MJ.mjs.map +1 -0
  163. package/dist/{chunk-AVPMSJCQ.js → chunk-Z7K5AMCE.js} +4 -4
  164. package/dist/{chunk-AVPMSJCQ.js.map → chunk-Z7K5AMCE.js.map} +1 -1
  165. package/dist/{chunk-4HL6CAZ7.mjs → chunk-ZKR5AJV5.mjs} +4 -4
  166. package/dist/{chunk-4HL6CAZ7.mjs.map → chunk-ZKR5AJV5.mjs.map} +1 -1
  167. package/dist/{chunk-DN6A6KXH.mjs → chunk-ZOJ3TLO5.mjs} +3 -3
  168. package/dist/{chunk-DN6A6KXH.mjs.map → chunk-ZOJ3TLO5.mjs.map} +1 -1
  169. package/dist/cli/index.js +3 -3
  170. package/dist/cli/index.mjs +1 -1
  171. package/dist/client/index.js +4 -4
  172. package/dist/client/index.mjs +3 -3
  173. package/dist/commerce/index.js +58 -57
  174. package/dist/commerce/index.mjs +7 -6
  175. package/dist/engage/index.js +10 -10
  176. package/dist/engage/index.mjs +7 -7
  177. package/dist/fleet/index.js +8 -8
  178. package/dist/fleet/index.mjs +4 -4
  179. package/dist/forms/index.js +16 -16
  180. package/dist/forms/index.mjs +9 -9
  181. package/dist/forms/server.js +10 -10
  182. package/dist/forms/server.mjs +8 -8
  183. package/dist/forms/static.js +7 -7
  184. package/dist/forms/static.mjs +6 -6
  185. package/dist/images/index.js +11 -11
  186. package/dist/images/index.mjs +4 -4
  187. package/dist/index.js +65 -64
  188. package/dist/index.js.map +1 -1
  189. package/dist/index.mjs +11 -10
  190. package/dist/index.mjs.map +1 -1
  191. package/dist/layout/SiteKitClientProviders.d.ts.map +1 -1
  192. package/dist/layout/client.d.ts.map +1 -1
  193. package/dist/layout/client.js +8 -8
  194. package/dist/layout/client.mjs +7 -7
  195. package/dist/layout/index.js +10 -10
  196. package/dist/layout/index.mjs +8 -8
  197. package/dist/layout/types.d.ts +16 -0
  198. package/dist/layout/types.d.ts.map +1 -1
  199. package/dist/maps/index.js +5 -5
  200. package/dist/maps/index.mjs +3 -3
  201. package/dist/search/index.js +4 -4
  202. package/dist/search/index.mjs +3 -3
  203. package/dist/seo/client.js +6 -5
  204. package/dist/seo/client.mjs +5 -4
  205. package/dist/seo/index.js +6 -5
  206. package/dist/seo/index.js.map +1 -1
  207. package/dist/seo/index.mjs +5 -4
  208. package/dist/seo/index.mjs.map +1 -1
  209. package/dist/server/index.js +3 -3
  210. package/dist/server/index.mjs +2 -2
  211. package/dist/shared/frame.d.ts +71 -0
  212. package/dist/shared/frame.d.ts.map +1 -0
  213. package/dist/shared/version.d.ts +1 -1
  214. package/dist/signal/index.js +11 -11
  215. package/dist/signal/index.mjs +2 -2
  216. package/dist/sync/index.js +16 -16
  217. package/dist/sync/index.mjs +4 -4
  218. package/package.json +1 -1
  219. package/dist/AnalyticsProvider-NA7EMJCA.mjs +0 -10
  220. package/dist/AnalyticsProvider-XE3ADUUH.js +0 -31
  221. package/dist/ChatWidget-BD4F4XLD.mjs +0 -11
  222. package/dist/ChatWidget-BZ3KOSXG.js +0 -20
  223. package/dist/EngageWidget-JPP6EDCJ.js +0 -18
  224. package/dist/EngageWidget-L7B6PCM3.mjs +0 -9
  225. package/dist/ManagedForm-2OPCHDNJ.js +0 -23
  226. package/dist/ManagedForm-AJM6D4SK.mjs +0 -14
  227. package/dist/SitemapSync-T2N3TCWF.js +0 -17
  228. package/dist/SitemapSync-YLWMU6J3.mjs +0 -8
  229. package/dist/chunk-AJBJH3BA.mjs.map +0 -1
  230. package/dist/chunk-FH4LLJFL.mjs.map +0 -1
  231. package/dist/chunk-GQTSQR63.js.map +0 -1
  232. package/dist/chunk-HRQ4367C.mjs +0 -6
  233. package/dist/chunk-KP56C66Z.js.map +0 -1
  234. package/dist/chunk-TMQKZ4DO.js +0 -8
  235. package/dist/chunk-VLR2UYO4.js.map +0 -1
  236. package/dist/chunk-WZZYTFDV.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { DEFAULT_HONEYPOT_FIELD } from './chunk-TMVKRQGJ.mjs';
2
- import { sonorFetch } from './chunk-4HL6CAZ7.mjs';
2
+ import { sonorFetch } from './chunk-ZKR5AJV5.mjs';
3
3
 
4
4
  // src/forms/defaultSuccessMessage.ts
5
5
  var DEFAULT_FORM_SUCCESS_MESSAGE = "Thank you for your submission! We will be in touch soon.";
@@ -215,5 +215,5 @@ async function submitForm({
215
215
  }
216
216
 
217
217
  export { DEFAULT_FORM_SUCCESS_MESSAGE, getApiConfig, normalizeFormConfig, submitForm };
218
- //# sourceMappingURL=chunk-GM5E6R5W.mjs.map
219
- //# sourceMappingURL=chunk-GM5E6R5W.mjs.map
218
+ //# sourceMappingURL=chunk-XW5KNCWJ.mjs.map
219
+ //# sourceMappingURL=chunk-XW5KNCWJ.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/forms/defaultSuccessMessage.ts","../src/forms/normalize-config.ts","../src/forms/recaptcha.ts","../src/forms/ga4-identity.ts","../src/forms/submitForm.ts"],"names":[],"mappings":"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","file":"chunk-GM5E6R5W.mjs","sourcesContent":["/** Shown when the API omits or returns an empty `success_message`. */\nexport const DEFAULT_FORM_SUCCESS_MESSAGE =\n 'Thank you for your submission! We will be in touch soon.'\n","/**\n * Shared form-config normalizer — the ONE place a raw\n * /api/public/forms/config payload becomes a ManagedFormConfig.\n *\n * Deliberately has no `'use client'` directive and no hooks, so it is usable\n * from a Server Component (StaticForm) as well as from useForm's client\n * fetch. Both the server shell and the hydrated enhancement must agree on\n * field order, step count and success copy or the swap visibly jumps, so\n * there must never be a second copy of this.\n */\n\nimport type { ManagedFormConfig } from './types'\nimport { DEFAULT_FORM_SUCCESS_MESSAGE } from './defaultSuccessMessage'\n\n/**\n * Normalize a raw /api/public/forms/config payload into ManagedFormConfig.\n * Single source of truth — used for both the client fetch and server-provided\n * `initialForm`, so the two paths can never drift.\n */\nexport function normalizeFormConfig(data: any): ManagedFormConfig {\n if (data.steps) {\n data.steps.sort((a: any, b: any) => (a.step_number || 0) - (b.step_number || 0))\n }\n if (data.fields) {\n data.fields.sort((a: any, b: any) => (a.sort_order || 0) - (b.sort_order || 0))\n }\n\n const total_steps = data.steps?.length || 1\n const is_multi_step = total_steps > 1\n\n const apiSuccess =\n typeof data.success_message === 'string' ? data.success_message.trim() : ''\n const success_message =\n apiSuccess ||\n (typeof (data as { successMessage?: string }).successMessage === 'string'\n ? String((data as { successMessage?: string }).successMessage).trim()\n : '') ||\n DEFAULT_FORM_SUCCESS_MESSAGE\n\n return {\n ...data,\n success_message,\n total_steps,\n is_multi_step,\n }\n}\n","/**\n * reCAPTCHA Enterprise - Client-side token generation for site-kit forms\n *\n * Site key is read from:\n * - window.__SITE_KIT_RECAPTCHA_SITE_KEY__ (set by SiteKitLayout)\n * - process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY (when bundled in Next.js app)\n */\n\nfunction getSiteKey(explicitSiteKey?: string): string | undefined {\n if (typeof window === 'undefined') return undefined\n if (explicitSiteKey) return explicitSiteKey\n const win = window as any\n return win.__SITE_KIT_RECAPTCHA_SITE_KEY__ ?? process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY\n}\n\n/** Max time to wait for reCAPTCHA Enterprise to become usable before giving up. */\nconst RECAPTCHA_LOAD_TIMEOUT_MS = 10000\n\nfunction loadScript(siteKey: string): Promise<any> {\n return new Promise((resolve) => {\n if (typeof window === 'undefined') {\n resolve(null)\n return\n }\n const win = window as any\n if (win.grecaptcha?.enterprise) {\n resolve(win.grecaptcha)\n return\n }\n\n // Never hang the form: if the script is blocked (ad-blocker), stalls, or\n // never initializes `grecaptcha.enterprise`, resolve null after a timeout.\n // The caller treats a null result as \"no token\" rather than waiting forever.\n let settled = false\n const finish = (value: any) => {\n if (settled) return\n settled = true\n resolve(value)\n }\n const giveUp = setTimeout(() => finish(null), RECAPTCHA_LOAD_TIMEOUT_MS)\n\n const waitForReady = () => {\n if (settled) return\n if (win.grecaptcha?.enterprise) {\n clearTimeout(giveUp)\n finish(win.grecaptcha)\n return\n }\n setTimeout(waitForReady, 50)\n }\n\n const existing = document.querySelector('script[src*=\"recaptcha/enterprise\"]')\n if (existing) {\n waitForReady()\n return\n }\n\n const script = document.createElement('script')\n script.src = `https://www.google.com/recaptcha/enterprise.js?render=${siteKey}`\n script.async = true\n script.onload = () => waitForReady()\n script.onerror = () => {\n clearTimeout(giveUp)\n finish(null)\n }\n document.head.appendChild(script)\n })\n}\n\n/**\n * Get a reCAPTCHA Enterprise token for form submission.\n * Returns null if not configured or in SSR.\n */\nexport async function getRecaptchaToken(explicitSiteKey?: string): Promise<string | null> {\n const siteKey = getSiteKey(explicitSiteKey)\n if (!siteKey || typeof window === 'undefined') return null\n try {\n const grecaptcha = await loadScript(siteKey)\n if (!grecaptcha?.enterprise?.execute) return null\n // loadScript only waits for grecaptcha.enterprise to EXIST — execute()\n // before enterprise.ready() rejects while the widget initializes (cold\n // page load = every first-visit submitter). A swallowed rejection here\n // means no token, and a requireRecaptcha project hard-rejects the lead.\n await new Promise<void>((resolve) => grecaptcha.enterprise.ready(resolve))\n const token = await grecaptcha.enterprise.execute(siteKey, { action: 'submit' })\n return token || null\n } catch (err) {\n // One retry after a beat — first-execute flakes persist on slow devices\n // even post-ready, and a dropped token is a dropped lead.\n try {\n await new Promise((resolve) => setTimeout(resolve, 800))\n const win = window as any\n const token = await win.grecaptcha.enterprise.execute(siteKey, { action: 'submit' })\n return token || null\n } catch (retryErr) {\n console.warn('[site-kit reCAPTCHA]', retryErr)\n return null\n }\n }\n}\n","/**\n * Reads the visitor's GA4 identity out of their own first-party cookies so a\n * lead conversion can be reported SERVER-side.\n *\n * Why the server has to do the reporting: Sonor's form-submit endpoint answers\n * with a byte-identical success payload whether it accepted a submission or\n * quarantined it as spam (deliberately — a bot must never learn it was\n * caught). So the browser cannot tell a real lead from a filtered one, and a\n * site firing its own ad conversion bills both. The accept/reject verdict only\n * exists on the server, so the conversion has to be sent from there — and to\n * send it, the server needs the GA4 identity that only the browser can see.\n *\n * Nothing here is a new identifier: these are cookies Google's own tag already\n * set on this visitor. We read them, we never write them.\n */\n\nexport interface Ga4Identity {\n /** GA4 client id, from `_ga`. Without it a server-sent event has no identity. */\n gaClientId?: string\n /**\n * GA4 session ids keyed by container id (the measurement id minus `G-`), from\n * the `_ga_<CONTAINER>` cookies.\n *\n * A map rather than one value because a page may carry more than one GA4\n * property, and picking the wrong one would silently attach the lead to the\n * wrong session — the sender knows which measurement id it is configured for,\n * this side does not.\n */\n gaSessions?: Record<string, string>\n}\n\nfunction readCookie(jar: string, name: string): string | undefined {\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n const match = jar.match(new RegExp(`(?:^|;\\\\s*)${escaped}=([^;]*)`))\n return match ? decodeURIComponent(match[1]) : undefined\n}\n\nexport function readGa4Identity(): Ga4Identity {\n if (typeof document === 'undefined') return {}\n const jar = document.cookie || ''\n if (!jar) return {}\n\n const identity: Ga4Identity = {}\n\n // `_ga` is `GA1.<depth>.<id1>.<id2>`; the client id is the last two parts\n // joined. Reading the raw cookie rather than the trailing two segments\n // blindly keeps it correct when the depth prefix varies by domain scope.\n const ga = readCookie(jar, '_ga')\n if (ga) {\n const parts = ga.split('.')\n if (parts.length >= 4) {\n const clientId = `${parts[parts.length - 2]}.${parts[parts.length - 1]}`\n if (/^\\d+\\.\\d+$/.test(clientId)) identity.gaClientId = clientId\n }\n }\n\n // `_ga_<CONTAINER>` is `GS<v>.<depth>.<session_id>.<session_number>....`\n const sessions: Record<string, string> = {}\n for (const raw of jar.split(';')) {\n const cookie = raw.trim()\n const eq = cookie.indexOf('=')\n if (eq < 0) continue\n const name = cookie.slice(0, eq)\n const container = /^_ga_([A-Z0-9]+)$/i.exec(name)?.[1]\n if (!container) continue\n const parts = decodeURIComponent(cookie.slice(eq + 1)).split('.')\n if (parts.length >= 3 && /^\\d+$/.test(parts[2])) sessions[container] = parts[2]\n }\n if (Object.keys(sessions).length > 0) identity.gaSessions = sessions\n\n return identity\n}\n","/**\n * @sonordev/site-kit/forms - Shared submission logic\n *\n * Single source of truth for sending a managed form to the Sonor API. Both\n * <ManagedForm> (via FormClient) and the headless useForm() hook submit through\n * here, so the request shape, retry behaviour, reCAPTCHA handling, and error\n * parsing can never drift between the two paths.\n */\n\nimport { sonorFetch } from '../shared/sonorFetch'\nimport { getRecaptchaToken } from './recaptcha'\nimport { DEFAULT_HONEYPOT_FIELD } from './contract'\nimport { readGa4Identity } from './ga4-identity'\nimport type { ManagedFormConfig } from './types'\n\n// The honeypot trap-field name lives once in the shared forms contract\n// (single source of truth for site-kit's client + sonor-api's intake).\n// Re-exported so existing importers of this path keep resolving it.\nexport { DEFAULT_HONEYPOT_FIELD }\n\nexport function getApiConfig(): { apiUrl: string; apiKey: string | undefined } {\n // Server branch must honor the same env override SiteKitLayout feeds into\n // __SITE_KIT_API_URL__, or SSR-rendered absolute URLs (the native form\n // action) would point at prod from a staging site.\n const apiUrl =\n typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : process.env.SONOR_API_URL || process.env.NEXT_PUBLIC_SONOR_API_URL || 'https://api.sonor.io'\n const apiKey =\n typeof window !== 'undefined' ? (window as any).__SITE_KIT_API_KEY__ : undefined\n return { apiUrl, apiKey }\n}\n\nfunction getUTMParams(): Record<string, string | null> {\n if (typeof window === 'undefined') return {}\n const params = new URLSearchParams(window.location.search)\n const out: Record<string, string | null> = {}\n for (const key of ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content']) {\n out[key] = params.get(key)\n }\n return out\n}\n\nexport interface SubmitFormArgs {\n config: ManagedFormConfig\n /**\n * Field values to submit. The caller must pass VISIBLE values only —\n * conditionally-hidden fields should be excluded so stale values are not sent.\n */\n values: Record<string, unknown>\n /** Honeypot input value (empty string for the headless hook, which has no honeypot UI). */\n honeypotValue: string\n /** Timestamp (ms) the form was first rendered — a weak anti-bot timing signal. */\n formLoadedAt: number\n}\n\n/**\n * Submit a managed form. Throws on failure (network, timeout, or a non-2xx\n * response) with a human-readable message; resolves with the parsed API\n * response on success.\n */\nexport async function submitForm({\n config,\n values,\n honeypotValue,\n formLoadedAt,\n}: SubmitFormArgs): Promise<unknown> {\n const { apiUrl, apiKey } = getApiConfig()\n if (!apiKey) {\n throw new Error('API key is required. Set SONOR_API_KEY in your environment.')\n }\n\n // reCAPTCHA token is fetched right before the POST so it cannot expire.\n const recaptchaToken = config.recaptcha_enabled\n ? await getRecaptchaToken(config.recaptcha_site_key)\n : null\n if (config.recaptcha_enabled && !recaptchaToken) {\n throw new Error('Verification could not be completed. Please try again.')\n }\n\n const honeypotFieldName = config.honeypot_field || DEFAULT_HONEYPOT_FIELD\n const utm = getUTMParams()\n // The visitor's existing GA4 cookies, so Sonor can report an accepted lead\n // as a conversion server-side. Nothing is written or created here — see\n // ga4-identity.ts for why the server, not this browser, has to do it.\n const ga4 = readGa4Identity()\n\n const payload = {\n formId: config.id,\n form_id: config.id,\n data: {\n ...values,\n ...(config.honeypot_enabled ? { [honeypotFieldName]: honeypotValue } : {}),\n },\n metadata: {\n pageUrl: typeof window !== 'undefined' ? window.location.href : null,\n referrer: typeof document !== 'undefined' ? document.referrer || null : null,\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : null,\n sessionId:\n typeof sessionStorage !== 'undefined' ? sessionStorage.getItem('_sk_sid') : null,\n // Anonymous visitor id (_sk_vid) — the same id Analytics/Signal stamp on\n // page views, so the Sonor side can bind this lead to its browsing session\n // (page -> lead attribution). Sent on every submission; null pre-hydration.\n visitorId:\n typeof localStorage !== 'undefined' ? localStorage.getItem('_sk_vid') : null,\n recaptchaToken: recaptchaToken || undefined,\n utmSource: utm.utm_source,\n utmMedium: utm.utm_medium,\n utmCampaign: utm.utm_campaign,\n utmTerm: utm.utm_term,\n utmContent: utm.utm_content,\n ...ga4,\n // Sub-site host — preserved on form_submissions for lead attribution\n // across multi-site projects. Resolved by SiteKitClientProviders.\n site:\n typeof window !== 'undefined'\n ? (window as { __SITE_KIT_SITE__?: string }).__SITE_KIT_SITE__ ||\n window.location.host\n : undefined,\n _formLoadedAt: formLoadedAt,\n },\n }\n\n const response = await sonorFetch(\n `${apiUrl}/api/public/forms/submit`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(payload),\n },\n { retries: 2, timeoutMs: 20000 },\n )\n\n const data = await response.json().catch(() => null)\n\n if (!response.ok) {\n const msg = (\n data?.message ??\n data?.error ??\n (response.statusText || `HTTP ${response.status}`)\n )\n .toString()\n .trim()\n throw new Error(\n msg ? `Failed to submit form: ${msg}` : `Failed to submit form (${response.status})`,\n )\n }\n\n return data\n}\n"]}
1
+ {"version":3,"sources":["../src/forms/defaultSuccessMessage.ts","../src/forms/normalize-config.ts","../src/forms/recaptcha.ts","../src/forms/ga4-identity.ts","../src/forms/submitForm.ts"],"names":[],"mappings":"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","file":"chunk-XW5KNCWJ.mjs","sourcesContent":["/** Shown when the API omits or returns an empty `success_message`. */\nexport const DEFAULT_FORM_SUCCESS_MESSAGE =\n 'Thank you for your submission! We will be in touch soon.'\n","/**\n * Shared form-config normalizer — the ONE place a raw\n * /api/public/forms/config payload becomes a ManagedFormConfig.\n *\n * Deliberately has no `'use client'` directive and no hooks, so it is usable\n * from a Server Component (StaticForm) as well as from useForm's client\n * fetch. Both the server shell and the hydrated enhancement must agree on\n * field order, step count and success copy or the swap visibly jumps, so\n * there must never be a second copy of this.\n */\n\nimport type { ManagedFormConfig } from './types'\nimport { DEFAULT_FORM_SUCCESS_MESSAGE } from './defaultSuccessMessage'\n\n/**\n * Normalize a raw /api/public/forms/config payload into ManagedFormConfig.\n * Single source of truth — used for both the client fetch and server-provided\n * `initialForm`, so the two paths can never drift.\n */\nexport function normalizeFormConfig(data: any): ManagedFormConfig {\n if (data.steps) {\n data.steps.sort((a: any, b: any) => (a.step_number || 0) - (b.step_number || 0))\n }\n if (data.fields) {\n data.fields.sort((a: any, b: any) => (a.sort_order || 0) - (b.sort_order || 0))\n }\n\n const total_steps = data.steps?.length || 1\n const is_multi_step = total_steps > 1\n\n const apiSuccess =\n typeof data.success_message === 'string' ? data.success_message.trim() : ''\n const success_message =\n apiSuccess ||\n (typeof (data as { successMessage?: string }).successMessage === 'string'\n ? String((data as { successMessage?: string }).successMessage).trim()\n : '') ||\n DEFAULT_FORM_SUCCESS_MESSAGE\n\n return {\n ...data,\n success_message,\n total_steps,\n is_multi_step,\n }\n}\n","/**\n * reCAPTCHA Enterprise - Client-side token generation for site-kit forms\n *\n * Site key is read from:\n * - window.__SITE_KIT_RECAPTCHA_SITE_KEY__ (set by SiteKitLayout)\n * - process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY (when bundled in Next.js app)\n */\n\nfunction getSiteKey(explicitSiteKey?: string): string | undefined {\n if (typeof window === 'undefined') return undefined\n if (explicitSiteKey) return explicitSiteKey\n const win = window as any\n return win.__SITE_KIT_RECAPTCHA_SITE_KEY__ ?? process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY\n}\n\n/** Max time to wait for reCAPTCHA Enterprise to become usable before giving up. */\nconst RECAPTCHA_LOAD_TIMEOUT_MS = 10000\n\nfunction loadScript(siteKey: string): Promise<any> {\n return new Promise((resolve) => {\n if (typeof window === 'undefined') {\n resolve(null)\n return\n }\n const win = window as any\n if (win.grecaptcha?.enterprise) {\n resolve(win.grecaptcha)\n return\n }\n\n // Never hang the form: if the script is blocked (ad-blocker), stalls, or\n // never initializes `grecaptcha.enterprise`, resolve null after a timeout.\n // The caller treats a null result as \"no token\" rather than waiting forever.\n let settled = false\n const finish = (value: any) => {\n if (settled) return\n settled = true\n resolve(value)\n }\n const giveUp = setTimeout(() => finish(null), RECAPTCHA_LOAD_TIMEOUT_MS)\n\n const waitForReady = () => {\n if (settled) return\n if (win.grecaptcha?.enterprise) {\n clearTimeout(giveUp)\n finish(win.grecaptcha)\n return\n }\n setTimeout(waitForReady, 50)\n }\n\n const existing = document.querySelector('script[src*=\"recaptcha/enterprise\"]')\n if (existing) {\n waitForReady()\n return\n }\n\n const script = document.createElement('script')\n script.src = `https://www.google.com/recaptcha/enterprise.js?render=${siteKey}`\n script.async = true\n script.onload = () => waitForReady()\n script.onerror = () => {\n clearTimeout(giveUp)\n finish(null)\n }\n document.head.appendChild(script)\n })\n}\n\n/**\n * Get a reCAPTCHA Enterprise token for form submission.\n * Returns null if not configured or in SSR.\n */\nexport async function getRecaptchaToken(explicitSiteKey?: string): Promise<string | null> {\n const siteKey = getSiteKey(explicitSiteKey)\n if (!siteKey || typeof window === 'undefined') return null\n try {\n const grecaptcha = await loadScript(siteKey)\n if (!grecaptcha?.enterprise?.execute) return null\n // loadScript only waits for grecaptcha.enterprise to EXIST — execute()\n // before enterprise.ready() rejects while the widget initializes (cold\n // page load = every first-visit submitter). A swallowed rejection here\n // means no token, and a requireRecaptcha project hard-rejects the lead.\n await new Promise<void>((resolve) => grecaptcha.enterprise.ready(resolve))\n const token = await grecaptcha.enterprise.execute(siteKey, { action: 'submit' })\n return token || null\n } catch (err) {\n // One retry after a beat — first-execute flakes persist on slow devices\n // even post-ready, and a dropped token is a dropped lead.\n try {\n await new Promise((resolve) => setTimeout(resolve, 800))\n const win = window as any\n const token = await win.grecaptcha.enterprise.execute(siteKey, { action: 'submit' })\n return token || null\n } catch (retryErr) {\n console.warn('[site-kit reCAPTCHA]', retryErr)\n return null\n }\n }\n}\n","/**\n * Reads the visitor's GA4 identity out of their own first-party cookies so a\n * lead conversion can be reported SERVER-side.\n *\n * Why the server has to do the reporting: Sonor's form-submit endpoint answers\n * with a byte-identical success payload whether it accepted a submission or\n * quarantined it as spam (deliberately — a bot must never learn it was\n * caught). So the browser cannot tell a real lead from a filtered one, and a\n * site firing its own ad conversion bills both. The accept/reject verdict only\n * exists on the server, so the conversion has to be sent from there — and to\n * send it, the server needs the GA4 identity that only the browser can see.\n *\n * Nothing here is a new identifier: these are cookies Google's own tag already\n * set on this visitor. We read them, we never write them.\n */\n\nexport interface Ga4Identity {\n /** GA4 client id, from `_ga`. Without it a server-sent event has no identity. */\n gaClientId?: string\n /**\n * GA4 session ids keyed by container id (the measurement id minus `G-`), from\n * the `_ga_<CONTAINER>` cookies.\n *\n * A map rather than one value because a page may carry more than one GA4\n * property, and picking the wrong one would silently attach the lead to the\n * wrong session — the sender knows which measurement id it is configured for,\n * this side does not.\n */\n gaSessions?: Record<string, string>\n}\n\nfunction readCookie(jar: string, name: string): string | undefined {\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n const match = jar.match(new RegExp(`(?:^|;\\\\s*)${escaped}=([^;]*)`))\n return match ? decodeURIComponent(match[1]) : undefined\n}\n\nexport function readGa4Identity(): Ga4Identity {\n if (typeof document === 'undefined') return {}\n const jar = document.cookie || ''\n if (!jar) return {}\n\n const identity: Ga4Identity = {}\n\n // `_ga` is `GA1.<depth>.<id1>.<id2>`; the client id is the last two parts\n // joined. Reading the raw cookie rather than the trailing two segments\n // blindly keeps it correct when the depth prefix varies by domain scope.\n const ga = readCookie(jar, '_ga')\n if (ga) {\n const parts = ga.split('.')\n if (parts.length >= 4) {\n const clientId = `${parts[parts.length - 2]}.${parts[parts.length - 1]}`\n if (/^\\d+\\.\\d+$/.test(clientId)) identity.gaClientId = clientId\n }\n }\n\n // `_ga_<CONTAINER>` is `GS<v>.<depth>.<session_id>.<session_number>....`\n const sessions: Record<string, string> = {}\n for (const raw of jar.split(';')) {\n const cookie = raw.trim()\n const eq = cookie.indexOf('=')\n if (eq < 0) continue\n const name = cookie.slice(0, eq)\n const container = /^_ga_([A-Z0-9]+)$/i.exec(name)?.[1]\n if (!container) continue\n const parts = decodeURIComponent(cookie.slice(eq + 1)).split('.')\n if (parts.length >= 3 && /^\\d+$/.test(parts[2])) sessions[container] = parts[2]\n }\n if (Object.keys(sessions).length > 0) identity.gaSessions = sessions\n\n return identity\n}\n","/**\n * @sonordev/site-kit/forms - Shared submission logic\n *\n * Single source of truth for sending a managed form to the Sonor API. Both\n * <ManagedForm> (via FormClient) and the headless useForm() hook submit through\n * here, so the request shape, retry behaviour, reCAPTCHA handling, and error\n * parsing can never drift between the two paths.\n */\n\nimport { sonorFetch } from '../shared/sonorFetch'\nimport { getRecaptchaToken } from './recaptcha'\nimport { DEFAULT_HONEYPOT_FIELD } from './contract'\nimport { readGa4Identity } from './ga4-identity'\nimport type { ManagedFormConfig } from './types'\n\n// The honeypot trap-field name lives once in the shared forms contract\n// (single source of truth for site-kit's client + sonor-api's intake).\n// Re-exported so existing importers of this path keep resolving it.\nexport { DEFAULT_HONEYPOT_FIELD }\n\nexport function getApiConfig(): { apiUrl: string; apiKey: string | undefined } {\n // Server branch must honor the same env override SiteKitLayout feeds into\n // __SITE_KIT_API_URL__, or SSR-rendered absolute URLs (the native form\n // action) would point at prod from a staging site.\n const apiUrl =\n typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : process.env.SONOR_API_URL || process.env.NEXT_PUBLIC_SONOR_API_URL || 'https://api.sonor.io'\n const apiKey =\n typeof window !== 'undefined' ? (window as any).__SITE_KIT_API_KEY__ : undefined\n return { apiUrl, apiKey }\n}\n\nfunction getUTMParams(): Record<string, string | null> {\n if (typeof window === 'undefined') return {}\n const params = new URLSearchParams(window.location.search)\n const out: Record<string, string | null> = {}\n for (const key of ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content']) {\n out[key] = params.get(key)\n }\n return out\n}\n\nexport interface SubmitFormArgs {\n config: ManagedFormConfig\n /**\n * Field values to submit. The caller must pass VISIBLE values only —\n * conditionally-hidden fields should be excluded so stale values are not sent.\n */\n values: Record<string, unknown>\n /** Honeypot input value (empty string for the headless hook, which has no honeypot UI). */\n honeypotValue: string\n /** Timestamp (ms) the form was first rendered — a weak anti-bot timing signal. */\n formLoadedAt: number\n}\n\n/**\n * Submit a managed form. Throws on failure (network, timeout, or a non-2xx\n * response) with a human-readable message; resolves with the parsed API\n * response on success.\n */\nexport async function submitForm({\n config,\n values,\n honeypotValue,\n formLoadedAt,\n}: SubmitFormArgs): Promise<unknown> {\n const { apiUrl, apiKey } = getApiConfig()\n if (!apiKey) {\n throw new Error('API key is required. Set SONOR_API_KEY in your environment.')\n }\n\n // reCAPTCHA token is fetched right before the POST so it cannot expire.\n const recaptchaToken = config.recaptcha_enabled\n ? await getRecaptchaToken(config.recaptcha_site_key)\n : null\n if (config.recaptcha_enabled && !recaptchaToken) {\n throw new Error('Verification could not be completed. Please try again.')\n }\n\n const honeypotFieldName = config.honeypot_field || DEFAULT_HONEYPOT_FIELD\n const utm = getUTMParams()\n // The visitor's existing GA4 cookies, so Sonor can report an accepted lead\n // as a conversion server-side. Nothing is written or created here — see\n // ga4-identity.ts for why the server, not this browser, has to do it.\n const ga4 = readGa4Identity()\n\n const payload = {\n formId: config.id,\n form_id: config.id,\n data: {\n ...values,\n ...(config.honeypot_enabled ? { [honeypotFieldName]: honeypotValue } : {}),\n },\n metadata: {\n pageUrl: typeof window !== 'undefined' ? window.location.href : null,\n referrer: typeof document !== 'undefined' ? document.referrer || null : null,\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : null,\n sessionId:\n typeof sessionStorage !== 'undefined' ? sessionStorage.getItem('_sk_sid') : null,\n // Anonymous visitor id (_sk_vid) — the same id Analytics/Signal stamp on\n // page views, so the Sonor side can bind this lead to its browsing session\n // (page -> lead attribution). Sent on every submission; null pre-hydration.\n visitorId:\n typeof localStorage !== 'undefined' ? localStorage.getItem('_sk_vid') : null,\n recaptchaToken: recaptchaToken || undefined,\n utmSource: utm.utm_source,\n utmMedium: utm.utm_medium,\n utmCampaign: utm.utm_campaign,\n utmTerm: utm.utm_term,\n utmContent: utm.utm_content,\n ...ga4,\n // Sub-site host — preserved on form_submissions for lead attribution\n // across multi-site projects. Resolved by SiteKitClientProviders.\n site:\n typeof window !== 'undefined'\n ? (window as { __SITE_KIT_SITE__?: string }).__SITE_KIT_SITE__ ||\n window.location.host\n : undefined,\n _formLoadedAt: formLoadedAt,\n },\n }\n\n const response = await sonorFetch(\n `${apiUrl}/api/public/forms/submit`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(payload),\n },\n { retries: 2, timeoutMs: 20000 },\n )\n\n const data = await response.json().catch(() => null)\n\n if (!response.ok) {\n const msg = (\n data?.message ??\n data?.error ??\n (response.statusText || `HTTP ${response.status}`)\n )\n .toString()\n .trim()\n throw new Error(\n msg ? `Failed to submit form: ${msg}` : `Failed to submit form (${response.status})`,\n )\n }\n\n return data\n}\n"]}
@@ -1,16 +1,60 @@
1
1
  'use client';
2
2
  import { registerAnalyticsDispatcher } from './chunk-3DPXOZAU.mjs';
3
+ import { isCrossOriginFrame } from './chunk-NVSWTDWU.mjs';
3
4
  import { getOrCreateVisitorId, getOrCreateSessionId } from './chunk-ZZQAGCSI.mjs';
4
- import { sonorFetch, sonorBeacon } from './chunk-4HL6CAZ7.mjs';
5
- import { createContext, useRef, useEffect, useState, useCallback, useMemo, useContext } from 'react';
5
+ import { sonorFetch, sonorBeacon } from './chunk-ZKR5AJV5.mjs';
6
+ import { createContext, useRef, useEffect, useState, useMemo, useCallback, useContext } from 'react';
6
7
  import { usePathname } from 'next/navigation';
7
8
  import { jsxs, jsx } from 'react/jsx-runtime';
8
9
 
9
- function getApiConfig() {
10
- const apiUrl = typeof window !== "undefined" ? window.__SITE_KIT_API_URL__ || "https://api.sonor.io" : "https://api.sonor.io";
10
+ // src/analytics/send-gate.ts
11
+ function windowConfig() {
12
+ const apiUrl = typeof window !== "undefined" && window.__SITE_KIT_API_URL__ || "https://api.sonor.io";
11
13
  const apiKey = typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ : void 0;
12
14
  return { apiUrl, apiKey };
13
15
  }
16
+ var announcedSuppression = false;
17
+ function resolveAnalyticsTarget(options = {}) {
18
+ const { apiUrl: globalApiUrl, apiKey: globalApiKey } = windowConfig();
19
+ const apiUrl = options.apiUrl || globalApiUrl;
20
+ const apiKey = options.apiKey || globalApiKey;
21
+ if (!apiKey) return null;
22
+ if (!options.allowInFrame && isCrossOriginFrame()) {
23
+ if (options.debug && !announcedSuppression) {
24
+ announcedSuppression = true;
25
+ console.info(
26
+ "[Analytics] This page is embedded in a cross-origin frame, so nothing is being reported. Set analytics.allowInFrame if this site is meant to be tracked as an embed."
27
+ );
28
+ }
29
+ return null;
30
+ }
31
+ return { apiUrl, apiKey };
32
+ }
33
+ async function analyticsSend(path, body, options = {}) {
34
+ const target = resolveAnalyticsTarget(options);
35
+ if (!target) return null;
36
+ try {
37
+ return await sonorFetch(
38
+ `${target.apiUrl}${path}`,
39
+ {
40
+ method: options.method || "POST",
41
+ headers: { "Content-Type": "application/json" },
42
+ ...options.keepalive ? { keepalive: true } : {},
43
+ ...body === void 0 ? {} : { body: JSON.stringify(body) }
44
+ },
45
+ { apiKey: target.apiKey, retries: options.retries ?? 0 }
46
+ );
47
+ } catch {
48
+ return null;
49
+ }
50
+ }
51
+ function analyticsBeacon(path, body, options = {}) {
52
+ const target = resolveAnalyticsTarget(options);
53
+ if (!target) return;
54
+ sonorBeacon(`${target.apiUrl}${path}`, body, target.apiKey);
55
+ }
56
+
57
+ // src/analytics/WebVitals.tsx
14
58
  function pathForMetric(metric, fallback) {
15
59
  const url = metric.navigationURL;
16
60
  if (url) {
@@ -61,29 +105,28 @@ function summarizeAttribution(metric) {
61
105
  return void 0;
62
106
  }
63
107
  }
64
- function WebVitals({ apiUrl: propApiUrl, apiKey: propApiKey, site: propSite, debug = false }) {
108
+ function WebVitals({
109
+ apiUrl: propApiUrl,
110
+ apiKey: propApiKey,
111
+ site: propSite,
112
+ allowInFrame = false,
113
+ debug = false
114
+ }) {
65
115
  const pathname = usePathname();
66
116
  const landingPathRef = useRef(pathname || "/");
67
- const propsRef = useRef({ propApiUrl, propApiKey, propSite, debug });
68
- propsRef.current = { propApiUrl, propApiKey, propSite, debug };
117
+ const propsRef = useRef({ propApiUrl, propApiKey, propSite, allowInFrame, debug });
118
+ propsRef.current = { propApiUrl, propApiKey, propSite, allowInFrame, debug };
69
119
  useEffect(() => {
70
120
  let cancelled = false;
71
121
  let teardown;
72
122
  import('./web-vitals.attribution-7LKLZ5GR.mjs').then(({ onCLS, onLCP, onTTFB, onINP, onFCP }) => {
73
123
  if (cancelled) return;
74
- const { propApiUrl: propApiUrl2, propApiKey: propApiKey2, propSite: propSite2, debug: debug2 } = propsRef.current;
124
+ const { propApiUrl: propApiUrl2, propApiKey: propApiKey2, propSite: propSite2, allowInFrame: allowInFrame2, debug: debug2 } = propsRef.current;
75
125
  const sent = /* @__PURE__ */ new Map();
76
126
  const report = (metric, viaBeacon = false) => {
77
127
  if (sent.get(metric.id) === metric.value) return;
78
128
  sent.set(metric.id, metric.value);
79
- const { apiUrl: globalApiUrl, apiKey: globalApiKey } = getApiConfig();
80
- const apiUrl = propApiUrl2 || globalApiUrl;
81
- const apiKey = propApiKey2 || globalApiKey;
82
129
  const site = propSite2 || (typeof window !== "undefined" ? window.__SITE_KIT_SITE__ || window.location.host : "");
83
- if (!apiKey) {
84
- if (debug2) console.warn("[Analytics] No API key configured for Web Vitals");
85
- return;
86
- }
87
130
  const data = {
88
131
  site,
89
132
  pagePath: pathForMetric(metric, landingPathRef.current),
@@ -97,22 +140,13 @@ function WebVitals({ apiUrl: propApiUrl, apiKey: propApiKey, site: propSite, deb
97
140
  attribution: summarizeAttribution(metric)
98
141
  };
99
142
  if (debug2) console.log("[Analytics] Web Vital:", data);
100
- const endpoint = `${apiUrl}/api/public/analytics/web-vitals`;
143
+ const endpoint = "/api/public/analytics/web-vitals";
144
+ const gate = { apiUrl: propApiUrl2, apiKey: propApiKey2, allowInFrame: allowInFrame2, debug: debug2 };
101
145
  if (viaBeacon) {
102
- sonorBeacon(endpoint, data, apiKey);
146
+ analyticsBeacon(endpoint, data, gate);
103
147
  return;
104
148
  }
105
- void sonorFetch(
106
- endpoint,
107
- {
108
- method: "POST",
109
- headers: { "Content-Type": "application/json" },
110
- body: JSON.stringify(data)
111
- },
112
- { apiKey, retries: 0 }
113
- ).catch((error) => {
114
- if (debug2) console.error("[Analytics] Error reporting Web Vital:", error);
115
- });
149
+ void analyticsSend(endpoint, data, gate);
116
150
  };
117
151
  const opts = { reportSoftNavs: true };
118
152
  const pending = [];
@@ -547,11 +581,6 @@ async function collectPageMetadata(isStale) {
547
581
  const content = getContentPageMetadata();
548
582
  return { ...light, ...media, ...content };
549
583
  }
550
- function getApiConfig2() {
551
- const apiUrl = typeof window !== "undefined" ? window.__SITE_KIT_API_URL__ || "https://api.sonor.io" : "https://api.sonor.io";
552
- const apiKey = typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ : void 0;
553
- return { apiUrl, apiKey };
554
- }
555
584
  function AnalyticsProvider({
556
585
  children,
557
586
  apiUrl: propApiUrl,
@@ -569,11 +598,16 @@ function AnalyticsProvider({
569
598
  externalVisitorId,
570
599
  externalSessionId,
571
600
  onPageMetadata,
572
- site: propSite
601
+ site: propSite,
602
+ allowInFrame = false
573
603
  }) {
574
604
  const pathname = usePathname();
575
605
  const [queryString, setQueryString] = useState("");
576
606
  const site = propSite || (typeof window !== "undefined" ? window.__SITE_KIT_SITE__ || window.location.host : "");
607
+ const gate = useMemo(
608
+ () => ({ apiUrl: propApiUrl, apiKey: propApiKey, allowInFrame, debug }),
609
+ [propApiUrl, propApiKey, allowInFrame, debug]
610
+ );
577
611
  useEffect(() => {
578
612
  if (typeof window === "undefined") return;
579
613
  setQueryString(window.location.search);
@@ -601,19 +635,17 @@ function AnalyticsProvider({
601
635
  return;
602
636
  }
603
637
  const fetchValidPages = async () => {
604
- const { apiUrl: globalApiUrl, apiKey: globalApiKey } = getApiConfig2();
605
- const apiUrl = propApiUrl || globalApiUrl;
606
- const apiKey = propApiKey || globalApiKey;
607
- if (!apiKey) {
608
- if (debug) console.warn("[Analytics] No API key for page validation");
609
- return;
610
- }
611
638
  try {
612
- const response = await sonorFetch(
613
- `${apiUrl}/api/public/seo/pages`,
614
- { method: "GET", headers: { "Content-Type": "application/json" } },
615
- { apiKey }
639
+ const response = await analyticsSend(
640
+ "/api/public/seo/pages",
641
+ void 0,
642
+ { ...gate, method: "GET", retries: 2 }
616
643
  );
644
+ if (!response) {
645
+ if (debug) console.warn("[Analytics] Page validation skipped (no key, or embedded)");
646
+ sitemapLoadedRef.current = true;
647
+ return;
648
+ }
617
649
  if (response.ok) {
618
650
  const data = await response.json();
619
651
  const pages = data?.pages || [];
@@ -636,7 +668,7 @@ function AnalyticsProvider({
636
668
  }
637
669
  };
638
670
  fetchValidPages();
639
- }, [propApiUrl, propApiKey, validateAgainstSitemap, debug]);
671
+ }, [gate, validateAgainstSitemap, debug]);
640
672
  useEffect(() => {
641
673
  if (!trackPageViews) return;
642
674
  if (!pathname) return;
@@ -645,11 +677,8 @@ function AnalyticsProvider({
645
677
  if (normalizedPath === lastPathRef.current) return;
646
678
  lastPathRef.current = normalizedPath;
647
679
  const trackPageView = async () => {
648
- const { apiUrl: globalApiUrl, apiKey: globalApiKey } = getApiConfig2();
649
- const apiUrl = propApiUrl || globalApiUrl;
650
- const apiKey = propApiKey || globalApiKey;
651
- if (!apiKey) {
652
- if (debug) console.warn("[Analytics] No API key configured");
680
+ if (!resolveAnalyticsTarget(gate)) {
681
+ if (debug) console.warn("[Analytics] Page view skipped (no key, or embedded)");
653
682
  return;
654
683
  }
655
684
  const utmParams = getUTMParams();
@@ -692,25 +721,13 @@ function AnalyticsProvider({
692
721
  if (debug) {
693
722
  console.log("[Analytics] Page view:", pageView);
694
723
  }
695
- try {
696
- const response = await sonorFetch(
697
- `${apiUrl}/api/public/analytics/page-view`,
698
- {
699
- method: "POST",
700
- headers: { "Content-Type": "application/json" },
701
- body: JSON.stringify(pageView)
702
- },
703
- { apiKey, retries: 0 }
704
- );
705
- if (debug) {
706
- console.log("[Analytics] Page view response:", response.status, response.statusText, "url:", `${apiUrl}/api/public/analytics/page-view`);
707
- }
708
- if (!response.ok && debug) {
724
+ const response = await analyticsSend("/api/public/analytics/page-view", pageView, gate);
725
+ if (debug && response) {
726
+ console.log("[Analytics] Page view response:", response.status, response.statusText);
727
+ if (!response.ok) {
709
728
  const text = await response.text().catch(() => "");
710
729
  console.error("[Analytics] Error tracking page view:", response.status, response.statusText, text);
711
730
  }
712
- } catch (error) {
713
- if (debug) console.error("[Analytics] Error tracking page view (fetch failed):", error);
714
731
  }
715
732
  if (validateAgainstSitemap && debug) {
716
733
  if (sitemapLoadedRef.current && validPathsRef.current && validPathsRef.current.size > 0) {
@@ -723,15 +740,12 @@ function AnalyticsProvider({
723
740
  }
724
741
  };
725
742
  scheduleIdleTask(() => trackPageView());
726
- }, [pathname, queryString, propApiUrl, propApiKey, trackPageViews, excludePaths, debug, validateAgainstSitemap]);
743
+ }, [pathname, queryString, gate, trackPageViews, excludePaths, debug, validateAgainstSitemap]);
727
744
  useEffect(() => {
728
745
  if (!trackJourneys) return;
729
746
  if (!pathname) return;
730
747
  if (typeof window === "undefined") return;
731
- const { apiUrl: globalApiUrl, apiKey: globalApiKey } = getApiConfig2();
732
- const apiUrl = propApiUrl || globalApiUrl;
733
- const apiKey = propApiKey || globalApiKey;
734
- if (!apiKey) return;
748
+ if (!resolveAnalyticsTarget(gate)) return;
735
749
  const now = Date.now();
736
750
  const previousPath = lastPathRef.current;
737
751
  const previousDuration = pageEnterTimeRef.current > 0 ? Math.round((now - pageEnterTimeRef.current) / 1e3) : 0;
@@ -782,48 +796,36 @@ function AnalyticsProvider({
782
796
  if (debug) {
783
797
  console.log("[Analytics] Journey step:", sessionData);
784
798
  }
785
- try {
786
- await sonorFetch(
787
- `${apiUrl}/api/public/analytics/session`,
788
- {
789
- method: "POST",
790
- headers: { "Content-Type": "application/json" },
791
- body: JSON.stringify(sessionData)
792
- },
793
- { apiKey, retries: 0 }
794
- );
795
- } catch (error) {
796
- if (debug) console.error("[Analytics] Error tracking journey:", error);
797
- }
799
+ await analyticsSend("/api/public/analytics/session", sessionData, gate);
798
800
  };
799
801
  scheduleIdleTask(() => trackJourneyStep());
800
802
  const handleUnload = () => {
801
803
  const duration = Math.round((Date.now() - journeyStartTimeRef.current) / 1e3);
802
- const payload = JSON.stringify({
803
- sessionId: sessionIdRef.current,
804
- site,
805
- action: "end",
806
- duration,
807
- lastPage: pathname,
808
- previousPageDuration: Math.round((Date.now() - pageEnterTimeRef.current) / 1e3),
809
- previousPageScrollDepth: currentScrollDepthRef.current
810
- });
811
- sonorBeacon(`${apiUrl}/api/public/analytics/session`, payload, apiKey);
804
+ analyticsBeacon(
805
+ "/api/public/analytics/session",
806
+ {
807
+ sessionId: sessionIdRef.current,
808
+ site,
809
+ action: "end",
810
+ duration,
811
+ lastPage: pathname,
812
+ previousPageDuration: Math.round((Date.now() - pageEnterTimeRef.current) / 1e3),
813
+ previousPageScrollDepth: currentScrollDepthRef.current
814
+ },
815
+ gate
816
+ );
812
817
  };
813
818
  window.addEventListener("pagehide", handleUnload);
814
819
  return () => {
815
820
  window.removeEventListener("pagehide", handleUnload);
816
821
  };
817
- }, [pathname, propApiUrl, propApiKey, trackJourneys, debug]);
822
+ }, [pathname, gate, trackJourneys, debug]);
818
823
  useEffect(() => {
819
824
  if (typeof window === "undefined") return;
820
825
  if (debug) console.log("[Analytics] Scroll tracking setup:", { trackScrollDepth, hasApiKey: !!propApiKey });
821
826
  if (!trackScrollDepth) return;
822
- const { apiUrl: globalApiUrl, apiKey: globalApiKey } = getApiConfig2();
823
- const apiUrl = propApiUrl || globalApiUrl;
824
- const apiKey = propApiKey || globalApiKey;
825
- if (!apiKey) {
826
- if (debug) console.warn("[Analytics] Scroll tracking disabled - no API key");
827
+ if (!resolveAnalyticsTarget(gate)) {
828
+ if (debug) console.warn("[Analytics] Scroll tracking disabled (no key, or embedded)");
827
829
  return;
828
830
  }
829
831
  if (debug) console.log("[Analytics] Scroll tracking enabled for:", pathname);
@@ -859,7 +861,7 @@ function AnalyticsProvider({
859
861
  if (hasTracked || maxDepth === 0) return;
860
862
  hasTracked = true;
861
863
  const totalTime = (Date.now() - startTime) / 1e3;
862
- const payload = JSON.stringify({
864
+ const payload = {
863
865
  sessionId: sessionIdRef.current,
864
866
  visitorId: visitorIdRef.current,
865
867
  site,
@@ -871,28 +873,16 @@ function AnalyticsProvider({
871
873
  timeTo100: milestone100,
872
874
  totalTimeSeconds: totalTime,
873
875
  deviceType: getDeviceType()
874
- });
876
+ };
875
877
  if (useBeacon) {
876
- sonorBeacon(`${apiUrl}/api/public/analytics/scroll-depth`, payload, apiKey);
877
- if (debug) console.log("[Analytics] Scroll depth (beacon):", { maxDepth, totalTime });
878
+ analyticsBeacon("/api/public/analytics/scroll-depth", payload, gate);
878
879
  } else {
879
- try {
880
- await sonorFetch(
881
- `${apiUrl}/api/public/analytics/scroll-depth`,
882
- {
883
- method: "POST",
884
- headers: { "Content-Type": "application/json" },
885
- body: payload,
886
- keepalive: true
887
- // Allows request to outlive the page
888
- },
889
- { apiKey, retries: 0 }
890
- );
891
- if (debug) console.log("[Analytics] Scroll depth:", { maxDepth, totalTime });
892
- } catch (error) {
893
- if (debug) console.error("[Analytics] Error tracking scroll depth:", error);
894
- }
880
+ await analyticsSend("/api/public/analytics/scroll-depth", payload, {
881
+ ...gate,
882
+ keepalive: true
883
+ });
895
884
  }
885
+ if (debug) console.log("[Analytics] Scroll depth:", { maxDepth, totalTime, useBeacon });
896
886
  };
897
887
  maxDepth = 0;
898
888
  startTime = Date.now();
@@ -915,14 +905,11 @@ function AnalyticsProvider({
915
905
  document.removeEventListener("visibilitychange", handleVisibilityChange);
916
906
  sendScrollData(false);
917
907
  };
918
- }, [pathname, propApiUrl, propApiKey, trackScrollDepth, debug]);
908
+ }, [pathname, gate, trackScrollDepth, debug]);
919
909
  useEffect(() => {
920
910
  if (!trackClicks) return;
921
911
  if (typeof window === "undefined") return;
922
- const { apiUrl: globalApiUrl, apiKey: globalApiKey } = getApiConfig2();
923
- const apiUrl = propApiUrl || globalApiUrl;
924
- const apiKey = propApiKey || globalApiKey;
925
- if (!apiKey) return;
912
+ if (!resolveAnalyticsTarget(gate)) return;
926
913
  const handleClick = async (e) => {
927
914
  const target = e.target;
928
915
  if (!target) return;
@@ -953,36 +940,17 @@ function AnalyticsProvider({
953
940
  elementText
954
941
  };
955
942
  if (debug) console.log("[Analytics] Click:", clickData);
956
- scheduleIdleTask(async () => {
957
- try {
958
- await sonorFetch(
959
- `${apiUrl}/api/public/analytics/heatmap-click`,
960
- {
961
- method: "POST",
962
- headers: { "Content-Type": "application/json" },
963
- body: JSON.stringify(clickData)
964
- },
965
- { apiKey, retries: 0 }
966
- );
967
- } catch (error) {
968
- if (debug) console.error("[Analytics] Error tracking click:", error);
969
- }
943
+ scheduleIdleTask(() => {
944
+ void analyticsSend("/api/public/analytics/heatmap-click", clickData, gate);
970
945
  }, 500);
971
946
  };
972
947
  document.addEventListener("click", handleClick, { passive: true });
973
948
  return () => {
974
949
  document.removeEventListener("click", handleClick);
975
950
  };
976
- }, [pathname, propApiUrl, propApiKey, trackClicks, debug]);
951
+ }, [pathname, gate, trackClicks, debug]);
977
952
  const trackEvent = useCallback((options) => {
978
953
  const doTrack = async () => {
979
- const { apiUrl: globalApiUrl, apiKey: globalApiKey } = getApiConfig2();
980
- const apiUrl = propApiUrl || globalApiUrl;
981
- const apiKey = propApiKey || globalApiKey;
982
- if (!apiKey) {
983
- if (debug) console.warn("[Analytics] No API key configured");
984
- return;
985
- }
986
954
  const event = {
987
955
  sessionId: sessionIdRef.current,
988
956
  visitorId: visitorIdRef.current,
@@ -997,34 +965,15 @@ function AnalyticsProvider({
997
965
  if (debug) {
998
966
  console.log("[Analytics] Event:", event);
999
967
  }
1000
- try {
1001
- const response = await sonorFetch(
1002
- `${apiUrl}/api/public/analytics/event`,
1003
- {
1004
- method: "POST",
1005
- headers: { "Content-Type": "application/json" },
1006
- body: JSON.stringify(event)
1007
- },
1008
- { apiKey, retries: 0 }
1009
- );
1010
- if (!response.ok && debug) {
1011
- console.error("[Analytics] Error tracking event:", response.statusText);
1012
- }
1013
- } catch (error) {
1014
- if (debug) console.error("[Analytics] Error tracking event:", error);
968
+ const response = await analyticsSend("/api/public/analytics/event", event, gate);
969
+ if (response && !response.ok && debug) {
970
+ console.error("[Analytics] Error tracking event:", response.statusText);
1015
971
  }
1016
972
  };
1017
973
  scheduleIdleTask(doTrack, 1e3);
1018
- }, [propApiUrl, propApiKey, pathname, debug]);
974
+ }, [gate, site, pathname, debug]);
1019
975
  const trackConversion = useCallback((options) => {
1020
976
  const doTrack = async () => {
1021
- const { apiUrl: globalApiUrl, apiKey: globalApiKey } = getApiConfig2();
1022
- const apiUrl = propApiUrl || globalApiUrl;
1023
- const apiKey = propApiKey || globalApiKey;
1024
- if (!apiKey) {
1025
- if (debug) console.warn("[Analytics] No API key configured");
1026
- return;
1027
- }
1028
977
  const conversion = {
1029
978
  sessionId: sessionIdRef.current,
1030
979
  visitorId: visitorIdRef.current,
@@ -1040,25 +989,13 @@ function AnalyticsProvider({
1040
989
  if (debug) {
1041
990
  console.log("[Analytics] Conversion:", conversion);
1042
991
  }
1043
- try {
1044
- const response = await sonorFetch(
1045
- `${apiUrl}/api/public/analytics/conversion`,
1046
- {
1047
- method: "POST",
1048
- headers: { "Content-Type": "application/json" },
1049
- body: JSON.stringify(conversion)
1050
- },
1051
- { apiKey, retries: 0 }
1052
- );
1053
- if (!response.ok && debug) {
1054
- console.error("[Analytics] Error tracking conversion:", response.statusText);
1055
- }
1056
- } catch (error) {
1057
- if (debug) console.error("[Analytics] Error tracking conversion:", error);
992
+ const response = await analyticsSend("/api/public/analytics/conversion", conversion, gate);
993
+ if (response && !response.ok && debug) {
994
+ console.error("[Analytics] Error tracking conversion:", response.statusText);
1058
995
  }
1059
996
  };
1060
997
  doTrack();
1061
- }, [propApiUrl, propApiKey, pathname, debug]);
998
+ }, [gate, site, pathname, debug]);
1062
999
  useEffect(() => {
1063
1000
  registerAnalyticsDispatcher({ trackEvent, trackConversion });
1064
1001
  return () => registerAnalyticsDispatcher(null);
@@ -1076,6 +1013,7 @@ function AnalyticsProvider({
1076
1013
  apiUrl: propApiUrl,
1077
1014
  apiKey: propApiKey,
1078
1015
  site,
1016
+ allowInFrame,
1079
1017
  debug
1080
1018
  }
1081
1019
  ),
@@ -1098,5 +1036,5 @@ function useTrackEvent() {
1098
1036
  }
1099
1037
 
1100
1038
  export { AnalyticsProvider, WebVitals, useAnalytics, useAnalyticsOptional, useTrackEvent };
1101
- //# sourceMappingURL=chunk-AJBJH3BA.mjs.map
1102
- //# sourceMappingURL=chunk-AJBJH3BA.mjs.map
1039
+ //# sourceMappingURL=chunk-Y7SRO7MJ.mjs.map
1040
+ //# sourceMappingURL=chunk-Y7SRO7MJ.mjs.map