@useinsider/guido 3.13.1 → 3.14.0-beta.8d5df20

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 (30) hide show
  1. package/dist/@types/config/schemas.js +108 -92
  2. package/dist/components/Guido.vue.js +1 -1
  3. package/dist/components/Guido.vue2.js +91 -85
  4. package/dist/components/organisms/header/ViewOptions.vue.js +1 -1
  5. package/dist/components/organisms/header/version-history/ViewOptions.vue.js +1 -1
  6. package/dist/composables/useActionsApi.js +30 -22
  7. package/dist/composables/useEmailTemplateApplier.js +8 -6
  8. package/dist/composables/useTimerClone.js +21 -19
  9. package/dist/config/migrator/index.js +11 -10
  10. package/dist/config/migrator/trackIdMigrator.js +11 -0
  11. package/dist/guido.css +1 -1
  12. package/dist/library.js +8 -5
  13. package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +12 -12
  14. package/dist/node_modules/valibot/dist/index.js +230 -216
  15. package/dist/package.json.js +1 -1
  16. package/dist/src/@types/config/schemas.d.ts +20 -0
  17. package/dist/src/composables/useActionsApi.d.ts +1 -1
  18. package/dist/src/composables/useConfig.d.ts +4 -0
  19. package/dist/src/config/migrator/index.d.ts +6 -1
  20. package/dist/src/config/migrator/trackIdMigrator.d.ts +6 -0
  21. package/dist/src/library.d.ts +1 -0
  22. package/dist/src/stores/config.d.ts +36 -0
  23. package/dist/src/stores/editor.d.ts +25 -0
  24. package/dist/src/utils/linkTrackingIds.d.ts +25 -0
  25. package/dist/static/styles/components/wide-panel.css.js +7 -0
  26. package/dist/static/styles/customEditorStyle.css.js +8 -0
  27. package/dist/stores/editor.js +4 -1
  28. package/dist/utils/linkTrackingIds.js +46 -0
  29. package/dist/utils/templatePreparation.js +72 -61
  30. package/package.json +4 -4
@@ -1,4 +1,4 @@
1
- const o = { stripo: { version: "2.69.1" } }, s = {
1
+ const o = { stripo: { version: "2.72.1" } }, s = {
2
2
  guido: o
3
3
  };
4
4
  export {
@@ -262,6 +262,14 @@ export declare const TemplateSchema: v.ObjectSchema<{
262
262
  readonly selectedUnsubscribePages: v.OptionalSchema<v.ArraySchema<v.NumberSchema<undefined>, undefined>, readonly []>;
263
263
  /** Force recreate template in Stripo storage (use true when updating externally modified templates) */
264
264
  readonly forceRecreate: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
265
+ /**
266
+ * Consumer-persisted tracking-id high-water mark (SD-141414). Used as the id floor
267
+ * during migration so a rolled-back document never re-mints retired tracking ids.
268
+ * Out-of-range numbers are coerced rather than rejected — this value arrives from
269
+ * stored partner data, and rejecting it would fail parseConfig and block the editor
270
+ * mount. Non-numbers still fail, like every other field in this schema.
271
+ */
272
+ readonly trackIdCounter: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.TransformAction<number, number>]>, 0>;
265
273
  /** Migration-only inputs (legacy block configs) */
266
274
  readonly migration: v.OptionalSchema<v.ObjectSchema<{
267
275
  /**
@@ -385,6 +393,8 @@ export declare const FeaturesSchema: v.ObjectSchema<{
385
393
  readonly autosave: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
386
394
  /** Enable pre-save domain-allowlist validation (opt-in; Guido self-serves the block toaster) */
387
395
  readonly allowlistEnabled: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
396
+ /** Enable persistent link tracking-id assignment for the click heatmap (opt-in) */
397
+ readonly linkTrackingIds: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
388
398
  }, undefined>;
389
399
  /**
390
400
  * Default block types available in Stripo
@@ -666,6 +676,14 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
666
676
  readonly selectedUnsubscribePages: v.OptionalSchema<v.ArraySchema<v.NumberSchema<undefined>, undefined>, readonly []>;
667
677
  /** Force recreate template in Stripo storage (use true when updating externally modified templates) */
668
678
  readonly forceRecreate: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
679
+ /**
680
+ * Consumer-persisted tracking-id high-water mark (SD-141414). Used as the id floor
681
+ * during migration so a rolled-back document never re-mints retired tracking ids.
682
+ * Out-of-range numbers are coerced rather than rejected — this value arrives from
683
+ * stored partner data, and rejecting it would fail parseConfig and block the editor
684
+ * mount. Non-numbers still fail, like every other field in this schema.
685
+ */
686
+ readonly trackIdCounter: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.TransformAction<number, number>]>, 0>;
669
687
  /** Migration-only inputs (legacy block configs) */
670
688
  readonly migration: v.OptionalSchema<v.ObjectSchema<{
671
689
  /**
@@ -774,6 +792,8 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
774
792
  readonly autosave: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
775
793
  /** Enable pre-save domain-allowlist validation (opt-in; Guido self-serves the block toaster) */
776
794
  readonly allowlistEnabled: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
795
+ /** Enable persistent link tracking-id assignment for the click heatmap (opt-in) */
796
+ readonly linkTrackingIds: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
777
797
  }, undefined>, {}>;
778
798
  /** Block configuration */
779
799
  readonly blocks: v.OptionalSchema<v.ObjectSchema<{
@@ -6,6 +6,6 @@ export declare const useActionsApi: () => {
6
6
  activateCustomViewStyles: (isActive?: boolean) => void;
7
7
  getPreviewData: (options?: CompileEmailOptions) => Promise<CompiledEmailResult>;
8
8
  updateTimerInClonedTemplate: () => Promise<string | null>;
9
- updateHtmlAndCss: (html: string, css: string) => void;
9
+ updateHtmlAndCss: (html: string, css: string) => Promise<void>;
10
10
  editorSave: () => Promise<boolean>;
11
11
  };
@@ -40,6 +40,7 @@ export declare const useConfig: () => {
40
40
  customFieldAttributes: string[];
41
41
  selectedUnsubscribePages: number[];
42
42
  forceRecreate: boolean;
43
+ trackIdCounter: number;
43
44
  migration: {
44
45
  recommendationConfigs: {
45
46
  [x: string]: {
@@ -97,6 +98,7 @@ export declare const useConfig: () => {
97
98
  liquidSyntax: boolean;
98
99
  autosave: boolean;
99
100
  allowlistEnabled: boolean;
101
+ linkTrackingIds: boolean;
100
102
  };
101
103
  blocks: {
102
104
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -172,6 +174,7 @@ export declare const useConfig: () => {
172
174
  customFieldAttributes: string[];
173
175
  selectedUnsubscribePages: number[];
174
176
  forceRecreate: boolean;
177
+ trackIdCounter: number;
175
178
  migration: {
176
179
  recommendationConfigs: {
177
180
  [x: string]: {
@@ -229,6 +232,7 @@ export declare const useConfig: () => {
229
232
  liquidSyntax: boolean;
230
233
  autosave: boolean;
231
234
  allowlistEnabled: boolean;
235
+ linkTrackingIds: boolean;
232
236
  } | null>;
233
237
  blocks: import("vue").ComputedRef<{
234
238
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1,2 +1,7 @@
1
1
  import type { LegacyRecommendationConfig } from '@@/Types/config';
2
- export declare const migrate: (html: string, recommendationConfigs?: Record<string, LegacyRecommendationConfig>) => Promise<string>;
2
+ export interface MigrateOptions {
3
+ linkTrackingIds?: boolean;
4
+ /** Consumer-persisted id high-water mark — ids are minted above it. */
5
+ trackIdFloor?: number;
6
+ }
7
+ export declare const migrate: (html: string, recommendationConfigs?: Record<string, LegacyRecommendationConfig>, options?: MigrateOptions) => Promise<string>;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Backfills persistent link tracking ids (SD-141414) at load so legacy
3
+ * templates, library imports and externally edited HTML enter the editor
4
+ * already tagged — before Stripo sees the document (no dirty flag, no undo).
5
+ */
6
+ export declare function migrateTrackIds(html: string, floor?: number): string;
@@ -1,5 +1,6 @@
1
1
  export { default as Guido } from './components/Guido.vue';
2
2
  export type { GuidoConfig, GuidoConfigInput, IdentityConfig, PartnerConfig, TemplateConfig, TemplateMigrationConfig, LegacyRecommendationConfig, EditorConfig, UIConfig, FeaturesConfig, BlocksConfig, CompilerConfig, DynamicContent, EmailHeader, DefaultBlockType, CustomBlockType, ValidationResult, ValidationError, } from './@types/config';
3
3
  export { validateConfig, parseConfig, parseConfigSafe, isValidConfig, getValidationErrors, MessageType, ProductType, } from './@types/config';
4
+ export { assignTrackingIds, readTrackSeq } from './utils/linkTrackingIds';
4
5
  export type { StripoEventType } from './@types/events';
5
6
  export type { PositionData, DynamicContentEvent, MergeTagClickEvent, MergeTag, BaseDynamicContent, DynamicContentNode, DynamicContentList, TooltipOptions, TextValueObject, L10n, } from './@types/generic';
@@ -45,6 +45,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
45
45
  customFieldAttributes: string[];
46
46
  selectedUnsubscribePages: number[];
47
47
  forceRecreate: boolean;
48
+ trackIdCounter: number;
48
49
  migration: {
49
50
  recommendationConfigs: {
50
51
  [x: string]: {
@@ -102,6 +103,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
102
103
  liquidSyntax: boolean;
103
104
  autosave: boolean;
104
105
  allowlistEnabled: boolean;
106
+ linkTrackingIds: boolean;
105
107
  };
106
108
  blocks: {
107
109
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -183,6 +185,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
183
185
  customFieldAttributes: string[];
184
186
  selectedUnsubscribePages: number[];
185
187
  forceRecreate: boolean;
188
+ trackIdCounter: number;
186
189
  migration: {
187
190
  recommendationConfigs: {
188
191
  [x: string]: {
@@ -240,6 +243,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
240
243
  liquidSyntax: boolean;
241
244
  autosave: boolean;
242
245
  allowlistEnabled: boolean;
246
+ linkTrackingIds: boolean;
243
247
  };
244
248
  blocks: {
245
249
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -321,6 +325,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
321
325
  customFieldAttributes: string[];
322
326
  selectedUnsubscribePages: number[];
323
327
  forceRecreate: boolean;
328
+ trackIdCounter: number;
324
329
  migration: {
325
330
  recommendationConfigs: {
326
331
  [x: string]: {
@@ -378,6 +383,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
378
383
  liquidSyntax: boolean;
379
384
  autosave: boolean;
380
385
  allowlistEnabled: boolean;
386
+ linkTrackingIds: boolean;
381
387
  };
382
388
  blocks: {
383
389
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -459,6 +465,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
459
465
  customFieldAttributes: string[];
460
466
  selectedUnsubscribePages: number[];
461
467
  forceRecreate: boolean;
468
+ trackIdCounter: number;
462
469
  migration: {
463
470
  recommendationConfigs: {
464
471
  [x: string]: {
@@ -516,6 +523,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
516
523
  liquidSyntax: boolean;
517
524
  autosave: boolean;
518
525
  allowlistEnabled: boolean;
526
+ linkTrackingIds: boolean;
519
527
  };
520
528
  blocks: {
521
529
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -597,6 +605,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
597
605
  customFieldAttributes: string[];
598
606
  selectedUnsubscribePages: number[];
599
607
  forceRecreate: boolean;
608
+ trackIdCounter: number;
600
609
  migration: {
601
610
  recommendationConfigs: {
602
611
  [x: string]: {
@@ -654,6 +663,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
654
663
  liquidSyntax: boolean;
655
664
  autosave: boolean;
656
665
  allowlistEnabled: boolean;
666
+ linkTrackingIds: boolean;
657
667
  };
658
668
  blocks: {
659
669
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -735,6 +745,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
735
745
  customFieldAttributes: string[];
736
746
  selectedUnsubscribePages: number[];
737
747
  forceRecreate: boolean;
748
+ trackIdCounter: number;
738
749
  migration: {
739
750
  recommendationConfigs: {
740
751
  [x: string]: {
@@ -792,6 +803,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
792
803
  liquidSyntax: boolean;
793
804
  autosave: boolean;
794
805
  allowlistEnabled: boolean;
806
+ linkTrackingIds: boolean;
795
807
  };
796
808
  blocks: {
797
809
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -873,6 +885,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
873
885
  customFieldAttributes: string[];
874
886
  selectedUnsubscribePages: number[];
875
887
  forceRecreate: boolean;
888
+ trackIdCounter: number;
876
889
  migration: {
877
890
  recommendationConfigs: {
878
891
  [x: string]: {
@@ -930,6 +943,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
930
943
  liquidSyntax: boolean;
931
944
  autosave: boolean;
932
945
  allowlistEnabled: boolean;
946
+ linkTrackingIds: boolean;
933
947
  };
934
948
  blocks: {
935
949
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1011,6 +1025,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1011
1025
  customFieldAttributes: string[];
1012
1026
  selectedUnsubscribePages: number[];
1013
1027
  forceRecreate: boolean;
1028
+ trackIdCounter: number;
1014
1029
  migration: {
1015
1030
  recommendationConfigs: {
1016
1031
  [x: string]: {
@@ -1068,6 +1083,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1068
1083
  liquidSyntax: boolean;
1069
1084
  autosave: boolean;
1070
1085
  allowlistEnabled: boolean;
1086
+ linkTrackingIds: boolean;
1071
1087
  };
1072
1088
  blocks: {
1073
1089
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1149,6 +1165,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1149
1165
  customFieldAttributes: string[];
1150
1166
  selectedUnsubscribePages: number[];
1151
1167
  forceRecreate: boolean;
1168
+ trackIdCounter: number;
1152
1169
  migration: {
1153
1170
  recommendationConfigs: {
1154
1171
  [x: string]: {
@@ -1206,6 +1223,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1206
1223
  liquidSyntax: boolean;
1207
1224
  autosave: boolean;
1208
1225
  allowlistEnabled: boolean;
1226
+ linkTrackingIds: boolean;
1209
1227
  };
1210
1228
  blocks: {
1211
1229
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1287,6 +1305,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1287
1305
  customFieldAttributes: string[];
1288
1306
  selectedUnsubscribePages: number[];
1289
1307
  forceRecreate: boolean;
1308
+ trackIdCounter: number;
1290
1309
  migration: {
1291
1310
  recommendationConfigs: {
1292
1311
  [x: string]: {
@@ -1344,6 +1363,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1344
1363
  liquidSyntax: boolean;
1345
1364
  autosave: boolean;
1346
1365
  allowlistEnabled: boolean;
1366
+ linkTrackingIds: boolean;
1347
1367
  };
1348
1368
  blocks: {
1349
1369
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1425,6 +1445,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1425
1445
  customFieldAttributes: string[];
1426
1446
  selectedUnsubscribePages: number[];
1427
1447
  forceRecreate: boolean;
1448
+ trackIdCounter: number;
1428
1449
  migration: {
1429
1450
  recommendationConfigs: {
1430
1451
  [x: string]: {
@@ -1482,6 +1503,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1482
1503
  liquidSyntax: boolean;
1483
1504
  autosave: boolean;
1484
1505
  allowlistEnabled: boolean;
1506
+ linkTrackingIds: boolean;
1485
1507
  };
1486
1508
  blocks: {
1487
1509
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1563,6 +1585,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1563
1585
  customFieldAttributes: string[];
1564
1586
  selectedUnsubscribePages: number[];
1565
1587
  forceRecreate: boolean;
1588
+ trackIdCounter: number;
1566
1589
  migration: {
1567
1590
  recommendationConfigs: {
1568
1591
  [x: string]: {
@@ -1620,6 +1643,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1620
1643
  liquidSyntax: boolean;
1621
1644
  autosave: boolean;
1622
1645
  allowlistEnabled: boolean;
1646
+ linkTrackingIds: boolean;
1623
1647
  };
1624
1648
  blocks: {
1625
1649
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1701,6 +1725,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1701
1725
  customFieldAttributes: string[];
1702
1726
  selectedUnsubscribePages: number[];
1703
1727
  forceRecreate: boolean;
1728
+ trackIdCounter: number;
1704
1729
  migration: {
1705
1730
  recommendationConfigs: {
1706
1731
  [x: string]: {
@@ -1758,6 +1783,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1758
1783
  liquidSyntax: boolean;
1759
1784
  autosave: boolean;
1760
1785
  allowlistEnabled: boolean;
1786
+ linkTrackingIds: boolean;
1761
1787
  };
1762
1788
  blocks: {
1763
1789
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1839,6 +1865,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1839
1865
  customFieldAttributes: string[];
1840
1866
  selectedUnsubscribePages: number[];
1841
1867
  forceRecreate: boolean;
1868
+ trackIdCounter: number;
1842
1869
  migration: {
1843
1870
  recommendationConfigs: {
1844
1871
  [x: string]: {
@@ -1896,6 +1923,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1896
1923
  liquidSyntax: boolean;
1897
1924
  autosave: boolean;
1898
1925
  allowlistEnabled: boolean;
1926
+ linkTrackingIds: boolean;
1899
1927
  };
1900
1928
  blocks: {
1901
1929
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1977,6 +2005,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1977
2005
  customFieldAttributes: string[];
1978
2006
  selectedUnsubscribePages: number[];
1979
2007
  forceRecreate: boolean;
2008
+ trackIdCounter: number;
1980
2009
  migration: {
1981
2010
  recommendationConfigs: {
1982
2011
  [x: string]: {
@@ -2034,6 +2063,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2034
2063
  liquidSyntax: boolean;
2035
2064
  autosave: boolean;
2036
2065
  allowlistEnabled: boolean;
2066
+ linkTrackingIds: boolean;
2037
2067
  };
2038
2068
  blocks: {
2039
2069
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -2115,6 +2145,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2115
2145
  customFieldAttributes: string[];
2116
2146
  selectedUnsubscribePages: number[];
2117
2147
  forceRecreate: boolean;
2148
+ trackIdCounter: number;
2118
2149
  migration: {
2119
2150
  recommendationConfigs: {
2120
2151
  [x: string]: {
@@ -2172,6 +2203,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2172
2203
  liquidSyntax: boolean;
2173
2204
  autosave: boolean;
2174
2205
  allowlistEnabled: boolean;
2206
+ linkTrackingIds: boolean;
2175
2207
  };
2176
2208
  blocks: {
2177
2209
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -2253,6 +2285,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2253
2285
  customFieldAttributes: string[];
2254
2286
  selectedUnsubscribePages: number[];
2255
2287
  forceRecreate: boolean;
2288
+ trackIdCounter: number;
2256
2289
  migration: {
2257
2290
  recommendationConfigs: {
2258
2291
  [x: string]: {
@@ -2310,6 +2343,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2310
2343
  liquidSyntax: boolean;
2311
2344
  autosave: boolean;
2312
2345
  allowlistEnabled: boolean;
2346
+ linkTrackingIds: boolean;
2313
2347
  };
2314
2348
  blocks: {
2315
2349
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -2393,6 +2427,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2393
2427
  customFieldAttributes: string[];
2394
2428
  selectedUnsubscribePages: number[];
2395
2429
  forceRecreate: boolean;
2430
+ trackIdCounter: number;
2396
2431
  migration: {
2397
2432
  recommendationConfigs: {
2398
2433
  [x: string]: {
@@ -2450,6 +2485,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2450
2485
  liquidSyntax: boolean;
2451
2486
  autosave: boolean;
2452
2487
  allowlistEnabled: boolean;
2488
+ linkTrackingIds: boolean;
2453
2489
  };
2454
2490
  blocks: {
2455
2491
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -9,6 +9,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
9
9
  isStripoInitialized: boolean;
10
10
  templateId: string;
11
11
  syncModulesEnabled: boolean;
12
+ trackIdSessionFloor: number;
12
13
  }, {
13
14
  isEditorToolbarVisible: (state: {
14
15
  loadingStatus: boolean;
@@ -21,6 +22,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
21
22
  isStripoInitialized: boolean;
22
23
  templateId: string;
23
24
  syncModulesEnabled: boolean;
25
+ trackIdSessionFloor: number;
24
26
  } & import("pinia").PiniaCustomStateProperties<{
25
27
  loadingStatus: boolean;
26
28
  isCodeEditorOpen: boolean;
@@ -32,6 +34,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
32
34
  isStripoInitialized: boolean;
33
35
  templateId: string;
34
36
  syncModulesEnabled: boolean;
37
+ trackIdSessionFloor: number;
35
38
  }>) => boolean;
36
39
  isUndoButtonDisabled: (state: {
37
40
  loadingStatus: boolean;
@@ -44,6 +47,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
44
47
  isStripoInitialized: boolean;
45
48
  templateId: string;
46
49
  syncModulesEnabled: boolean;
50
+ trackIdSessionFloor: number;
47
51
  } & import("pinia").PiniaCustomStateProperties<{
48
52
  loadingStatus: boolean;
49
53
  isCodeEditorOpen: boolean;
@@ -55,6 +59,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
55
59
  isStripoInitialized: boolean;
56
60
  templateId: string;
57
61
  syncModulesEnabled: boolean;
62
+ trackIdSessionFloor: number;
58
63
  }>) => boolean;
59
64
  isRedoButtonDisabled: (state: {
60
65
  loadingStatus: boolean;
@@ -67,6 +72,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
67
72
  isStripoInitialized: boolean;
68
73
  templateId: string;
69
74
  syncModulesEnabled: boolean;
75
+ trackIdSessionFloor: number;
70
76
  } & import("pinia").PiniaCustomStateProperties<{
71
77
  loadingStatus: boolean;
72
78
  isCodeEditorOpen: boolean;
@@ -78,6 +84,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
78
84
  isStripoInitialized: boolean;
79
85
  templateId: string;
80
86
  syncModulesEnabled: boolean;
87
+ trackIdSessionFloor: number;
81
88
  }>) => boolean;
82
89
  isCodeEditorButtonDisabled: (state: {
83
90
  loadingStatus: boolean;
@@ -90,6 +97,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
90
97
  isStripoInitialized: boolean;
91
98
  templateId: string;
92
99
  syncModulesEnabled: boolean;
100
+ trackIdSessionFloor: number;
93
101
  } & import("pinia").PiniaCustomStateProperties<{
94
102
  loadingStatus: boolean;
95
103
  isCodeEditorOpen: boolean;
@@ -101,6 +109,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
101
109
  isStripoInitialized: boolean;
102
110
  templateId: string;
103
111
  syncModulesEnabled: boolean;
112
+ trackIdSessionFloor: number;
104
113
  }>) => boolean;
105
114
  isPreviewButtonDisabled: (state: {
106
115
  loadingStatus: boolean;
@@ -113,6 +122,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
113
122
  isStripoInitialized: boolean;
114
123
  templateId: string;
115
124
  syncModulesEnabled: boolean;
125
+ trackIdSessionFloor: number;
116
126
  } & import("pinia").PiniaCustomStateProperties<{
117
127
  loadingStatus: boolean;
118
128
  isCodeEditorOpen: boolean;
@@ -124,6 +134,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
124
134
  isStripoInitialized: boolean;
125
135
  templateId: string;
126
136
  syncModulesEnabled: boolean;
137
+ trackIdSessionFloor: number;
127
138
  }>) => boolean;
128
139
  isViewOptionsDisabled: (state: {
129
140
  loadingStatus: boolean;
@@ -136,6 +147,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
136
147
  isStripoInitialized: boolean;
137
148
  templateId: string;
138
149
  syncModulesEnabled: boolean;
150
+ trackIdSessionFloor: number;
139
151
  } & import("pinia").PiniaCustomStateProperties<{
140
152
  loadingStatus: boolean;
141
153
  isCodeEditorOpen: boolean;
@@ -147,6 +159,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
147
159
  isStripoInitialized: boolean;
148
160
  templateId: string;
149
161
  syncModulesEnabled: boolean;
162
+ trackIdSessionFloor: number;
150
163
  }>) => boolean;
151
164
  isVersionHistoryButtonDisabled: (state: {
152
165
  loadingStatus: boolean;
@@ -159,6 +172,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
159
172
  isStripoInitialized: boolean;
160
173
  templateId: string;
161
174
  syncModulesEnabled: boolean;
175
+ trackIdSessionFloor: number;
162
176
  } & import("pinia").PiniaCustomStateProperties<{
163
177
  loadingStatus: boolean;
164
178
  isCodeEditorOpen: boolean;
@@ -170,6 +184,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
170
184
  isStripoInitialized: boolean;
171
185
  templateId: string;
172
186
  syncModulesEnabled: boolean;
187
+ trackIdSessionFloor: number;
173
188
  }>) => boolean;
174
189
  isExportButtonDisabled: (state: {
175
190
  loadingStatus: boolean;
@@ -182,6 +197,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
182
197
  isStripoInitialized: boolean;
183
198
  templateId: string;
184
199
  syncModulesEnabled: boolean;
200
+ trackIdSessionFloor: number;
185
201
  } & import("pinia").PiniaCustomStateProperties<{
186
202
  loadingStatus: boolean;
187
203
  isCodeEditorOpen: boolean;
@@ -193,6 +209,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
193
209
  isStripoInitialized: boolean;
194
210
  templateId: string;
195
211
  syncModulesEnabled: boolean;
212
+ trackIdSessionFloor: number;
196
213
  }>) => boolean;
197
214
  isSaveAsButtonDisabled: (state: {
198
215
  loadingStatus: boolean;
@@ -205,6 +222,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
205
222
  isStripoInitialized: boolean;
206
223
  templateId: string;
207
224
  syncModulesEnabled: boolean;
225
+ trackIdSessionFloor: number;
208
226
  } & import("pinia").PiniaCustomStateProperties<{
209
227
  loadingStatus: boolean;
210
228
  isCodeEditorOpen: boolean;
@@ -216,6 +234,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
216
234
  isStripoInitialized: boolean;
217
235
  templateId: string;
218
236
  syncModulesEnabled: boolean;
237
+ trackIdSessionFloor: number;
219
238
  }>) => boolean;
220
239
  isTestButtonDisabled: (state: {
221
240
  loadingStatus: boolean;
@@ -228,6 +247,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
228
247
  isStripoInitialized: boolean;
229
248
  templateId: string;
230
249
  syncModulesEnabled: boolean;
250
+ trackIdSessionFloor: number;
231
251
  } & import("pinia").PiniaCustomStateProperties<{
232
252
  loadingStatus: boolean;
233
253
  isCodeEditorOpen: boolean;
@@ -239,6 +259,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
239
259
  isStripoInitialized: boolean;
240
260
  templateId: string;
241
261
  syncModulesEnabled: boolean;
262
+ trackIdSessionFloor: number;
242
263
  }>) => boolean;
243
264
  isSaveButtonDisabled: (state: {
244
265
  loadingStatus: boolean;
@@ -251,6 +272,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
251
272
  isStripoInitialized: boolean;
252
273
  templateId: string;
253
274
  syncModulesEnabled: boolean;
275
+ trackIdSessionFloor: number;
254
276
  } & import("pinia").PiniaCustomStateProperties<{
255
277
  loadingStatus: boolean;
256
278
  isCodeEditorOpen: boolean;
@@ -262,6 +284,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
262
284
  isStripoInitialized: boolean;
263
285
  templateId: string;
264
286
  syncModulesEnabled: boolean;
287
+ trackIdSessionFloor: number;
265
288
  }>) => boolean;
266
289
  isInSaveableState: (state: {
267
290
  loadingStatus: boolean;
@@ -274,6 +297,7 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
274
297
  isStripoInitialized: boolean;
275
298
  templateId: string;
276
299
  syncModulesEnabled: boolean;
300
+ trackIdSessionFloor: number;
277
301
  } & import("pinia").PiniaCustomStateProperties<{
278
302
  loadingStatus: boolean;
279
303
  isCodeEditorOpen: boolean;
@@ -285,5 +309,6 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
285
309
  isStripoInitialized: boolean;
286
310
  templateId: string;
287
311
  syncModulesEnabled: boolean;
312
+ trackIdSessionFloor: number;
288
313
  }>) => boolean;
289
314
  }, {}>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Persistent link tracking ids for the click heatmap (SD-141414).
3
+ * Pure string transforms — no DOM parse/serialize round-trip, safe for both
4
+ * Stripo raw HTML and hand-authored HTML-editor documents. Shared with email-fe.
5
+ */
6
+ export declare const TRACK_ID_ATTRIBUTE = "data-ins-track-id";
7
+ export declare const TRACK_SEQ_ATTRIBUTE = "data-ins-track-seq";
8
+ export interface TrackingIdResult {
9
+ html: string;
10
+ changed: boolean;
11
+ nextSeq: number;
12
+ }
13
+ /**
14
+ * Reads the persisted id high-water mark: <body> attr, then <html> attr,
15
+ * then the leading comment fallback. Returns 0 when absent.
16
+ */
17
+ export declare function readTrackSeq(html: string): number;
18
+ /**
19
+ * Ensures every <a> opening tag carries a unique positive-integer id and the
20
+ * document records the id high-water mark. Ids are minted above
21
+ * max(persisted seq, max id in document, floor) so deleted ids are never
22
+ * reused — even after a version restore or paste-over (floor = session floor).
23
+ * Idempotent: a document already normalized returns changed=false.
24
+ */
25
+ export declare function assignTrackingIds(html: string, floor?: number): TrackingIdResult;
@@ -103,6 +103,13 @@ ue-control-panel,
103
103
  display: none !important;
104
104
  }
105
105
 
106
+ /* Stripo 2.72 added a "Restore default styles" button to the settings header that does
107
+ nothing when clicked — styles are never reset. Reported upstream; hidden until fixed.
108
+ Scoped to Stripo's own e2e hook class so the sibling close (X) and level-up buttons stay. */
109
+ .control-panel-header .e2e-restore-default-styles {
110
+ display: none !important;
111
+ }
112
+
106
113
  .container.droppable-header-container ue-button:last-child {
107
114
  margin-right: 0;
108
115
  }
@@ -47,6 +47,14 @@ const n = `.esd-x,
47
47
  display: none !important;
48
48
  }
49
49
 
50
+ /* Stripo 2.72 renders drag-to-resize handles over images. Product image size must come
51
+ from the Image Size control in the settings panel, not free-hand dragging, which breaks
52
+ the card layout. Grid layout uses .product-image, list layout .product-image-cell. */
53
+ .recommendation-block-v2 .product-image ue-image-resize-control,
54
+ .recommendation-block-v2 .product-image-cell ue-image-resize-control {
55
+ display: none !important;
56
+ }
57
+
50
58
  /* Mobile layout: hide mobile container by default in editor */
51
59
  .ins-recommendation-mobile-container {
52
60
  display: none;