@cnv-vn/track 0.2.0-beta.7 → 0.3.0-beta.1

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.
@@ -496,6 +496,135 @@ interface RemoteConfigEnvelope {
496
496
  zaloQrLogin?: {
497
497
  enabled?: boolean;
498
498
  };
499
+ /** Cấu hình Launcher (FAB loyalty/rewards) đã publish — `config: null` = chưa cấu hình lần nào. */
500
+ launcher?: {
501
+ /** Version riêng của Launcher (tăng mỗi lần Lưu) — KHÔNG dùng chung với `version` ở trên (2 tính năng publish độc lập). */
502
+ version?: number;
503
+ updatedAt?: string;
504
+ config?: LauncherRemoteConfig | null;
505
+ };
506
+ /** Cấu hình Panel (nội dung mở ra khi khách click Launcher) đã publish — entity RIÊNG với
507
+ * `launcher` (xem `ke_hoach_tinh_nang_launcher.md` §8.1), `config: null` = chưa cấu hình lần nào. */
508
+ panel?: {
509
+ /** Version riêng của Panel — publish độc lập với `launcher`/`version` ở trên. */
510
+ version?: number;
511
+ updatedAt?: string;
512
+ config?: PanelRemoteConfig | null;
513
+ };
514
+ }
515
+ /**
516
+ * Cấu hình Launcher do dashboard CDP quản lý (`ke_hoach_tinh_nang_launcher.md` §7) — khớp 1:1
517
+ * model `LauncherConfigDocument.LauncherConfig` (tracking-system) và `LauncherConfig`
518
+ * (cdp-frontend, `tracking-launcher-config.model.ts`). SDK chỉ ĐỌC bản published, dùng để tự
519
+ * render FAB (xem `core/launcher.ts`) — không có API ghi nào ở SDK.
520
+ */
521
+ interface LauncherRemoteConfig {
522
+ buttonTextDesktop?: string;
523
+ buttonTextMobile?: string;
524
+ /** `'DEFAULT'` dùng `iconPreset`; `'CUSTOM'` dùng `customIconUrl`. */
525
+ iconType?: 'DEFAULT' | 'CUSTOM';
526
+ iconPreset?: 'BAG_HEART' | 'TAG' | 'CROWN' | 'STAR' | 'GIFT';
527
+ customIconUrl?: string | null;
528
+ buttonShape?: 'SQUARE' | 'SHAVED' | 'ROUNDED' | 'CIRCULAR';
529
+ placementDesktop?: LauncherPlacement;
530
+ placementMobile?: LauncherPlacement;
531
+ backgroundColor?: string;
532
+ textColor?: string;
533
+ contentLayoutDesktop?: 'ICON_WITH_TEXT' | 'TEXT_ONLY' | 'ICON_ONLY';
534
+ contentLayoutMobile?: 'TEXT_ONLY' | 'ICON_ONLY';
535
+ deviceVisibility?: 'DESKTOP_AND_MOBILE' | 'DESKTOP_ONLY' | 'NONE';
536
+ hideOnHomepage?: boolean;
537
+ /** Mỗi phần tử là 1 chuỗi con cần khớp (contains) `location.pathname + location.search`. */
538
+ hideUrlConditions?: string[];
539
+ useCustomZIndex?: boolean;
540
+ zIndex?: number | null;
541
+ /** `true` ⇒ SDK áp style vị trí/z-index bằng `!important` (phòng CSS site đè lên). */
542
+ addImportantRule?: boolean;
543
+ }
544
+ interface LauncherPlacement {
545
+ position: 'LEFT' | 'RIGHT';
546
+ sideSpacing: number;
547
+ bottomSpacing: number;
548
+ }
549
+ /**
550
+ * Cấu hình Panel do dashboard CDP quản lý (`ke_hoach_tinh_nang_launcher.md` §8) — khớp 1:1
551
+ * model `PanelConfigDocument.PanelConfig` (tracking-system) và `PanelConfig` (cdp-frontend,
552
+ * `tracking-panel-config.model.ts`), TRỪ 2 field `bannerImageResourceKey`/`brandIconResourceKey`
553
+ * (chỉ dùng để quản lý media ở tầng admin, SDK chỉ cần `url` để render). SDK chỉ ĐỌC bản
554
+ * published, dùng để tự render nội dung Panel (xem `core/panel.ts`).
555
+ */
556
+ interface PanelRemoteConfig {
557
+ bannerImageUrl?: string | null;
558
+ brandIconUrl?: string | null;
559
+ headerVisitor?: PanelHeaderCopy;
560
+ headerMember?: PanelHeaderCopy;
561
+ accountCreationCta?: PanelAccountCreationCta;
562
+ /** Thứ tự + bật/tắt từng section — chỉ `POINTS` có nội dung thật, xem `core/panel.ts`. */
563
+ sections?: PanelSectionConfig[];
564
+ /**
565
+ * Block tự soạn cho view "Cách kiếm thêm điểm". Rỗng/thiếu ⇒ dòng menu giữ hành vi cũ: chỉ bắn
566
+ * `cnv:panel:menu-click` cho site tự điều hướng, Panel KHÔNG mở view nào (shop chưa cấu hình thì
567
+ * không được mở ra một màn trống).
568
+ */
569
+ earnBlocks?: PanelContentBlock[];
570
+ /** Cùng vai trò `earnBlocks`, cho view "Cách đổi điểm". */
571
+ redeemBlocks?: PanelContentBlock[];
572
+ theme?: 'LIGHT' | 'DARK';
573
+ colors?: PanelColors;
574
+ shapes?: PanelShapes;
575
+ wallpaper?: 'NONE' | 'WAVES' | 'CUBES' | 'FUN' | 'GEOMETRIC' | 'CROSS_HATCHING';
576
+ /** `true` ⇒ bỏ chân panel "Cung cấp bởi CNV Loyalty". Thiếu/`false` = vẫn hiện (mặc định). */
577
+ hideBranding?: boolean;
578
+ }
579
+ interface PanelHeaderCopy {
580
+ caption?: string;
581
+ title?: string;
582
+ }
583
+ interface PanelAccountCreationCta {
584
+ title?: string;
585
+ description?: string;
586
+ signInLinkText?: string;
587
+ createAccountButtonText?: string;
588
+ }
589
+ interface PanelSectionConfig {
590
+ type?: 'POINTS' | 'REFERRAL' | 'VIP';
591
+ enabled?: boolean;
592
+ order?: number;
593
+ }
594
+ /**
595
+ * Icon dựng sẵn cho 1 block nội dung — merchant CHỌN từ bộ này ở dashboard, không tải ảnh riêng.
596
+ * Khoá lạ (dashboard mới hơn bản SDK đang cache trên máy khách) lùi về icon của chính view chứ
597
+ * không vẽ ô rỗng — cùng nguyên tắc fail-safe `SECTIONS` đang áp cho section type lạ.
598
+ */
599
+ type PanelBlockIcon = 'ORDER' | 'STAR' | 'GIFT' | 'USERS' | 'CAKE' | 'SHARE' | 'COIN' | 'CHECK';
600
+ /**
601
+ * 1 block nội dung do MERCHANT tự soạn cho view "Cách kiếm thêm điểm" / "Cách đổi điểm".
602
+ *
603
+ * Panel hiển thị NGUYÊN VĂN, không suy ra con số nào từ nghiệp vụ loyalty — khác hẳn `points`/
604
+ * `tier` (số thật, do server tính). Đây là chỗ shop tự khai luật tích/đổi điểm của mình, vì luật
605
+ * đó nằm ngoài dữ liệu mà tracking-api đọc được.
606
+ */
607
+ interface PanelContentBlock {
608
+ icon?: PanelBlockIcon;
609
+ title?: string;
610
+ description?: string;
611
+ }
612
+ interface PanelColors {
613
+ bannerBg?: string;
614
+ bannerFont?: string;
615
+ /** Mirror model admin — `core/panel.ts` hiện CHƯA render field này (Panel không có header bar riêng). */
616
+ headerBarFont?: string;
617
+ buttonBg?: string;
618
+ buttonFont?: string;
619
+ linkColor?: string;
620
+ iconColor?: string;
621
+ }
622
+ interface PanelShapes {
623
+ container?: 'SQUARE' | 'ROUNDED';
624
+ card?: 'SQUARE' | 'ROUNDED';
625
+ button?: 'SQUARE' | 'ROUNDED';
626
+ /** Mirror model admin — `core/panel.ts` hiện CHƯA render field này (Panel chưa có input nào). */
627
+ input?: 'SQUARE' | 'ROUNDED';
499
628
  }
500
629
  /**
501
630
  * Lý do `loginWithZalo()` thất bại (`ZaloQrLoginError.reason`). LƯU Ý phạm vi
@@ -551,6 +680,19 @@ interface ZaloQrLoginResult {
551
680
  level?: string;
552
681
  /** Điểm kinh nghiệm/tích luỹ hiện tại (nếu có). */
553
682
  xp?: number;
683
+ /**
684
+ * JWT HẸP QUYỀN, sống 24h — dùng DUY NHẤT để gọi lại `GET {endpoint}/panel/session` khôi phục
685
+ * trạng thái Member sau khi khách F5 lại trang, KHÁC HẲN apiToken/loginToken thật (365 ngày, đã
686
+ * bị chặn không trả về client — xem javadoc trên). An toàn hơn hẳn token thật vì: hẹp quyền (chỉ
687
+ * verify được ở đúng 1 endpoint này), sống ngắn (24h), và khoá ký riêng theo từng project — lộ
688
+ * token này chỉ lộ đúng tên/hạng/điểm của 1 khách, không dùng được ở bất kỳ API nào khác trong hệ
689
+ * sinh thái CNV. `panel.ts` tự lưu 2 field này vào `localStorage` để khôi phục Member state lúc
690
+ * mở lại trang — integrator dùng `loginWithZalo()` trực tiếp (không qua Panel) có thể tự làm
691
+ * tương tự nếu muốn hành vi "nhớ đăng nhập" giống vậy.
692
+ */
693
+ panelSessionToken?: string;
694
+ /** Epoch-ms hết hạn của {@link panelSessionToken} — so `Date.now() > panelSessionExp` không cần decode JWT. */
695
+ panelSessionExp?: number;
554
696
  }
555
697
  /**
556
698
  * Phiên QR-login đang chờ người dùng quét. SDK KHÔNG tự vẽ QR — host page tự
@@ -644,7 +786,10 @@ interface Dispatcher {
644
786
  * spin up an isolated copy without leaking state between cases.
645
787
  *
646
788
  * Public API and what each method does:
647
- * init(projectId, options?) → set up runtime, build transport
789
+ * init(projectId, options?) → set up runtime, build transport,
790
+ * optionally fire an automatic pageview
791
+ * pageview(name?, properties?) → emit `type:"page"`
792
+ * page(name?, properties?) → emit `type:"page"` (alias of pageview)
648
793
  * track(event, properties?) → emit `type:"track"`
649
794
  * identify(userId, traits?) → emit `type:"identify"`, persist uid
650
795
  * reset() → rotate anonymousId, drop userId
@@ -652,14 +797,16 @@ interface Dispatcher {
652
797
  * consent(state) → merge consent flags
653
798
  * set(options) → patch SDK options at runtime
654
799
  *
800
+ * `pageview()`/`page()` mở lại platform-wide (mọi project, không whitelist) — backend
801
+ * (`CnvIngestService.enforceEventAllowed`) đã cho `type=page` qua không điều kiện, xem cùng thay
802
+ * đổi phía tracking-api.
803
+ *
655
804
  * RETIRED (platform-wide, mọi site — ke_hoach_gioi_han_event_cho_phep.md):
656
- * `pageview()`/`page()`/`screen()`/`group()`/`alias()` vẫn còn tồn tại như no-op (giữ chữ ký hàm
657
- * để không phá interface `Dispatcher`/`Runtime` và code cũ gọi vào không throw), nhưng KHÔNG còn
658
- * gửi gì đi nữa cho BẤT KỲ site nào — backend (`CnvIngestService.enforceEventAllowed`) đã luôn từ
659
- * chối các type này khi project resolve được rồi, nên quyết định là bỏ hẳn khả năng gửi ở SDK
660
- * luôn, không riêng site nào. Chỉ còn `track()` + `identify()` hoạt động thật — whitelist tên
661
- * event nào được phép là việc của backend (`allowedEventNames`), SDK không tự gate gì thêm ở phía
662
- * client nữa (tránh khai báo trùng 2 nơi dễ lệch nhau).
805
+ * `screen()`/`group()`/`alias()` vẫn còn tồn tại như no-op (giữ chữ ký hàm để không phá interface
806
+ * `Dispatcher`/`Runtime` và code cũ gọi vào không throw), nhưng KHÔNG còn gửi gì đi nữa cho BẤT KỲ
807
+ * site nào — backend vẫn luôn từ chối các type này khi project resolve được rồi. Whitelist tên
808
+ * event nào được phép cho `track()` là việc của backend (`allowedEventNames`), SDK không tự gate
809
+ * gì thêm ở phía client nữa (tránh khai báo trùng 2 nơi dễ lệch nhau).
663
810
  *
664
811
  * Init order matters:
665
812
  * 1. Cookie / LS reads happen on demand (lazy) — every event resolves
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cnv-vn/track",
3
- "version": "0.2.0-beta.7",
4
- "description": "CNV Tracking SDK — lightweight, async-first web analytics tracker (<20KB gzipped).",
3
+ "version": "0.3.0-beta.1",
4
+ "description": "CNV Tracking SDK — lightweight, async-first web analytics tracker (<30KB gzipped).",
5
5
  "keywords": [
6
6
  "analytics",
7
7
  "tracking",
@@ -97,14 +97,17 @@
97
97
  {
98
98
  "name": "IIFE (minified + gzipped)",
99
99
  "path": "dist/cnv-track.min.js",
100
- "limit": "20 KB",
100
+ "limit": "50 KB",
101
101
  "gzip": true
102
102
  },
103
103
  {
104
104
  "name": "ESM tree-shaken (gzipped)",
105
105
  "path": "dist/cnv-track.esm.js",
106
- "limit": "20 KB",
106
+ "limit": "50 KB",
107
107
  "gzip": true
108
108
  }
109
- ]
109
+ ],
110
+ "dependencies": {
111
+ "qrcode-generator": "^2.0.4"
112
+ }
110
113
  }