지난 [React.js] GA4(Google Analytics 4) - ①연동하기에서 웹사이트와 GA4를 연동해보았으니,
이번에는 웹사이트에서 GA4 API를 활용하여 데이터를 호출하는 방법을 구체적으로 알아볼 것이다!
여기서는 React.js의 프론트엔드 클라이언트에서 GA에 API를 호출하는 방법을 다룬다.
GA4 이전의 GA3까지는 Reporting API v4에서 API 사용법을 다루었으나,
GA4 업데이트되면서 해당 API에 대한 지원이 중단되고, Analytics Data API v1로 대체되었다.
Data API v1에서 사용 가능한 다양한 메서드들과 사용 방법들을 확인할 수 있다.
* 참고로 100% 한글화되지 않았기에, 종종 제목과 내용이 숫자로 되어있는 문서들이 있는데,
해당 문서는 언어를 'English'로 바꿔서 영어로 확인해야한다는 단점이 있다.
영어가 부담스럽고, 읽어봐도 어떻게 써야하는지 잘 모르겠다면 당신은 잘 오다!
지금부터 한 조각씩 천천히 사용법을 알아볼 것이다.
위의 Data API v1 공식문서에서 기본 보고서 메뉴를 클릭하면 제목도, 내용도 숫자로 나타난다.
아마 한국어로 번역하는 과정에서 오류가 발생했거나, 아직 미완성이거나... 그러한 이유인 듯하다.
번역은 되지 않았더라도, 공식문서를 확인해보면 눈여겨볼만한 내용은 다음과 같다.
runReport
메서드는 https://analyticsdata.googleapis.com/v1beta/properties/GA4_PROPERTY_ID:runReport
에HTTP POST
요청을 보내서 사용할 수 있고, GA4_PROPERTY_ID
값이 필요하다.dataRanges
, dimensions
, metrics
항목이 필요하다.여기까지 봤을 때, GA4_PROPERTY_ID
도 dataRanges
, dimensions
, metrics
도 뭔진 모르겠지만
React.js에서 axios
를 통해 위의 URL로 dataRanges
, dimensions
, metrics
데이터가 포함된
POST
요청을 보내면 되겠다는 생각을 할 수 있어야 한다!
문서에서 다른 부분은 차치하더라도 딱 이 부분만큼은 반드시 숙지하도록 한다.
GA4_PROPERTY_ID
dataRanges
dimensions
metrics
저렇게 POST
요청을 보내면 어떤 응답이 돌아올까?
물론 공식문서에서도 확인할 수 있지만, 공식문서에서는 응답의 예시를 보여줄 뿐
내가 GA를 연동한 웹사이트에 관한 응답을 보여주진 않는다.
즉, 예시를 보더라도 딱히 와닿지 않을 수 있다.
하지만 GA4 Query Explorer를 사용하면 내 웹사이트에 관한 요청과 응답을
확인할 수 있을 뿐만 아니라, 위의 dataRanges
, dimensions
, metrics
를 어떻게 작성해야 하는지도
직관적으로 보여주고 복사 기능까지 있기 때문에 POST
요청에서의 data
부분은 거의 떠먹여주는 수준이다!
GA4 Query Explorer에 접속하면 아래와 같이 화면이 나올텐데,
이전에 GA를 연동할 때 로그인해둔 계정으로 로그인하면 자동으로 속성을 호출한다.
[Select property]의 'account'를 설정하면 'property'는 자동으로 설정된다.
'start date'와 'end date'는 데이터를 수집할 시작일과 마지막일이다.
* 하단에 적혀있듯, 꼭 YYYY-MM-DD와 같은 날짜 형식이 아니더라도
yesterday(어제) 혹은 today(오늘)와 같은 텍스트로도 설정이 가능하다.
'metrics'는 수집하고 싶은 구체적인 데이터들을 의미한다.
필자는 활성화 사용자 수, 조회수, 세션 등을 수집하고자 위와 같이 설정해두었다.
'dimensions'는 데이터들을 나눌 분기점을 의미한다.
예를 들어, date
로 설정해두면 날짜별로 데이터들을 표기한다는 것이다.
그 외에는 추가적으로 설정할 수 있는 옵션들인데,
알아보고자 구글의 상세한 설명을 보기 위해 클릭했으나ㅡ...
Service Unavailable이 나타나며 아무런 설명도 나타나지 않는다.
하지만 필수 옵션도 아니니, 우선 없이 진행하도록 한다.
'keep empty rows'를 체크한 이유는 다른 블로그에서 GA를 활용할 때
이 부분이 활성화되어 있어야 그래프로 나타냈을 때 오류가 나타나지 않는다고 정보를 얻었기 때문이다.
단순히 데이터만 확인하고 싶고 그래프화하지 않을 것이라면 비활성화 해두어도 무방하다.
속성들에 대한 설정을 마치고 [MAKE REQUEST] 버튼을 누르면!
짜잔~ 이렇게 요청할 때 사용되는 data
의 JSON 형식도 확인 및 복사하여 활용할 수 있고,
요청에 따른 응답을 TABLE / JSON 형식으로 확인할 수도 있다!
GA4_PROPERTY_ID
dataRanges
dimensions
metrics
한 번에 3개의 요구사항이 해결됐다 :0
여기까지 왔을 때, 코드의 형태는 다음과 같다.
// Example.js
import { useEffect } from 'react';
import axios from 'axios';
const Example = () => {
useEffect(() => {
axios
.post(`https://analyticsdata.googleapis.com/v1beta/properties/${GA4_PROPERTY_ID}:runReport`,
{
"dimensions": [{ "name":"date" }],
"metrics": [{ "name":"activeUsers" }, { "name":"screenPageViews" }, { "name":"sessions" }],
"dateRanges": [{ "startDate":"2024-01-01", "endDate":"today" }],
"keepEmptyRows": true
}
)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
})
})
}
export default Example;
GA의 홈 화면에서 좌측 하단의 관리(⚙️) 버튼 ▶ [속성 설정] ▶ [속성 세부정보] ▶ 우측 상단의 '속성 ID'에서 확인할 수 있다!
친절하게 복사버튼도 있으니, 해당 속성 ID를 복사하여 코드에 붙여넣도록 하자 :)
* 하지만 이러한 ID, KEY 값과 같은 데이터들은 노출될 경우 보안상 취약할 수 있기 때문에,
.env
파일에 환경변수로 담아두는 것을 추천한다.
* 필자 역시 REACT_APP_GA4_PROPERTY_ID 라는 환경변수로 .env
파일에 담아두었다.
여기까지 모든 절차를 잘 따라왔다면, 이제 필요한 값들은 대부분 준비가 되었다.
GA4_PROPERTY_ID
dataRanges
dimensions
metrics
코드도 아래와 같이 작성되었을 것이다.
// Example.js
import { useEffect } from 'react';
import axios from 'axios';
const Example = () => {
useEffect(() => {
axios
.post(`https://analyticsdata.googleapis.com/v1beta/properties/${process.env.REACT_APP_GA4_PROPERTY_ID}:runReport`,
{
"dimensions": [{ "name":"date" }],
"metrics": [{ "name":"activeUsers" }, { "name":"screenPageViews" }, { "name":"sessions" }],
"dateRanges": [{ "startDate":"2024-01-01", "endDate":"today" }],
"keepEmptyRows": true
}
)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
})
})
}
export default Example;
좋다!
이제 runReport
를 통해 받은 응답을 확인하기 위해 콘솔창을 딱 열어보면!
분명 완벽해야했을 내 응답은 어째서 401(Unauthorized) 상태 코드를 보여주는걸까?
다행히 검색을 통해 원인을 알 수 있었는데, 바로 POST
요청에서 access_token
을 빼먹었기 때문이다.
즉, API에 요청을 보낼 때 내가 승인이나 인증을 받은 사람인지 증명하지 못했다는 것!
* 무엇을 믿고 데이터를 함부로 주겠나?!
당황하지 않고 Google Cloud API 서비스로 접속한다.
http://
, https://
를 제외하고 입력한다..../auth/userinfo.email - 기본 Google 계정의 이메일 주소 확인
만 선택한 다음,http://localhost:port
, ③https://developers.google.com/oauthplayground
를 입력하고여기서 생성된 클라이언트 ID(OAuth Client ID
)와 클라이언트 보안 비밀번호(OAuth Client Secret
)은 이후에 사용되므로,
JSON 파일을 다운로드 받거나 복사해두도록 한다!
* 이후에도 해당 ID를 클릭하여 정보들을 다시 확인할 수 있긴하다.
(여기서 [사용]을 누르면 아래와 같이 'API 사용 설정됨'이 우측에 나타나고,
[사용] 버튼이 [관리] 버튼으로 바뀐다)
이제 토큰을 받기 위한 세팅은 끝났으니,
OAuth 2.0 PlayGround로 이동하여 토큰을 받아보자!
OAuth Client ID
)와 클라이언트 보안 비밀번호(OAuth Client Secret
)을 입력해준다.Refresh token
과 Access token
이 생성된다!여기까지 왔으니, 다시 한 번 header
에 Access token
을 넣어서 코드를 작성해보면ㅡ
* GA4_PROPERTY_ID
와 마찬가지로 보안상의 이유로 .env
에 환경변수로 담아 작성했다.
// Example.js
import { useEffect } from 'react';
import axios from 'axios';
const Example = () => {
useEffect(() => {
axios
.post(`https://analyticsdata.googleapis.com/v1beta/properties/${process.env.REACT_APP_GA4_PROPERTY_ID}:runReport`,
{
"dimensions": [{ "name":"date" }],
"metrics": [{ "name":"activeUsers" }, { "name":"screenPageViews" }, { "name":"sessions" }],
"dateRanges": [{ "startDate":"2024-01-01", "endDate":"today" }],
"keepEmptyRows": true
},
{
headers: {
'Authorization': `Bearer ${process.env.REACT_APP_OAUTH_ACCESS_TOKEN}`
}
}
)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
})
})
}
export default Example;
두근거리는 마음으로 콘솔창을 열어보니?!
정상적으로 응답이 호출되는 것을 확인할 수 있었다!
다만, Access token
만으로는 한계가 있는데
기본적으로 Access token
은 만료기간이 존재하기 때문이다.
(아래 예시의 경우, 1시간(60분, 3600초) 이후에 Access token
이 만료된다는 것)
1시간마다 코드에서 Access token
을 교체해줄 수도 없는 노릇이니, 자동적으로 갱신이 되어야하는데
그 때 사용되는 것이 바로 Refresh token
이다.
OAuth 2.0 Playground의 설정(⚙️)에서 입력했던 클라이언트 ID(OAuth Client ID
)와 클라이언트 보안 비밀번호(OAuth Client Secret
),
그리고 3. 에서 생성된 Refresh token
이 있다면 Access token
을 손쉽게 갱신할 수 있다.
* 이번에도 역시 마찬가지로 보안상의 이유로 .env
에 환경변수로 담아 작성했다.
axios
.post('https://accounts.google.com/o/oauth2/token',
{
"client_id": `${process.env.REACT_APP_OAUTH_CLIENT_ID}`
"client_secret": `${process.env.REACT_APP_OAUTH_CLIENT_SECRET}`,
"refresh_token": `${process.env.REACT_APP_OAUTH_REFRESH_TOKEN}`,
// "grant_type"은 "refresh_token"으로, 이 코드와 동일하게 작성해주면 된다.
"grant_type": "refresh_token"
}
)
.then((response) => { console.log(response); }
.catch((error) => { console.log(error); })
이렇게 작성해두면 response.data.access_token
에 갱신된 Access token
이 전달되어 응답이 온다!
정리해보자면,
① OAuth Client ID
, OAuth Client Secret
, Refresh token
을 통해 https://accounts.google.com/o/oauth2/token
으로
POST
요청을 보내서 갱신된 Access token
을 발급 받는다.
② 발급 받은 Access token
을 headers
에 담아
https://analyticsdata.googleapis.com/v1beta/properties/${process.env.REACT_APP_GA4_PROPERTY_ID}:runReport
으로
dataRanges
, dimensions
, metrics
데이터를 포함하여 POST
요청을 보내면 원하는 결과값이 호출된다는 것!
여기까지 이해하는데 성공했다면 자신을 칭찬해주면 된다!
GA4의 이전 버전인 GA3(Universal Analytics, UA)에 관한 글이 검색결과의 주를 이루고
GA4를 연동하는 것까지는 정보가 많아도 API를 실제로 요청하는 것에 대한 내용은 적어서
필자는 거의 1.5일 가까이 GA4를 붙들어매고 이해하려고 애썼다...
어쨌거나! 글을 읽고 고개를 끄덕이며 바로바로 이해가 됐다면 충분히 자부심을 느껴도 된다는 것이다 :)
이제 마지막이다.
정리한 내용을 바탕으로 코드를 작성해보자면ㅡ
// Example.js
import { useEffect } from 'react';
import axios from 'axios';
const Example = () => {
useEffect(() => {
// 'client_id', 'client_secret', 'refresh_token'을 사용하여 갱신된 'access_token'을 요청한다.
axios.post('https://accounts.google.com/o/oauth2/token',
{
"client_id": `${process.env.REACT_APP_OAUTH_CLIENT_ID}`,
"client_secret": `${process.env.REACT_APP_OAUTH_CLIENT_SECRET}`,
"refresh_token": `${process.env.REACT_APP_OAUTH_REFRESH_TOKEN}`,
"grant_type": "refresh_token"
}
)
.then((response) => {
// 만약 정상적으로 'access_token'을 받았다면, 기본 보고서(runReport)를 호출하는 요청을 보낸다.
axios.post(`https://analyticsdata.googleapis.com/v1beta/properties/${process.env.REACT_APP_GA4_PROPERTY_ID}:runReport`,
// runReport 요청에 필요한 'dimensions', 'metrics', 'dataRanges'를 data에 포함하여 전송한다.
{
"dimensions": [{ "name":"date" }],
"metrics": [{ "name":"activeUsers" }, { "name":"screenPageViews" }, { "name":"sessions" }],
"dateRanges": [{ "startDate":"2024-01-01", "endDate":"today" }],
"keepEmptyRows": true,
},
// 이전에 전달받은 'access_token'을 headers에 담는다(인증).
{
headers: {
'Authorization': `Bearer ${response.data.access_token}`
}
}
)
// 정상적으로 응답을 받았다면, 콘솔창에 runReport의 결과가 나타날 것이다.
.then((response) => {
console.log(response);
})
// runReport가 정상적으로 호출되지 않았다면, [REPORT ERROR]라는 문구와 함께 콘솔창에 에러가 보일 것이다.
.catch((error) => {
console.log('[REPORT ERROR] ', error);
})
})
// 'access_token'을 호출하는 것에 실패했다면, [TOKEN ERROR]라는 문구와 함께 콘솔창에 에러가 보일 것이다.
.catch((error) => {
console.log('[TOKEN ERROR] ', error);
})
})
}
이렇게 코드를 작성하면 정상적으로 GA4의 기본 보고서가 응답으로 날아온다 :D
정말 길고 길었다!
이제 보고서 응답도 받았으니, 이것을 야무지게 조리해서 방문자수로 보이게 하거나
도표로 만들어 방문자 통계를 내거나 혹은 방문자들의 다른 데이터를 정리해서 분석하거나 하는 것은
여러분의 몫이니 다양하게 사용해보도록 하자!
좋은글 감사합니다! 근데 더 간단하게 권한허용을 하는 방법이 있어서 소개드려요!
https://www.heropy.dev/p/wc7QvJ
https://developers.google.com/analytics/devguides/reporting/data/v1/quickstart-client-libraries?hl=ko