[React.js] GA4(Google Analytics) - ②API 호출하기

slight-snow·2024년 1월 24일
0

React

목록 보기
3/3
post-thumbnail

지난 [React.js] GA4(Google Analytics 4) - ①연동하기에서 웹사이트와 GA4를 연동해보았으니,
이번에는 웹사이트에서 GA4 API를 활용하여 데이터를 호출하는 방법을 구체적으로 알아볼 것이다!



📌구글 애널리틱스(Google Analytics) API 호출 방법

여기서는 React.js의 프론트엔드 클라이언트에서 GA에 API를 호출하는 방법을 다룬다.


🧩 API 공식 문서

GA4 이전의 GA3까지는 Reporting API v4에서 API 사용법을 다루었으나,
GA4 업데이트되면서 해당 API에 대한 지원이 중단되고, Analytics Data API v1로 대체되었다.

Data API v1에서 사용 가능한 다양한 메서드들과 사용 방법들을 확인할 수 있다.

* 참고로 100% 한글화되지 않았기에, 종종 제목과 내용이 숫자로 되어있는 문서들이 있는데,
  해당 문서는 언어를 'English'로 바꿔서 영어로 확인해야한다는 단점이 있다.

영어가 부담스럽고, 읽어봐도 어떻게 써야하는지 잘 모르겠다면 당신은 잘 오다!
지금부터 한 조각씩 천천히 사용법을 알아볼 것이다.


🧩 기본 보고서: runReport

위의 Data API v1 공식문서에서 기본 보고서 메뉴를 클릭하면 제목도, 내용도 숫자로 나타난다.
아마 한국어로 번역하는 과정에서 오류가 발생했거나, 아직 미완성이거나... 그러한 이유인 듯하다.

번역은 되지 않았더라도, 공식문서를 확인해보면 눈여겨볼만한 내용은 다음과 같다.

  • runReport 메서드는 https://analyticsdata.googleapis.com/v1beta/properties/GA4_PROPERTY_ID:runReport
    HTTP POST 요청을 보내서 사용할 수 있고, GA4_PROPERTY_ID 값이 필요하다.
  • 보고서를 생성하기 위해서는 dataRanges, dimensions, metrics 항목이 필요하다.

여기까지 봤을 때, GA4_PROPERTY_IDdataRanges, dimensions, metrics도 뭔진 모르겠지만
React.js에서 axios를 통해 위의 URL로 dataRanges, dimensions, metrics 데이터가 포함된
POST 요청을 보내면 되겠다는 생각을 할 수 있어야 한다!

문서에서 다른 부분은 차치하더라도 딱 이 부분만큼은 반드시 숙지하도록 한다.

  • GA4_PROPERTY_ID
  • dataRanges
  • dimensions
  • metrics

🧩 GA4 Query Explorer (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;

🧩 GA4 Property ID (GA4_PROPERTY_ID)

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를 통해 받은 응답을 확인하기 위해 콘솔창을 딱 열어보면!



🧩 Google API Console (Client ID, Client Secret)

분명 완벽해야했을 내 응답은 어째서 401(Unauthorized) 상태 코드를 보여주는걸까?
다행히 검색을 통해 원인을 알 수 있었는데, 바로 POST 요청에서 access_token을 빼먹었기 때문이다.
즉, API에 요청을 보낼 때 내가 승인이나 인증을 받은 사람인지 증명하지 못했다는 것!

* 무엇을 믿고 데이터를 함부로 주겠나?!

당황하지 않고 Google Cloud API 서비스로 접속한다.

  1. 아마 처음 접속했다면 아래와 같이 깨끗한 화면을 볼 수 있을텐데,
    화면에 보이는 [프로젝트 만들기]를 클릭하여 우선 프로젝트를 생성해주도록 한다.

  1. 프로젝트 이름을 입력하고, [만들기] 버튼을 누른다.

  1. 프로젝트를 만드는 데 성공했다면, 좌측 메뉴의 [사용자 인증 정보]에 들어가서 [+ 사용자 인증 정보 만들기]를 클릭,
    [OAuth 클라이언트 ID]를 눌러 OAuth 2.0 클라이언트 ID를 하나 만들어주도록 한다.

  1. 그러면 동의 화면을 구성해야 한다는 문구가 나타날텐데, [동의 화면 구성] 버튼을 눌러 해당 절차로 이동한다.

  1. User Type으로 '외부'를 선택한 후 [만들기] 버튼을 눌러준다.

  1. 앱의 이름과 사용자 지원 이메일을 입력한다. 사용자 지원 이메일은 선택할 수 있는게 자신밖에 없어서 그대로 선택해주면 된다.
    배포된 React.js의 홈페이지 URL을 '애플리케이션 홈페이지'에 입력하고, '승인된 도메인 1'에는 http://, https://를 제외하고 입력한다.

  1. [범위 추가 또는 삭제] 버튼을 클릭하여 .../auth/userinfo.email - 기본 Google 계정의 이메일 주소 확인만 선택한 다음,
    [업데이트] 버튼을 눌러 갱신해주고, [저장 후 계속] 버튼으로 다음 절차로 넘어간다.

  1. 테스트 사용자는 나 자신의 메일을 입력하여 추가해주고, [저장 후 계속]을 누르면
    OAuth 동의 화면 설정이 완료된다!

  1. 이제 동의 화면 설정도 완료되었으니, 다시 3.에서 진행하려고 했던 [OAuth 클라이언트 ID] 만들기를 재개하도록 한다.
    '애플리케이션 유형'은 '웹 애플리케이션'으로 설정하고, 프로젝트의 이름을 입력한다.
    '승인된 자바스크립트 원본'에는 프로젝트의 배포 URL을 입력하고,
    '승인된 리디렉션 URI'에는 ①배포 URL, ②http://localhost:port, ③https://developers.google.com/oauthplayground 를 입력하고
    [만들기] 버튼을 누르면 OAuth 2.0 클라이언트 ID가 생성된다.

여기서 생성된 클라이언트 ID(OAuth Client ID)와 클라이언트 보안 비밀번호(OAuth Client Secret)은 이후에 사용되므로,
JSON 파일을 다운로드 받거나 복사해두도록 한다!
* 이후에도 해당 ID를 클릭하여 정보들을 다시 확인할 수 있긴하다.

  1. 좌측 메뉴의 [사용 설정된 API 및 서비스] 를 클릭하고, 화면 중앙의 [+ API 및 서비스 사용 설정]을 눌러 API 라이브러리로 이동한다.

  1. 'Google Analytics Reporting API', 'Google Analytics Data API'를 검색하여 아래와 같이 생긴 API를 클릭,
    [사용] 버튼을 눌러 활성화 시켜준다.

(여기서 [사용]을 누르면 아래와 같이 'API 사용 설정됨'이 우측에 나타나고,
[사용] 버튼이 [관리] 버튼으로 바뀐다)


🧩 OAuth 2.0 PlayGround (Access Token, Refresh Token)

이제 토큰을 받기 위한 세팅은 끝났으니,
OAuth 2.0 PlayGround로 이동하여 토큰을 받아보자!

  1. 우측 상단의 설정(⚙️)을 눌러, 다른 것은 크게 손댈 것이 없고 'Use your own OAuth credentials' 체크박스를 활성화한 다음,
    이전에 생성했던 클라이언트 ID(OAuth Client ID)와 클라이언트 보안 비밀번호(OAuth Client Secret)을 입력해준다.
    따로 저장버튼은 보이지 않는데, 하단의 [Close] 버튼을 누르면 자동으로 설정이 저장된다.

  1. 왼쪽에 있는 Scope들 중, 하단의 Scope만 선택한 다음 [Authorize APIs] 버튼을 누른다.

  1. 그러면 이렇게 Refresh tokenAccess token이 생성된다!

여기까지 왔으니, 다시 한 번 headerAccess 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 tokenheaders에 담아
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

정말 길고 길었다!
이제 보고서 응답도 받았으니, 이것을 야무지게 조리해서 방문자수로 보이게 하거나
도표로 만들어 방문자 통계를 내거나 혹은 방문자들의 다른 데이터를 정리해서 분석하거나 하는 것은
여러분의 몫이니 다양하게 사용해보도록 하자!


profile
주니어 개발자의 기억을 위한 기록 :)

0개의 댓글