Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Walkthrough세 개의 페이지에 걸쳐 분석 결과 추적을 위한 Google Analytics 이벤트 통합이 추가되었습니다. 중점 계산, 장소 상호작용, 후보 조회를 추적하는 새로운 GA 이벤트와 함께 localStorage 및 sessionStorage 플래그를 사용하여 사용자 역할과 탐색 상태를 관리합니다. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/meeting/`[id]/page.tsx:
- Around line 173-185: The calculation_type logic is wrong because id is always
present on /meeting/[id], causing 'first' never to be sent and browser_id can be
null; update the code around sendGAEvent so calculationType is determined by a
persistent flag (e.g., check localStorage.getItem(`midpoint_calculated_${id}`)
or similar) rather than presence of id, set calculationType to 'first' if that
flag is absent and 'recalculated' if present, then after sending mark that flag
in localStorage (localStorage.setItem(`midpoint_calculated_${id}`, 'true'));
also ensure browser_id is not sent as null by reading
localStorage.getItem('browser_id') and if missing either generate/store a new id
or omit the browser_id field when calling sendGAEvent so it never transmits
null.
In `@app/result/`[id]/page.tsx:
- Around line 171-181: The useEffect currently treats
sessionStorage.getItem(`from_recommend_${id}`) as a boolean flag ('1') which can
cause the wrong candidate to be picked; update the effect to read and parse the
stored value as a selectedResultId (supporting formats set by the redirect
logic: e.g. a plain numeric id or a prefix like "1:<id>"), then remove the key
and pick the candidate by that parsed id (falling back to the existing
selectedResultId or locationResults[0] if parsing fails) before computing
candidateId and calling trackMidpointCandidateViewed; reference useEffect,
sessionStorage.getItem(`from_recommend_${id}`), selectedResultId,
locationResults, and trackMidpointCandidateViewed to locate where to change.
| if (typeof window !== 'undefined') { | ||
| const calculationType = id ? 'recalculated' : 'first'; | ||
| const isHost = localStorage.getItem(`is_host_${id}`) === 'true'; | ||
| const userRole = isHost ? 'host' : 'participant'; | ||
| const browserId = localStorage.getItem('browser_id'); | ||
|
|
||
| sendGAEvent('event', 'midpoint_calculated', { | ||
| meeting_url_id: id, | ||
| browser_id: browserId, | ||
| role: userRole, | ||
| calculation_type: calculationType, | ||
| }); | ||
| } |
There was a problem hiding this comment.
calculation_type가 사실상 항상 recalculated로 전송됩니다.
Line 174는 id 존재 여부로 분기하고 있는데, /meeting/[id] 경로에서는 id가 항상 존재해 first가 전송되지 않습니다. 그리고 Line 177은 browser_id가 없을 때 null이 전송될 수 있습니다.
수정 제안
- if (typeof window !== 'undefined') {
- const calculationType = id ? 'recalculated' : 'first';
+ if (typeof window !== 'undefined' && id) {
+ const calcStateKey = `has_midpoint_calculated_${id}`;
+ const calculationType = sessionStorage.getItem(calcStateKey) ? 'recalculated' : 'first';
const isHost = localStorage.getItem(`is_host_${id}`) === 'true';
const userRole = isHost ? 'host' : 'participant';
- const browserId = localStorage.getItem('browser_id');
+ let browserId = localStorage.getItem('browser_id');
+ if (!browserId) {
+ browserId = `bid_${Math.random().toString(36).substring(2, 15)}${Date.now().toString(36)}`;
+ localStorage.setItem('browser_id', browserId);
+ }
sendGAEvent('event', 'midpoint_calculated', {
meeting_url_id: id,
browser_id: browserId,
role: userRole,
calculation_type: calculationType,
});
+ sessionStorage.setItem(calcStateKey, '1');
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/meeting/`[id]/page.tsx around lines 173 - 185, The calculation_type logic
is wrong because id is always present on /meeting/[id], causing 'first' never to
be sent and browser_id can be null; update the code around sendGAEvent so
calculationType is determined by a persistent flag (e.g., check
localStorage.getItem(`midpoint_calculated_${id}`) or similar) rather than
presence of id, set calculationType to 'first' if that flag is absent and
'recalculated' if present, then after sending mark that flag in localStorage
(localStorage.setItem(`midpoint_calculated_${id}`, 'true')); also ensure
browser_id is not sent as null by reading localStorage.getItem('browser_id') and
if missing either generate/store a new id or omit the browser_id field when
calling sendGAEvent so it never transmits null.
| // 장소 리스트에서 결과보기 페이지로 돌아왔을 때 midpoint_candidate_viewed 전송 | ||
| useEffect(() => { | ||
| if (typeof window === 'undefined' || !id || locationResults.length === 0) return; | ||
| const fromRecommend = sessionStorage.getItem(`from_recommend_${id}`); | ||
| if (fromRecommend !== '1') return; | ||
|
|
||
| sessionStorage.removeItem(`from_recommend_${id}`); | ||
| const selected = locationResults.find((r) => r.id === selectedResultId) ?? locationResults[0]; | ||
| const candidateId = `mid_${selected.endStation.replace(/\s+/g, '_')}`; | ||
| trackMidpointCandidateViewed(selected.id, candidateId); | ||
| }, [id, locationResults, selectedResultId, trackMidpointCandidateViewed]); |
There was a problem hiding this comment.
추천 페이지 복귀 시 잘못된 후보가 집계될 수 있습니다.
Line 315에서 '1'만 저장하면, Line 178에서 selectedResultId 기본값(1)을 기준으로 후보를 선택하게 되어 실제로 추천 페이지로 이동했던 후보와 다른 candidate_id가 전송될 수 있습니다.
수정 제안
- const fromRecommend = sessionStorage.getItem(`from_recommend_${id}`);
- if (fromRecommend !== '1') return;
+ const fromRecommendRank = sessionStorage.getItem(`from_recommend_${id}`);
+ if (!fromRecommendRank) return;
- sessionStorage.removeItem(`from_recommend_${id}`);
- const selected = locationResults.find((r) => r.id === selectedResultId) ?? locationResults[0];
+ const parsedRank = Number(fromRecommendRank);
+ sessionStorage.removeItem(`from_recommend_${id}`);
+ const selected =
+ locationResults.find((r) => r.id === parsedRank) ??
+ locationResults.find((r) => r.id === selectedResultId) ??
+ locationResults[0];
const candidateId = `mid_${selected.endStation.replace(/\s+/g, '_')}`;
trackMidpointCandidateViewed(selected.id, candidateId);- if (typeof window !== 'undefined') {
- sessionStorage.setItem(`from_recommend_${id}`, '1');
- }
+ if (typeof window !== 'undefined') {
+ sessionStorage.setItem(`from_recommend_${id}`, String(result.id));
+ }Also applies to: 314-316
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/result/`[id]/page.tsx around lines 171 - 181, The useEffect currently
treats sessionStorage.getItem(`from_recommend_${id}`) as a boolean flag ('1')
which can cause the wrong candidate to be picked; update the effect to read and
parse the stored value as a selectedResultId (supporting formats set by the
redirect logic: e.g. a plain numeric id or a prefix like "1:<id>"), then remove
the key and pick the candidate by that parsed id (falling back to the existing
selectedResultId or locationResults[0] if parsing fails) before computing
candidateId and calling trackMidpointCandidateViewed; reference useEffect,
sessionStorage.getItem(`from_recommend_${id}`), selectedResultId,
locationResults, and trackMidpointCandidateViewed to locate where to change.
🚀 GA4 이벤트 추가
📝 변경사항
✅ 체크리스트
📸 스크린샷
💬 리뷰어 전달사항
Summary by CodeRabbit
릴리스 노트