You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-`account.days[]`: `{date, revenue, ctr, ecpm, fillRate, winFillRate}`. AdFit 콘솔에 값이 없거나 누락된 날짜는 `null`이며 0으로 대체하지 않는다.
8
10
-`account.fetchedAt`: `CONNECTED`일 때 이번 관리자 조회에서 AdFit 응답을 성공적으로 파싱한 시각이다. 원천 데이터의 최종 집계 시각이나 배치 동기화 시각이 아니다.
9
11
-`account.revenue`: 조회 기간 중 실제 내려온 일별 수익 합계. 수익 데이터가 전부 `null`이면 `null`.
10
12
-`account.cost`, `account.roi`: AdFit 계정 자동 보고서가 광고 비용을 제공하지 않으므로 항상 `null`.
11
-
- 자동 보고서는 `ADFIT_SESSION_COOKIE` 또는 `picke.adfit.session-cookie`가 있을 때 AdFit 콘솔 계정 종합 일별 API를 조회한다.
13
+
- 자동 보고서는 세션 쿠키가 있을 때 AdFit 콘솔 계정 종합 일별 API를 조회한다. 쿠키는 매 조회 시점에 다시 읽는다.
14
+
- 쿠키 우선순위: 관리자 화면 입력값(`adfit_session_cookies` 테이블, `source=ADMIN_CONSOLE`) > 환경변수 `ADFIT_SESSION_COOKIE`·`picke.adfit.session-cookie`(`source=ENVIRONMENT`). 둘 다 없으면 `source=NONE`.
15
+
- 세션이 만료되면 `RECONNECT_REQUIRED`가 된다. 재배포 없이 `PUT /session-cookie`로 새 쿠키를 넣어 복구한다.
12
16
- 세션 쿠키가 없으면 `NOT_CONFIGURED`, 로그인 만료·리다이렉트·HTML 로그인 응답이면 `RECONNECT_REQUIRED`, API 장애·스키마 불일치면 `UNAVAILABLE`.
- AdFit 계정 자동 보고서는 콘솔 내부 API(`accountTotal/periodicIndicators`)를 사용한다. 공개 파트너 REST API가 아니므로 세션 만료 시 재연결이 필요하다.
23
27
- 공식 참고: https://adfit.kakao.com/ , https://adfit.github.io/
24
-
- DB: `docs/db/20260910_create_adfit_daily_reports.sql`. 현재 프로젝트는 Hibernate ddl-auto=update를 사용한다.
28
+
- 카카오 REST API 키(`Authorization: KakaoAK ...`)로는 조회할 수 없다. 애드핏 매체주 수익용 공개 REST API가 없다. 카카오 디벨로퍼스 REST API 레퍼런스에 해당 엔드포인트가 없고, AdX Report API는 RTB 연동 DSP 전용, 카카오모먼트 리포트 API는 광고주 집행 측이다.
29
+
- DB: `docs/db/20260910_create_adfit_daily_reports.sql`, `docs/db/20260913_create_adfit_session_cookies.sql`. 현재 프로젝트는 Hibernate ddl-auto=update를 사용한다.
-`GET /api/v1/admin/analytics/mixpanel?from=YYYY-MM-DD&to=YYYY-MM-DD&events=A,B`: ADMIN 전용. 최대 366일.
4
+
-`GET /api/v1/admin/analytics/sentry?from=YYYY-MM-DD&to=YYYY-MM-DD`: ADMIN 전용. 최대 366일.
5
+
- 두 응답의 `status`: `NOT_CONFIGURED`, `CONNECTED`, `UNAVAILABLE`. 조회 실패를 0으로 대체하지 않는다.
6
+
-`NOT_CONFIGURED`는 오류가 아니다. 토큰을 넣기 전 상태이므로 화면은 지면을 비우고 안내만 띄운다.
7
+
8
+
## Mixpanel
9
+
10
+
집계 API가 아니라 **원본 이벤트를 내려받아 서버가 직접 센다.**
11
+
12
+
-`GET https://data.mixpanel.com/api/2.0/export?from_date&to_date`. 응답은 한 줄에 이벤트 하나인 NDJSON.
13
+
- 인증은 프로젝트 API 비밀을 Basic 사용자명 자리에 넣고 비밀번호를 비우는 레거시 방식이다. 이 방식에 `project_id`를 넣으면 400이 된다. 비밀이 이미 프로젝트를 특정한다.
14
+
-`events[].days[]`: `{date, count}`. 최신 날짜부터. 원본을 전부 받아 세므로 이벤트가 없던 날짜는 미집계가 아니라 **0**이다.
15
+
-`events`를 비우면 기간에 나타난 이벤트 전부를 발생 수 내림차순으로 준다. 이벤트 이름을 미리 설정해 둘 필요가 없다.
16
+
- 원본을 전부 받으므로 기간은 **31일까지**다(`MixpanelClient.MAX_DAYS`). 4일치가 약 2MB다.
17
+
-`properties.time`은 프로젝트 타임존 기준 epoch 초이고 `from_date`·`to_date` 경계도 같은 타임존을 따른다. 둘을 같은 타임존으로 묶어야 Mixpanel 화면 숫자와 맞는다. `picke.analytics.mixpanel.project-zone`(기본 `UTC`)로 맞춘다. 이 프로젝트는 UTC로 실측 확인했다.
18
+
- 경계 하루가 타임존 차이로 걸쳐 들어올 수 있어 요청 기간 밖 이벤트는 버린다.
19
+
20
+
### 왜 집계 API를 안 쓰는가
21
+
22
+
-**현재 Picke의 Mixpanel 플랜은 Query API를 허용하지 않는다.** 2026-09-14 실측: `/api/query/segmentation`·`/api/query/insights` 모두 `HTTP 402 Your plan does not allow API calls`. 인증은 통과하므로 자격 문제가 아니다.
23
+
- 같은 플랜에서 Raw Export는 **200으로 열려 있다.** 그래서 이쪽으로 붙였다. Mixpanel MCP나 다른 클라이언트를 붙여도 Query API를 호출하는 한 같은 402를 받는다.
24
+
- 서비스 계정 방식(`username:secret`)은 이 프로젝트에서 401이다. 프로젝트 토큰(`project_token`)은 이벤트 수집용이라 조회 인증에 쓰이지 않는다(401).
0 commit comments