connectbase-client 1.10.0 → 1.12.0
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.
- package/CHANGELOG.md +85 -0
- package/dist/connect-base.umd.js +3 -3
- package/dist/index.d.mts +133 -5
- package/dist/index.d.ts +133 -5
- package/dist/index.js +99 -4
- package/dist/index.mjs +99 -4
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -241,7 +241,66 @@ interface AnalyticsRangeOptions {
|
|
|
241
241
|
interface VisitorListOptions {
|
|
242
242
|
limit?: number;
|
|
243
243
|
offset?: number;
|
|
244
|
-
|
|
244
|
+
/**
|
|
245
|
+
* 백엔드가 인식하는 정렬 키 — 외 값은 silent 로 default(`last_visit`) 처리됩니다.
|
|
246
|
+
*
|
|
247
|
+
* 1.12.0 에서 백엔드 실제 동작에 맞춰 enum 정정 (1.10/1.11 의 `total_visits`/
|
|
248
|
+
* `total_page_views` 는 백엔드에서 인식되지 않아 항상 default 분기였음).
|
|
249
|
+
*/
|
|
250
|
+
sort_by?: 'last_visit' | 'visits' | 'page_views' | 'first_visit';
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* 멤버별 합산 방문자 그룹 항목.
|
|
254
|
+
*
|
|
255
|
+
* 한 명의 회원이 여러 디바이스/브라우저로 접속했을 때 visitor row 들을 합쳐 단일 row.
|
|
256
|
+
* 익명 visitor 는 `app_member_id == undefined` 로 단일 row 그대로 노출되며 `visitor_count == 1`.
|
|
257
|
+
*
|
|
258
|
+
* `visitor_count` 는 "디바이스 수" 가 아닌 **"추적 브라우저 인스턴스 수"** 를 의미합니다.
|
|
259
|
+
* 같은 디바이스에서 시크릿모드 + 일반모드는 visitor 2 = visitor_count 2 로 카운트됩니다.
|
|
260
|
+
*/
|
|
261
|
+
interface VisitorGroupItem {
|
|
262
|
+
app_member_id?: string;
|
|
263
|
+
/** 익명 visitor row 의 경우 단일 visitor_uid. 회원 그룹은 visitor_uids 참조. */
|
|
264
|
+
visitor_uid?: string;
|
|
265
|
+
/** 회원 그룹에 속한 visitor_uid 목록. 익명 row 는 undefined. */
|
|
266
|
+
visitor_uids?: string[];
|
|
267
|
+
visitor_count: number;
|
|
268
|
+
total_visits: number;
|
|
269
|
+
total_page_views: number;
|
|
270
|
+
first_visit_at: string;
|
|
271
|
+
last_visit_at: string;
|
|
272
|
+
country?: string;
|
|
273
|
+
is_bot: boolean;
|
|
274
|
+
}
|
|
275
|
+
interface VisitorGroupListResponse {
|
|
276
|
+
groups: VisitorGroupItem[];
|
|
277
|
+
total: number;
|
|
278
|
+
limit: number;
|
|
279
|
+
offset: number;
|
|
280
|
+
has_more: boolean;
|
|
281
|
+
}
|
|
282
|
+
interface VisitorByMemberResponse {
|
|
283
|
+
app_member_id: string;
|
|
284
|
+
visitor_uids: string[];
|
|
285
|
+
visitor_count: number;
|
|
286
|
+
total_visits: number;
|
|
287
|
+
total_page_views: number;
|
|
288
|
+
first_visit_at: string;
|
|
289
|
+
last_visit_at: string;
|
|
290
|
+
country?: string;
|
|
291
|
+
is_bot: boolean;
|
|
292
|
+
}
|
|
293
|
+
interface MergeVisitorsRequest {
|
|
294
|
+
source_visitor_uid: string;
|
|
295
|
+
/** target_visitor_uid 또는 target_member_id 중 하나는 필수. */
|
|
296
|
+
target_visitor_uid?: string;
|
|
297
|
+
target_member_id?: string;
|
|
298
|
+
}
|
|
299
|
+
interface MergeVisitorsResponse {
|
|
300
|
+
success: boolean;
|
|
301
|
+
target_visitor_id: string;
|
|
302
|
+
moved_records: number;
|
|
303
|
+
message?: string;
|
|
245
304
|
}
|
|
246
305
|
declare class SessionManager {
|
|
247
306
|
private _sessionId;
|
|
@@ -302,15 +361,38 @@ declare class AnalyticsAPI {
|
|
|
302
361
|
*/
|
|
303
362
|
trackEvent(name: string, properties?: Record<string, unknown>): void;
|
|
304
363
|
/**
|
|
305
|
-
* 사용자 식별 (로그인
|
|
306
|
-
*
|
|
364
|
+
* 사용자 식별 (로그인 직후 호출).
|
|
365
|
+
*
|
|
366
|
+
* 이후 모든 방문 배치에 `app_member_id` 가 첨부되어 새 활동은 회원으로 기록됩니다.
|
|
367
|
+
* 추가로 **현재 visitor_uid 의 기존 익명 활동을 즉시 회원에게 backfill** 하기 위해
|
|
368
|
+
* 백엔드 `link-member` 엔드포인트를 한 번 호출합니다 (1.11.0+). 호출 실패는
|
|
369
|
+
* silent — 다음 batch 가 닿을 때 백엔드 자동 매핑이 동일하게 처리하므로 자가 복구.
|
|
370
|
+
*
|
|
371
|
+
* 산업 표준(GA4 User-ID, Mixpanel/PostHog `identify`) 과 동작 정합.
|
|
372
|
+
*
|
|
373
|
+
* @example
|
|
374
|
+
* ```ts
|
|
375
|
+
* // 로그인 성공 직후
|
|
376
|
+
* await cb.auth.signIn({ email, password })
|
|
377
|
+
* cb.analytics.identify(member.id)
|
|
378
|
+
* ```
|
|
307
379
|
*/
|
|
308
380
|
identify(memberId: string): void;
|
|
309
381
|
/**
|
|
310
|
-
* 방문자 트래커에 현재 회원 ID 설정 (로그인/게스트 가입 시 호출)
|
|
311
|
-
*
|
|
382
|
+
* 방문자 트래커에 현재 회원 ID 설정 (로그인/게스트 가입 시 호출).
|
|
383
|
+
*
|
|
384
|
+
* `identify()` 와 달리 즉시 backfill 호출은 하지 않습니다 — 단순히 이후 batch 의
|
|
385
|
+
* `app_member_id` 값만 갱신. null 을 넘기면 익명 상태로 복귀 (로그아웃).
|
|
312
386
|
*/
|
|
313
387
|
setMemberId(memberId: string | null): void;
|
|
388
|
+
/**
|
|
389
|
+
* 백엔드 link-member 엔드포인트 한 번 호출 — 즉시 backfill 트리거.
|
|
390
|
+
*
|
|
391
|
+
* - 첫 페이지뷰가 아직 백엔드에 닿기 전이면 visitor 가 없어 404. 무시 — 다음 batch 가
|
|
392
|
+
* 가면 백엔드 BatchRecordVisit 가 자동 LinkMember 를 호출.
|
|
393
|
+
* - storage_web_id 가 init 안 됐거나 모든 종류의 네트워크 오류 — silent fail.
|
|
394
|
+
*/
|
|
395
|
+
private linkMemberSilent;
|
|
314
396
|
/** 현재 설정된 회원 ID 조회 (미설정 시 null) */
|
|
315
397
|
getMemberId(): string | null;
|
|
316
398
|
/**
|
|
@@ -363,6 +445,52 @@ declare class AnalyticsAPI {
|
|
|
363
445
|
* 방문자 목록 조회 — JWT/cb_sk_ 인증 필요.
|
|
364
446
|
*/
|
|
365
447
|
getVisitors(storageWebId?: string, options?: VisitorListOptions): Promise<VisitorListResponse>;
|
|
448
|
+
/**
|
|
449
|
+
* 멤버별 합산 방문자 그룹 조회 — JWT/cb_sk_ 인증 필요. (1.11+)
|
|
450
|
+
*
|
|
451
|
+
* `getVisitors` 와 달리 visitor row 들을 `app_member_id` 로 합쳐 단일 row 로 반환.
|
|
452
|
+
* 같은 사람이 PC + 모바일 + 태블릿으로 접속한 경우 visitor 3개 → 그룹 1개.
|
|
453
|
+
* 익명 visitor 는 단일 row 로 그대로 포함되어 페이지네이션이 일관됨.
|
|
454
|
+
*
|
|
455
|
+
* @example
|
|
456
|
+
* ```ts
|
|
457
|
+
* const { groups } = await cb.analytics.getVisitorGroups('019d8...', { limit: 50 })
|
|
458
|
+
* for (const g of groups) {
|
|
459
|
+
* if (g.app_member_id) console.log(`${g.app_member_id}: ${g.visitor_count} 디바이스`)
|
|
460
|
+
* }
|
|
461
|
+
* ```
|
|
462
|
+
*/
|
|
463
|
+
getVisitorGroups(storageWebId?: string, options?: VisitorListOptions): Promise<VisitorGroupListResponse>;
|
|
464
|
+
/**
|
|
465
|
+
* 단건 멤버 합산 방문자 조회 — JWT/cb_sk_ 인증 필요. (1.11+)
|
|
466
|
+
*
|
|
467
|
+
* 어드민 회원 상세 페이지처럼 **한 명만 필요**할 때. 페이지네이션 풀 다운 없이
|
|
468
|
+
* 한 번의 호출로 합산 결과 반환.
|
|
469
|
+
*
|
|
470
|
+
* @example
|
|
471
|
+
* ```ts
|
|
472
|
+
* const v = await cb.analytics.getVisitorByMember('019d8...', memberId)
|
|
473
|
+
* console.log(`${v.visitor_count} 디바이스, 총 ${v.total_page_views} pv`)
|
|
474
|
+
* ```
|
|
475
|
+
*/
|
|
476
|
+
getVisitorByMember(storageWebId: string | undefined, memberId: string): Promise<VisitorByMemberResponse>;
|
|
477
|
+
/**
|
|
478
|
+
* 두 visitor 를 한 사람으로 통합하는 admin 작업 — JWT/cb_sk_ 인증 필요. (1.11+)
|
|
479
|
+
*
|
|
480
|
+
* 외부 인증 시스템에서 두 visitor 가 동일인임을 알았을 때 사용. source 의 자식 레코드
|
|
481
|
+
* (page_views, daily, custom_events, experiment_assignments, heatmap_events,
|
|
482
|
+
* session_recordings) 를 target 으로 옮기고 source visitor 는 삭제됨.
|
|
483
|
+
*
|
|
484
|
+
* @param request 둘 중 하나 필수: `target_visitor_uid` 또는 `target_member_id`.
|
|
485
|
+
* @example
|
|
486
|
+
* ```ts
|
|
487
|
+
* await cb.analytics.mergeVisitors('019d8...', {
|
|
488
|
+
* source_visitor_uid: 'old-uid',
|
|
489
|
+
* target_member_id: '01a...',
|
|
490
|
+
* })
|
|
491
|
+
* ```
|
|
492
|
+
*/
|
|
493
|
+
mergeVisitors(storageWebId: string | undefined, request: MergeVisitorsRequest): Promise<MergeVisitorsResponse>;
|
|
366
494
|
/**
|
|
367
495
|
* 조회 메서드 공통 가드 — Public Key 인증 SDK 인스턴스에서는 명확한 에러를 던진다.
|
|
368
496
|
* 백엔드 라우트는 cb_pk_ 를 거부하므로 호출 자체를 막는 것이 디버깅에 유리.
|
package/dist/index.d.ts
CHANGED
|
@@ -241,7 +241,66 @@ interface AnalyticsRangeOptions {
|
|
|
241
241
|
interface VisitorListOptions {
|
|
242
242
|
limit?: number;
|
|
243
243
|
offset?: number;
|
|
244
|
-
|
|
244
|
+
/**
|
|
245
|
+
* 백엔드가 인식하는 정렬 키 — 외 값은 silent 로 default(`last_visit`) 처리됩니다.
|
|
246
|
+
*
|
|
247
|
+
* 1.12.0 에서 백엔드 실제 동작에 맞춰 enum 정정 (1.10/1.11 의 `total_visits`/
|
|
248
|
+
* `total_page_views` 는 백엔드에서 인식되지 않아 항상 default 분기였음).
|
|
249
|
+
*/
|
|
250
|
+
sort_by?: 'last_visit' | 'visits' | 'page_views' | 'first_visit';
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* 멤버별 합산 방문자 그룹 항목.
|
|
254
|
+
*
|
|
255
|
+
* 한 명의 회원이 여러 디바이스/브라우저로 접속했을 때 visitor row 들을 합쳐 단일 row.
|
|
256
|
+
* 익명 visitor 는 `app_member_id == undefined` 로 단일 row 그대로 노출되며 `visitor_count == 1`.
|
|
257
|
+
*
|
|
258
|
+
* `visitor_count` 는 "디바이스 수" 가 아닌 **"추적 브라우저 인스턴스 수"** 를 의미합니다.
|
|
259
|
+
* 같은 디바이스에서 시크릿모드 + 일반모드는 visitor 2 = visitor_count 2 로 카운트됩니다.
|
|
260
|
+
*/
|
|
261
|
+
interface VisitorGroupItem {
|
|
262
|
+
app_member_id?: string;
|
|
263
|
+
/** 익명 visitor row 의 경우 단일 visitor_uid. 회원 그룹은 visitor_uids 참조. */
|
|
264
|
+
visitor_uid?: string;
|
|
265
|
+
/** 회원 그룹에 속한 visitor_uid 목록. 익명 row 는 undefined. */
|
|
266
|
+
visitor_uids?: string[];
|
|
267
|
+
visitor_count: number;
|
|
268
|
+
total_visits: number;
|
|
269
|
+
total_page_views: number;
|
|
270
|
+
first_visit_at: string;
|
|
271
|
+
last_visit_at: string;
|
|
272
|
+
country?: string;
|
|
273
|
+
is_bot: boolean;
|
|
274
|
+
}
|
|
275
|
+
interface VisitorGroupListResponse {
|
|
276
|
+
groups: VisitorGroupItem[];
|
|
277
|
+
total: number;
|
|
278
|
+
limit: number;
|
|
279
|
+
offset: number;
|
|
280
|
+
has_more: boolean;
|
|
281
|
+
}
|
|
282
|
+
interface VisitorByMemberResponse {
|
|
283
|
+
app_member_id: string;
|
|
284
|
+
visitor_uids: string[];
|
|
285
|
+
visitor_count: number;
|
|
286
|
+
total_visits: number;
|
|
287
|
+
total_page_views: number;
|
|
288
|
+
first_visit_at: string;
|
|
289
|
+
last_visit_at: string;
|
|
290
|
+
country?: string;
|
|
291
|
+
is_bot: boolean;
|
|
292
|
+
}
|
|
293
|
+
interface MergeVisitorsRequest {
|
|
294
|
+
source_visitor_uid: string;
|
|
295
|
+
/** target_visitor_uid 또는 target_member_id 중 하나는 필수. */
|
|
296
|
+
target_visitor_uid?: string;
|
|
297
|
+
target_member_id?: string;
|
|
298
|
+
}
|
|
299
|
+
interface MergeVisitorsResponse {
|
|
300
|
+
success: boolean;
|
|
301
|
+
target_visitor_id: string;
|
|
302
|
+
moved_records: number;
|
|
303
|
+
message?: string;
|
|
245
304
|
}
|
|
246
305
|
declare class SessionManager {
|
|
247
306
|
private _sessionId;
|
|
@@ -302,15 +361,38 @@ declare class AnalyticsAPI {
|
|
|
302
361
|
*/
|
|
303
362
|
trackEvent(name: string, properties?: Record<string, unknown>): void;
|
|
304
363
|
/**
|
|
305
|
-
* 사용자 식별 (로그인
|
|
306
|
-
*
|
|
364
|
+
* 사용자 식별 (로그인 직후 호출).
|
|
365
|
+
*
|
|
366
|
+
* 이후 모든 방문 배치에 `app_member_id` 가 첨부되어 새 활동은 회원으로 기록됩니다.
|
|
367
|
+
* 추가로 **현재 visitor_uid 의 기존 익명 활동을 즉시 회원에게 backfill** 하기 위해
|
|
368
|
+
* 백엔드 `link-member` 엔드포인트를 한 번 호출합니다 (1.11.0+). 호출 실패는
|
|
369
|
+
* silent — 다음 batch 가 닿을 때 백엔드 자동 매핑이 동일하게 처리하므로 자가 복구.
|
|
370
|
+
*
|
|
371
|
+
* 산업 표준(GA4 User-ID, Mixpanel/PostHog `identify`) 과 동작 정합.
|
|
372
|
+
*
|
|
373
|
+
* @example
|
|
374
|
+
* ```ts
|
|
375
|
+
* // 로그인 성공 직후
|
|
376
|
+
* await cb.auth.signIn({ email, password })
|
|
377
|
+
* cb.analytics.identify(member.id)
|
|
378
|
+
* ```
|
|
307
379
|
*/
|
|
308
380
|
identify(memberId: string): void;
|
|
309
381
|
/**
|
|
310
|
-
* 방문자 트래커에 현재 회원 ID 설정 (로그인/게스트 가입 시 호출)
|
|
311
|
-
*
|
|
382
|
+
* 방문자 트래커에 현재 회원 ID 설정 (로그인/게스트 가입 시 호출).
|
|
383
|
+
*
|
|
384
|
+
* `identify()` 와 달리 즉시 backfill 호출은 하지 않습니다 — 단순히 이후 batch 의
|
|
385
|
+
* `app_member_id` 값만 갱신. null 을 넘기면 익명 상태로 복귀 (로그아웃).
|
|
312
386
|
*/
|
|
313
387
|
setMemberId(memberId: string | null): void;
|
|
388
|
+
/**
|
|
389
|
+
* 백엔드 link-member 엔드포인트 한 번 호출 — 즉시 backfill 트리거.
|
|
390
|
+
*
|
|
391
|
+
* - 첫 페이지뷰가 아직 백엔드에 닿기 전이면 visitor 가 없어 404. 무시 — 다음 batch 가
|
|
392
|
+
* 가면 백엔드 BatchRecordVisit 가 자동 LinkMember 를 호출.
|
|
393
|
+
* - storage_web_id 가 init 안 됐거나 모든 종류의 네트워크 오류 — silent fail.
|
|
394
|
+
*/
|
|
395
|
+
private linkMemberSilent;
|
|
314
396
|
/** 현재 설정된 회원 ID 조회 (미설정 시 null) */
|
|
315
397
|
getMemberId(): string | null;
|
|
316
398
|
/**
|
|
@@ -363,6 +445,52 @@ declare class AnalyticsAPI {
|
|
|
363
445
|
* 방문자 목록 조회 — JWT/cb_sk_ 인증 필요.
|
|
364
446
|
*/
|
|
365
447
|
getVisitors(storageWebId?: string, options?: VisitorListOptions): Promise<VisitorListResponse>;
|
|
448
|
+
/**
|
|
449
|
+
* 멤버별 합산 방문자 그룹 조회 — JWT/cb_sk_ 인증 필요. (1.11+)
|
|
450
|
+
*
|
|
451
|
+
* `getVisitors` 와 달리 visitor row 들을 `app_member_id` 로 합쳐 단일 row 로 반환.
|
|
452
|
+
* 같은 사람이 PC + 모바일 + 태블릿으로 접속한 경우 visitor 3개 → 그룹 1개.
|
|
453
|
+
* 익명 visitor 는 단일 row 로 그대로 포함되어 페이지네이션이 일관됨.
|
|
454
|
+
*
|
|
455
|
+
* @example
|
|
456
|
+
* ```ts
|
|
457
|
+
* const { groups } = await cb.analytics.getVisitorGroups('019d8...', { limit: 50 })
|
|
458
|
+
* for (const g of groups) {
|
|
459
|
+
* if (g.app_member_id) console.log(`${g.app_member_id}: ${g.visitor_count} 디바이스`)
|
|
460
|
+
* }
|
|
461
|
+
* ```
|
|
462
|
+
*/
|
|
463
|
+
getVisitorGroups(storageWebId?: string, options?: VisitorListOptions): Promise<VisitorGroupListResponse>;
|
|
464
|
+
/**
|
|
465
|
+
* 단건 멤버 합산 방문자 조회 — JWT/cb_sk_ 인증 필요. (1.11+)
|
|
466
|
+
*
|
|
467
|
+
* 어드민 회원 상세 페이지처럼 **한 명만 필요**할 때. 페이지네이션 풀 다운 없이
|
|
468
|
+
* 한 번의 호출로 합산 결과 반환.
|
|
469
|
+
*
|
|
470
|
+
* @example
|
|
471
|
+
* ```ts
|
|
472
|
+
* const v = await cb.analytics.getVisitorByMember('019d8...', memberId)
|
|
473
|
+
* console.log(`${v.visitor_count} 디바이스, 총 ${v.total_page_views} pv`)
|
|
474
|
+
* ```
|
|
475
|
+
*/
|
|
476
|
+
getVisitorByMember(storageWebId: string | undefined, memberId: string): Promise<VisitorByMemberResponse>;
|
|
477
|
+
/**
|
|
478
|
+
* 두 visitor 를 한 사람으로 통합하는 admin 작업 — JWT/cb_sk_ 인증 필요. (1.11+)
|
|
479
|
+
*
|
|
480
|
+
* 외부 인증 시스템에서 두 visitor 가 동일인임을 알았을 때 사용. source 의 자식 레코드
|
|
481
|
+
* (page_views, daily, custom_events, experiment_assignments, heatmap_events,
|
|
482
|
+
* session_recordings) 를 target 으로 옮기고 source visitor 는 삭제됨.
|
|
483
|
+
*
|
|
484
|
+
* @param request 둘 중 하나 필수: `target_visitor_uid` 또는 `target_member_id`.
|
|
485
|
+
* @example
|
|
486
|
+
* ```ts
|
|
487
|
+
* await cb.analytics.mergeVisitors('019d8...', {
|
|
488
|
+
* source_visitor_uid: 'old-uid',
|
|
489
|
+
* target_member_id: '01a...',
|
|
490
|
+
* })
|
|
491
|
+
* ```
|
|
492
|
+
*/
|
|
493
|
+
mergeVisitors(storageWebId: string | undefined, request: MergeVisitorsRequest): Promise<MergeVisitorsResponse>;
|
|
366
494
|
/**
|
|
367
495
|
* 조회 메서드 공통 가드 — Public Key 인증 SDK 인스턴스에서는 명확한 에러를 던진다.
|
|
368
496
|
* 백엔드 라우트는 cb_pk_ 를 거부하므로 호출 자체를 막는 것이 디버깅에 유리.
|
package/dist/index.js
CHANGED
|
@@ -8384,15 +8384,31 @@ var AnalyticsAPI = class {
|
|
|
8384
8384
|
this.enqueue(event);
|
|
8385
8385
|
}
|
|
8386
8386
|
/**
|
|
8387
|
-
* 사용자 식별 (로그인
|
|
8388
|
-
*
|
|
8387
|
+
* 사용자 식별 (로그인 직후 호출).
|
|
8388
|
+
*
|
|
8389
|
+
* 이후 모든 방문 배치에 `app_member_id` 가 첨부되어 새 활동은 회원으로 기록됩니다.
|
|
8390
|
+
* 추가로 **현재 visitor_uid 의 기존 익명 활동을 즉시 회원에게 backfill** 하기 위해
|
|
8391
|
+
* 백엔드 `link-member` 엔드포인트를 한 번 호출합니다 (1.11.0+). 호출 실패는
|
|
8392
|
+
* silent — 다음 batch 가 닿을 때 백엔드 자동 매핑이 동일하게 처리하므로 자가 복구.
|
|
8393
|
+
*
|
|
8394
|
+
* 산업 표준(GA4 User-ID, Mixpanel/PostHog `identify`) 과 동작 정합.
|
|
8395
|
+
*
|
|
8396
|
+
* @example
|
|
8397
|
+
* ```ts
|
|
8398
|
+
* // 로그인 성공 직후
|
|
8399
|
+
* await cb.auth.signIn({ email, password })
|
|
8400
|
+
* cb.analytics.identify(member.id)
|
|
8401
|
+
* ```
|
|
8389
8402
|
*/
|
|
8390
8403
|
identify(memberId) {
|
|
8391
8404
|
this.setMemberId(memberId);
|
|
8405
|
+
this.linkMemberSilent(memberId);
|
|
8392
8406
|
}
|
|
8393
8407
|
/**
|
|
8394
|
-
* 방문자 트래커에 현재 회원 ID 설정 (로그인/게스트 가입 시 호출)
|
|
8395
|
-
*
|
|
8408
|
+
* 방문자 트래커에 현재 회원 ID 설정 (로그인/게스트 가입 시 호출).
|
|
8409
|
+
*
|
|
8410
|
+
* `identify()` 와 달리 즉시 backfill 호출은 하지 않습니다 — 단순히 이후 batch 의
|
|
8411
|
+
* `app_member_id` 값만 갱신. null 을 넘기면 익명 상태로 복귀 (로그아웃).
|
|
8396
8412
|
*/
|
|
8397
8413
|
setMemberId(memberId) {
|
|
8398
8414
|
this.memberId = memberId || null;
|
|
@@ -8409,6 +8425,25 @@ var AnalyticsAPI = class {
|
|
|
8409
8425
|
}
|
|
8410
8426
|
this.log("Member id set", { memberId });
|
|
8411
8427
|
}
|
|
8428
|
+
/**
|
|
8429
|
+
* 백엔드 link-member 엔드포인트 한 번 호출 — 즉시 backfill 트리거.
|
|
8430
|
+
*
|
|
8431
|
+
* - 첫 페이지뷰가 아직 백엔드에 닿기 전이면 visitor 가 없어 404. 무시 — 다음 batch 가
|
|
8432
|
+
* 가면 백엔드 BatchRecordVisit 가 자동 LinkMember 를 호출.
|
|
8433
|
+
* - storage_web_id 가 init 안 됐거나 모든 종류의 네트워크 오류 — silent fail.
|
|
8434
|
+
*/
|
|
8435
|
+
linkMemberSilent(memberId) {
|
|
8436
|
+
if (!this.storageWebId) return;
|
|
8437
|
+
const prefix = this.http.hasPublicKey() ? "/v1/public" : "/v1";
|
|
8438
|
+
this.http.post(
|
|
8439
|
+
`${prefix}/storages/web/${this.storageWebId}/visitors/link-member`,
|
|
8440
|
+
{
|
|
8441
|
+
visitor_uid: this.session.visitorUid,
|
|
8442
|
+
app_member_id: memberId
|
|
8443
|
+
}
|
|
8444
|
+
).catch(() => {
|
|
8445
|
+
});
|
|
8446
|
+
}
|
|
8412
8447
|
/** 현재 설정된 회원 ID 조회 (미설정 시 null) */
|
|
8413
8448
|
getMemberId() {
|
|
8414
8449
|
return this.memberId;
|
|
@@ -8540,6 +8575,66 @@ var AnalyticsAPI = class {
|
|
|
8540
8575
|
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
8541
8576
|
return this.http.get(`/v1/storages/web/${id}/visitors${qs}`);
|
|
8542
8577
|
}
|
|
8578
|
+
/**
|
|
8579
|
+
* 멤버별 합산 방문자 그룹 조회 — JWT/cb_sk_ 인증 필요. (1.11+)
|
|
8580
|
+
*
|
|
8581
|
+
* `getVisitors` 와 달리 visitor row 들을 `app_member_id` 로 합쳐 단일 row 로 반환.
|
|
8582
|
+
* 같은 사람이 PC + 모바일 + 태블릿으로 접속한 경우 visitor 3개 → 그룹 1개.
|
|
8583
|
+
* 익명 visitor 는 단일 row 로 그대로 포함되어 페이지네이션이 일관됨.
|
|
8584
|
+
*
|
|
8585
|
+
* @example
|
|
8586
|
+
* ```ts
|
|
8587
|
+
* const { groups } = await cb.analytics.getVisitorGroups('019d8...', { limit: 50 })
|
|
8588
|
+
* for (const g of groups) {
|
|
8589
|
+
* if (g.app_member_id) console.log(`${g.app_member_id}: ${g.visitor_count} 디바이스`)
|
|
8590
|
+
* }
|
|
8591
|
+
* ```
|
|
8592
|
+
*/
|
|
8593
|
+
async getVisitorGroups(storageWebId, options) {
|
|
8594
|
+
const id = this.requireServerSideStorageId(storageWebId, "getVisitorGroups");
|
|
8595
|
+
const params = new URLSearchParams();
|
|
8596
|
+
if (options?.limit !== void 0) params.set("limit", String(options.limit));
|
|
8597
|
+
if (options?.offset !== void 0) params.set("offset", String(options.offset));
|
|
8598
|
+
if (options?.sort_by) params.set("sort_by", options.sort_by);
|
|
8599
|
+
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
8600
|
+
return this.http.get(`/v1/storages/web/${id}/visitor-groups${qs}`);
|
|
8601
|
+
}
|
|
8602
|
+
/**
|
|
8603
|
+
* 단건 멤버 합산 방문자 조회 — JWT/cb_sk_ 인증 필요. (1.11+)
|
|
8604
|
+
*
|
|
8605
|
+
* 어드민 회원 상세 페이지처럼 **한 명만 필요**할 때. 페이지네이션 풀 다운 없이
|
|
8606
|
+
* 한 번의 호출로 합산 결과 반환.
|
|
8607
|
+
*
|
|
8608
|
+
* @example
|
|
8609
|
+
* ```ts
|
|
8610
|
+
* const v = await cb.analytics.getVisitorByMember('019d8...', memberId)
|
|
8611
|
+
* console.log(`${v.visitor_count} 디바이스, 총 ${v.total_page_views} pv`)
|
|
8612
|
+
* ```
|
|
8613
|
+
*/
|
|
8614
|
+
async getVisitorByMember(storageWebId, memberId) {
|
|
8615
|
+
const id = this.requireServerSideStorageId(storageWebId, "getVisitorByMember");
|
|
8616
|
+
return this.http.get(`/v1/storages/web/${id}/members/${memberId}/visitor`);
|
|
8617
|
+
}
|
|
8618
|
+
/**
|
|
8619
|
+
* 두 visitor 를 한 사람으로 통합하는 admin 작업 — JWT/cb_sk_ 인증 필요. (1.11+)
|
|
8620
|
+
*
|
|
8621
|
+
* 외부 인증 시스템에서 두 visitor 가 동일인임을 알았을 때 사용. source 의 자식 레코드
|
|
8622
|
+
* (page_views, daily, custom_events, experiment_assignments, heatmap_events,
|
|
8623
|
+
* session_recordings) 를 target 으로 옮기고 source visitor 는 삭제됨.
|
|
8624
|
+
*
|
|
8625
|
+
* @param request 둘 중 하나 필수: `target_visitor_uid` 또는 `target_member_id`.
|
|
8626
|
+
* @example
|
|
8627
|
+
* ```ts
|
|
8628
|
+
* await cb.analytics.mergeVisitors('019d8...', {
|
|
8629
|
+
* source_visitor_uid: 'old-uid',
|
|
8630
|
+
* target_member_id: '01a...',
|
|
8631
|
+
* })
|
|
8632
|
+
* ```
|
|
8633
|
+
*/
|
|
8634
|
+
async mergeVisitors(storageWebId, request) {
|
|
8635
|
+
const id = this.requireServerSideStorageId(storageWebId, "mergeVisitors");
|
|
8636
|
+
return this.http.post(`/v1/storages/web/${id}/visitors/merge`, request);
|
|
8637
|
+
}
|
|
8543
8638
|
/**
|
|
8544
8639
|
* 조회 메서드 공통 가드 — Public Key 인증 SDK 인스턴스에서는 명확한 에러를 던진다.
|
|
8545
8640
|
* 백엔드 라우트는 cb_pk_ 를 거부하므로 호출 자체를 막는 것이 디버깅에 유리.
|
package/dist/index.mjs
CHANGED
|
@@ -8346,15 +8346,31 @@ var AnalyticsAPI = class {
|
|
|
8346
8346
|
this.enqueue(event);
|
|
8347
8347
|
}
|
|
8348
8348
|
/**
|
|
8349
|
-
* 사용자 식별 (로그인
|
|
8350
|
-
*
|
|
8349
|
+
* 사용자 식별 (로그인 직후 호출).
|
|
8350
|
+
*
|
|
8351
|
+
* 이후 모든 방문 배치에 `app_member_id` 가 첨부되어 새 활동은 회원으로 기록됩니다.
|
|
8352
|
+
* 추가로 **현재 visitor_uid 의 기존 익명 활동을 즉시 회원에게 backfill** 하기 위해
|
|
8353
|
+
* 백엔드 `link-member` 엔드포인트를 한 번 호출합니다 (1.11.0+). 호출 실패는
|
|
8354
|
+
* silent — 다음 batch 가 닿을 때 백엔드 자동 매핑이 동일하게 처리하므로 자가 복구.
|
|
8355
|
+
*
|
|
8356
|
+
* 산업 표준(GA4 User-ID, Mixpanel/PostHog `identify`) 과 동작 정합.
|
|
8357
|
+
*
|
|
8358
|
+
* @example
|
|
8359
|
+
* ```ts
|
|
8360
|
+
* // 로그인 성공 직후
|
|
8361
|
+
* await cb.auth.signIn({ email, password })
|
|
8362
|
+
* cb.analytics.identify(member.id)
|
|
8363
|
+
* ```
|
|
8351
8364
|
*/
|
|
8352
8365
|
identify(memberId) {
|
|
8353
8366
|
this.setMemberId(memberId);
|
|
8367
|
+
this.linkMemberSilent(memberId);
|
|
8354
8368
|
}
|
|
8355
8369
|
/**
|
|
8356
|
-
* 방문자 트래커에 현재 회원 ID 설정 (로그인/게스트 가입 시 호출)
|
|
8357
|
-
*
|
|
8370
|
+
* 방문자 트래커에 현재 회원 ID 설정 (로그인/게스트 가입 시 호출).
|
|
8371
|
+
*
|
|
8372
|
+
* `identify()` 와 달리 즉시 backfill 호출은 하지 않습니다 — 단순히 이후 batch 의
|
|
8373
|
+
* `app_member_id` 값만 갱신. null 을 넘기면 익명 상태로 복귀 (로그아웃).
|
|
8358
8374
|
*/
|
|
8359
8375
|
setMemberId(memberId) {
|
|
8360
8376
|
this.memberId = memberId || null;
|
|
@@ -8371,6 +8387,25 @@ var AnalyticsAPI = class {
|
|
|
8371
8387
|
}
|
|
8372
8388
|
this.log("Member id set", { memberId });
|
|
8373
8389
|
}
|
|
8390
|
+
/**
|
|
8391
|
+
* 백엔드 link-member 엔드포인트 한 번 호출 — 즉시 backfill 트리거.
|
|
8392
|
+
*
|
|
8393
|
+
* - 첫 페이지뷰가 아직 백엔드에 닿기 전이면 visitor 가 없어 404. 무시 — 다음 batch 가
|
|
8394
|
+
* 가면 백엔드 BatchRecordVisit 가 자동 LinkMember 를 호출.
|
|
8395
|
+
* - storage_web_id 가 init 안 됐거나 모든 종류의 네트워크 오류 — silent fail.
|
|
8396
|
+
*/
|
|
8397
|
+
linkMemberSilent(memberId) {
|
|
8398
|
+
if (!this.storageWebId) return;
|
|
8399
|
+
const prefix = this.http.hasPublicKey() ? "/v1/public" : "/v1";
|
|
8400
|
+
this.http.post(
|
|
8401
|
+
`${prefix}/storages/web/${this.storageWebId}/visitors/link-member`,
|
|
8402
|
+
{
|
|
8403
|
+
visitor_uid: this.session.visitorUid,
|
|
8404
|
+
app_member_id: memberId
|
|
8405
|
+
}
|
|
8406
|
+
).catch(() => {
|
|
8407
|
+
});
|
|
8408
|
+
}
|
|
8374
8409
|
/** 현재 설정된 회원 ID 조회 (미설정 시 null) */
|
|
8375
8410
|
getMemberId() {
|
|
8376
8411
|
return this.memberId;
|
|
@@ -8502,6 +8537,66 @@ var AnalyticsAPI = class {
|
|
|
8502
8537
|
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
8503
8538
|
return this.http.get(`/v1/storages/web/${id}/visitors${qs}`);
|
|
8504
8539
|
}
|
|
8540
|
+
/**
|
|
8541
|
+
* 멤버별 합산 방문자 그룹 조회 — JWT/cb_sk_ 인증 필요. (1.11+)
|
|
8542
|
+
*
|
|
8543
|
+
* `getVisitors` 와 달리 visitor row 들을 `app_member_id` 로 합쳐 단일 row 로 반환.
|
|
8544
|
+
* 같은 사람이 PC + 모바일 + 태블릿으로 접속한 경우 visitor 3개 → 그룹 1개.
|
|
8545
|
+
* 익명 visitor 는 단일 row 로 그대로 포함되어 페이지네이션이 일관됨.
|
|
8546
|
+
*
|
|
8547
|
+
* @example
|
|
8548
|
+
* ```ts
|
|
8549
|
+
* const { groups } = await cb.analytics.getVisitorGroups('019d8...', { limit: 50 })
|
|
8550
|
+
* for (const g of groups) {
|
|
8551
|
+
* if (g.app_member_id) console.log(`${g.app_member_id}: ${g.visitor_count} 디바이스`)
|
|
8552
|
+
* }
|
|
8553
|
+
* ```
|
|
8554
|
+
*/
|
|
8555
|
+
async getVisitorGroups(storageWebId, options) {
|
|
8556
|
+
const id = this.requireServerSideStorageId(storageWebId, "getVisitorGroups");
|
|
8557
|
+
const params = new URLSearchParams();
|
|
8558
|
+
if (options?.limit !== void 0) params.set("limit", String(options.limit));
|
|
8559
|
+
if (options?.offset !== void 0) params.set("offset", String(options.offset));
|
|
8560
|
+
if (options?.sort_by) params.set("sort_by", options.sort_by);
|
|
8561
|
+
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
8562
|
+
return this.http.get(`/v1/storages/web/${id}/visitor-groups${qs}`);
|
|
8563
|
+
}
|
|
8564
|
+
/**
|
|
8565
|
+
* 단건 멤버 합산 방문자 조회 — JWT/cb_sk_ 인증 필요. (1.11+)
|
|
8566
|
+
*
|
|
8567
|
+
* 어드민 회원 상세 페이지처럼 **한 명만 필요**할 때. 페이지네이션 풀 다운 없이
|
|
8568
|
+
* 한 번의 호출로 합산 결과 반환.
|
|
8569
|
+
*
|
|
8570
|
+
* @example
|
|
8571
|
+
* ```ts
|
|
8572
|
+
* const v = await cb.analytics.getVisitorByMember('019d8...', memberId)
|
|
8573
|
+
* console.log(`${v.visitor_count} 디바이스, 총 ${v.total_page_views} pv`)
|
|
8574
|
+
* ```
|
|
8575
|
+
*/
|
|
8576
|
+
async getVisitorByMember(storageWebId, memberId) {
|
|
8577
|
+
const id = this.requireServerSideStorageId(storageWebId, "getVisitorByMember");
|
|
8578
|
+
return this.http.get(`/v1/storages/web/${id}/members/${memberId}/visitor`);
|
|
8579
|
+
}
|
|
8580
|
+
/**
|
|
8581
|
+
* 두 visitor 를 한 사람으로 통합하는 admin 작업 — JWT/cb_sk_ 인증 필요. (1.11+)
|
|
8582
|
+
*
|
|
8583
|
+
* 외부 인증 시스템에서 두 visitor 가 동일인임을 알았을 때 사용. source 의 자식 레코드
|
|
8584
|
+
* (page_views, daily, custom_events, experiment_assignments, heatmap_events,
|
|
8585
|
+
* session_recordings) 를 target 으로 옮기고 source visitor 는 삭제됨.
|
|
8586
|
+
*
|
|
8587
|
+
* @param request 둘 중 하나 필수: `target_visitor_uid` 또는 `target_member_id`.
|
|
8588
|
+
* @example
|
|
8589
|
+
* ```ts
|
|
8590
|
+
* await cb.analytics.mergeVisitors('019d8...', {
|
|
8591
|
+
* source_visitor_uid: 'old-uid',
|
|
8592
|
+
* target_member_id: '01a...',
|
|
8593
|
+
* })
|
|
8594
|
+
* ```
|
|
8595
|
+
*/
|
|
8596
|
+
async mergeVisitors(storageWebId, request) {
|
|
8597
|
+
const id = this.requireServerSideStorageId(storageWebId, "mergeVisitors");
|
|
8598
|
+
return this.http.post(`/v1/storages/web/${id}/visitors/merge`, request);
|
|
8599
|
+
}
|
|
8505
8600
|
/**
|
|
8506
8601
|
* 조회 메서드 공통 가드 — Public Key 인증 SDK 인스턴스에서는 명확한 에러를 던진다.
|
|
8507
8602
|
* 백엔드 라우트는 cb_pk_ 를 거부하므로 호출 자체를 막는 것이 디버깅에 유리.
|