Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
564ff45
setting: @pinback/analytics workspace ์˜์กด์„ฑ ์ถ”๊ฐ€
constantly-dev Mar 26, 2026
5c964f1
setting: AnalyticsProvider types ์ •์˜
constantly-dev Mar 26, 2026
47c7f0b
setting: turbo.json globalEnv ์„ค์ • ์ถ”๊ฐ€
constantly-dev Mar 26, 2026
60c455f
feat: noopProvider ๊ตฌํ˜„
constantly-dev Mar 26, 2026
31cc203
feat: consoleProvider ๊ตฌํ˜„
constantly-dev Mar 26, 2026
6094c83
setting: amplitudeProvider ๊ตฌํ˜„
constantly-dev Mar 26, 2026
6bec51a
setting: amplitude default set analytics ๊ตฌํ˜„
constantly-dev Mar 26, 2026
6a7ae48
feat: initAnalytics, trackEvent ์ถ”๊ฐ€
constantly-dev Mar 26, 2026
ea6ed3d
feat: UserProperties job_role ์ œ์™ธ ํ•„๋“œ ์‚ญ์ œ
constantly-dev Mar 27, 2026
faeea57
setting: @amplitude/ampli ์˜์กด ์ถ”๊ฐ€
constantly-dev Mar 27, 2026
4229876
setting: ampli interface index ํŒŒ์ผ ์ถ”๊ฐ€ (ampli pull)
constantly-dev Mar 27, 2026
fae9019
feat: login, logout userProperties ์„ค์ • ๋กœ์ง ์ถ”๊ฐ€
constantly-dev Mar 27, 2026
e3b5c9a
refactor: consoleProvider init apiKey ์ข…์† ์ œ๊ฑฐ
constantly-dev Mar 27, 2026
d58c4cc
chore: apps/landing @pinback/analytics ์˜์กด ์ œ๊ฑฐ
constantly-dev Mar 27, 2026
68b05df
feat: refresh ๋กœ๊ทธ์ธ ๋Œ€๋น„ ์ž„์‹œ jobRole ์ƒํƒœ ์ถ”๊ฐ€
constantly-dev Mar 27, 2026
627c0e6
setting: client, extension initAnalytics ์ถ”๊ฐ€
constantly-dev Mar 27, 2026
203646c
fix: update pnpm-lock
constantly-dev Mar 27, 2026
ef69f3b
feat: amplitude user properties API ์—ฐ๋™
constantly-dev Apr 2, 2026
c7f291c
refactor: amplitude identify ๋กœ์ง์„ ์ „์šฉ API ๊ธฐ๋ฐ˜์œผ๋กœ ๊ต์ฒด
constantly-dev Apr 2, 2026
94adbe0
fix: consoleProvider identify์— userProperties ์ถœ๋ ฅ ์ถ”๊ฐ€
constantly-dev Apr 2, 2026
51d91d8
fix: session replay ์„ค์ • ์ œ๊ฑฐ
constantly-dev Apr 2, 2026
1dc7b9c
fix: ๋กœ๊ทธ์ธ ํ›„ amplitude identify ๋ˆ„๋ฝ ๋ฌธ์ œ ์ˆ˜์ •
constantly-dev Apr 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
},
"dependencies": {
"@pinback/contracts": "workspace:*",
"@pinback/analytics": "workspace:*",
"@tanstack/react-query": "^5.85.3",
"axios": "^1.11.0",
"class-variance-authority": "^0.7.1",
Expand Down
20 changes: 15 additions & 5 deletions apps/client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { analytics } from '@pinback/analytics';
import { router } from '@routes/router';
import { useGetAmplitudeUserProperties } from '@shared/apis/queries';
import { useEffect } from 'react';
import { RouterProvider } from 'react-router-dom';
import './App.css';

function App() {
return (
<>
<RouterProvider router={router} />
</>
);
const { data: userProperties } = useGetAmplitudeUserProperties();

useEffect(() => {
if (!userProperties) return;
analytics.identify(
String(userProperties.userId),
userProperties.jobRole ? { job_role: userProperties.jobRole } : undefined
);
}, [userProperties]);

return <RouterProvider router={router} />;
}

export default App;
2 changes: 1 addition & 1 deletion apps/client/src/layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Outlet, useLocation } from 'react-router-dom';
const Layout = () => {
const location = useLocation();
const queryClient = useQueryClient();
const isLoggedIn = authStorage.hasAccessToken();

const isPolicyPage =
location.pathname === ROUTES_CONFIG.privacyPolicy.path ||
Expand All @@ -20,7 +21,6 @@ const Layout = () => {
location.pathname.startsWith(ROUTES_CONFIG.onboardingCallback.path);

const isSidebarHidden = isAuthPage || isPolicyPage;
const isLoggedIn = authStorage.hasAccessToken();

const { data: hasJobData, isLoading: isHasJobLoading } = useGetHasJob(
isLoggedIn && !isAuthPage
Expand Down
6 changes: 6 additions & 0 deletions apps/client/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { initAnalytics } from '@pinback/analytics';
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.tsx';

initAnalytics({
apiKey: import.meta.env.VITE_AMPLITUDE_API_KEY,
isDev: import.meta.env.DEV,
});
import { QueryClientProvider } from '@tanstack/react-query';
import getQueryClient from '@shared/apis/setting/query/getQueryClient.ts';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
Expand Down
3 changes: 3 additions & 0 deletions apps/client/src/pages/onBoarding/GoogleCallback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import apiRequest from '@shared/apis/setting/axiosInstance';
import LoadingChippi from '@shared/components/loadingChippi/LoadingChippi';
import { authStorage } from '@shared/utils/authStorage';
import { extensionBridge } from '@shared/utils/extensionBridge';
import { useQueryClient } from '@tanstack/react-query';
import { useEffect } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';

const GoogleCallback = () => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const queryClient = useQueryClient();

useEffect(() => {
const code = searchParams.get('code');
Expand Down Expand Up @@ -65,6 +67,7 @@ const GoogleCallback = () => {
res.data.data;

authStorage.setUserIdentity(email, userId);
queryClient.invalidateQueries({ queryKey: ['amplitudeUserProperties'] });

handleUserLogin(isUser, accessToken, refreshToken, hasJob);
} catch (error) {
Expand Down
7 changes: 7 additions & 0 deletions apps/client/src/shared/apis/axios.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import apiRequest from '@shared/apis/setting/axiosInstance';
import {
AmplitudeUserPropertiesResponse,
EditArticleRequest,
HasJobResponse,
JobsResponse,
Expand Down Expand Up @@ -117,3 +118,9 @@ export const getCategoryDetail = async (categoryId: number) => {
const { data } = await apiRequest.get(`/api/v3/categories/${categoryId}`);
return data.data;
};

export const getAmplitudeUserProperties =
async (): Promise<AmplitudeUserPropertiesResponse> => {
const { data } = await apiRequest.get('/api/v3/users/properties');
return data.data;
};
15 changes: 15 additions & 0 deletions apps/client/src/shared/apis/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
deleteCategory,
deleteRemindArticle,
getAcorns,
getAmplitudeUserProperties,
getArticleDetail,
getCategoryDetail,
getDashboardCategories,
Expand All @@ -20,6 +21,7 @@ import {
} from '@shared/apis/axios';
import {
AcornsResponse,
AmplitudeUserPropertiesResponse,
ArticleDetailResponse,
ArticleReadStatusResponse,
CategoryDetailResponse,
Expand Down Expand Up @@ -220,6 +222,16 @@ export const useSuspenseGetJobs = () => {
});
};

export const useGetAmplitudeUserProperties =
(): UseQueryResult<AmplitudeUserPropertiesResponse, AxiosError> => {
return useQuery({
queryKey: ['amplitudeUserProperties'],
queryFn: getAmplitudeUserProperties,
staleTime: Infinity,
retry: false,
});
};

export const usePatchUserJob = () => {
const queryClient = useQueryClient();

Expand All @@ -229,6 +241,9 @@ export const usePatchUserJob = () => {
queryClient.invalidateQueries({
queryKey: ['hasJob'],
});
queryClient.invalidateQueries({
queryKey: ['amplitudeUserProperties'],
});
},
});
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { analytics } from '@pinback/analytics';
import { Icon } from '@pinback/design-system/icons';
import { Button } from '@pinback/design-system/ui';
import { useQueryClient } from '@tanstack/react-query';
Expand Down Expand Up @@ -44,6 +45,7 @@ export default function ProfilePopup({
if (!open) return null;

const handleLogout = () => {
analytics.reset();
authStorage.clearSession();
queryClient.clear();
extensionBridge.logout();
Expand Down
5 changes: 5 additions & 0 deletions apps/client/src/shared/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,8 @@ export interface CategoryDetailResponse {
export interface HasJobResponse {
hasJob: boolean;
}

export interface AmplitudeUserPropertiesResponse {
userId: string;
jobRole: string | null;
}
1 change: 1 addition & 0 deletions apps/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"dependencies": {
"@pinback/contracts": "workspace:*",
"@tanstack/react-query": "^5.85.5",
"@pinback/analytics": "workspace:*",
"axios": "^1.11.0",
"react": "^19.1.1",
"react-dom": "^19.1.1"
Expand Down
6 changes: 6 additions & 0 deletions apps/extension/src/popup.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { initAnalytics } from '@pinback/analytics';
import { createRoot } from 'react-dom/client';
import App from './App';
import { QueryClientProvider } from '@tanstack/react-query';
import getQueryClient from './apis/query/getQueryClient';

initAnalytics({
apiKey: import.meta.env.VITE_AMPLITUDE_API_KEY,
isDev: import.meta.env.DEV,
});

const queryClient = getQueryClient();

const rootEl = document.getElementById('root');
Expand Down
14 changes: 14 additions & 0 deletions packages/analytics/ampli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"Zone": "us",
"OrgId": "416251",
"WorkspaceId": "b45d1b45-76f3-4ffc-a3df-3d2ba02b40a7",
"SourceId": "549df154-226b-4813-b3fa-2e6975515641",
"Branch": "main",
"Version": "1.0.0",
"VersionId": "a8d7f423-b996-4b7f-b836-cd64e2319f47",
"Runtime": "browser:typescript-ampli-v2",
"Platform": "Browser",
"Language": "TypeScript",
"SDK": "@amplitude/analytics-browser@^1.0",
"Path": "./src/ampli"
}
34 changes: 34 additions & 0 deletions packages/analytics/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { analytics } from './src/analytics';
import { amplitudeProvider } from './src/providers/amplitude';
import { consoleProvider } from './src/providers/console';

export type { AnalyticsProvider, UserProperties } from './src/types';
export { analytics };

interface InitAnalyticsOptions {
apiKey: string;
isDev: boolean;
}

export const initAnalytics = ({ apiKey, isDev }: InitAnalyticsOptions): void => {
if (isDev || !apiKey) {
analytics.setProvider(consoleProvider);
return;
}

try {
amplitudeProvider.init(apiKey);
analytics.setProvider(amplitudeProvider);
} catch (error) {
console.error('[Analytics] Failed to initialize Amplitude, falling back to console provider', error);
analytics.setProvider(consoleProvider);
}
};

// ํƒ€์ž…๋œ ์ด๋ฒคํŠธ(Ampli ๋“ฑ)๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์–ด๋ ค์šด ์˜ˆ์™ธ ์ผ€์ด์Šค์šฉ fallback
export const trackEvent = (
eventName: string,
properties?: Record<string, unknown>
): void => {
analytics.track(eventName, properties);
};
14 changes: 14 additions & 0 deletions packages/analytics/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "@pinback/analytics",
"version": "1.0.0",
"main": "index.ts",
"scripts": {
"ampli:pull": "ampli pull"
},
"dependencies": {
"@amplitude/unified": "^1.0.10"
},
"devDependencies": {
"@amplitude/ampli": "^1.36.2"
}
}
Loading
Loading