GA4 Search Console 30일 노출 데이터, Python으로 자동 분석하는 법

블로그를 운영하다 보면 어느 순간 이런 상황이 옵니다. GA4는 GA4대로 열어놓고, Search Console은 또 따로 열어놓고, 두 화면을 번갈아 보면서 수동으로 숫자를 정리하는 상황. 데이터는 있는데 연결이 안 되니 결국 중요한 인사이트를 놓치게 됩니다. GA4 Search Console 데이터를 Python으로 자동 분석하면 이 과정 전체를 하나의 스크립트로 해결할 수 있습니다.

왜 두 데이터를 따로 보면 안 되는가

GA4 Search Console Python 자동 분석

GA4와 Google Search Console(GSC)은 측정하는 대상이 다릅니다. GA4는 사이트 안에서 사용자가 무엇을 하는지를 추적하고, GSC는 구글 검색 결과에서 내 사이트가 어떻게 보이는지를 추적합니다. 두 데이터를 따로 보면 다음과 같은 문제가 생깁니다.

확인 항목 GA4 단독 GSC 단독 두 데이터 연결
노출 대비 클릭률 파악 불가 가능 가능
유입 후 체류시간 분석 가능 불가 가능
검색어별 실제 전환 경로 불가 불가 가능
노출은 많은데 클릭이 없는 페이지 탐지 불가 부분 가능 가능

두 데이터를 연결해야 비로소 “이 페이지는 검색에 잘 노출되는데 왜 클릭이 없는가”, “이 키워드로 유입된 사람들은 얼마나 오래 읽는가” 같은 질문에 답할 수 있습니다.

GA4 Search Console Python 자동 분석 환경 준비

분석에 필요한 도구는 크게 두 가지입니다. Google API 접근 권한 설정과 Python 라이브러리 설치입니다.

1단계 — Google Cloud Console에서 API 활성화

Google Cloud Console에 접속해 프로젝트를 생성하고, 다음 두 API를 활성화합니다.

  • Google Analytics Data API — GA4 데이터 접근용
  • Google Search Console API — GSC 노출·클릭 데이터 접근용

이후 서비스 계정(Service Account)을 생성하고 JSON 키 파일을 다운로드합니다. 이 키 파일이 Python 스크립트에서 인증 수단으로 사용됩니다.

2단계 — 서비스 계정에 권한 부여

생성한 서비스 계정 이메일을 GA4 속성 관리자 화면에서 ‘뷰어’ 권한으로 추가합니다. GSC도 마찬가지로 해당 속성의 사용자 관리 메뉴에서 동일한 이메일에 ‘전체’ 또는 ‘제한’ 권한을 부여합니다. 이 단계를 빠뜨리면 API 호출 시 403 오류가 발생하므로 반드시 확인합니다.

3단계 — 라이브러리 설치

터미널에서 아래 명령어로 필요한 패키지를 설치합니다.

pip install google-analytics-data google-auth google-api-python-client pandas

GA4 Search Console 30일 데이터를 Python으로 가져오는 방법

환경 준비가 끝나면 실제 데이터를 불러오는 단계입니다. GA4와 GSC 각각 API를 호출한 후 pandas DataFrame으로 병합합니다.

GA4 데이터 수집 — 최근 30일 페이지별 세션

from google.analytics.data_v1beta import BetaAnalyticsDataClient
from google.analytics.data_v1beta.types import RunReportRequest, DateRange, Dimension, Metric
from google.oauth2 import service_account

CREDENTIALS_FILE = "your-service-account.json"  # 실제 파일명으로 변경
GA4_PROPERTY_ID = "properties/XXXXXXXXX"        # 실제 속성 ID로 변경

credentials = service_account.Credentials.from_service_account_file(
    CREDENTIALS_FILE,
    scopes=["https://www.googleapis.com/auth/analytics.readonly"]
)
client = BetaAnalyticsDataClient(credentials=credentials)

request = RunReportRequest(
    property=GA4_PROPERTY_ID,
    dimensions=[Dimension(name="pagePath")],
    metrics=[
        Metric(name="sessions"),
        Metric(name="averageSessionDuration")
    ],
    date_ranges=[DateRange(start_date="30daysAgo", end_date="today")]
)
response = client.run_report(request)

GSC 데이터 수집 — 최근 30일 쿼리·URL별 노출·클릭

from googleapiclient.discovery import build

SITE_URL = "https://yourdomain.com"  # 실제 사이트 URL로 변경

service = build("searchconsole", "v1", credentials=credentials)

request_body = {
    "startDate": "2025-04-01",
    "endDate": "2025-04-30",
    "dimensions": ["query", "page"],
    "rowLimit": 1000
}

response_gsc = service.searchanalytics().query(
    siteUrl=SITE_URL, body=request_body
).execute()

날짜는 분석 목적에 맞게 조정합니다. rowLimit은 최대 25,000까지 설정 가능하지만, 초기 테스트 시에는 1,000으로 두는 것이 적합합니다.

두 데이터를 병합해서 분석하는 방법

GA4와 GSC 데이터를 각각 pandas DataFrame으로 변환한 후 URL을 기준으로 병합합니다.

import pandas as pd

# GA4 데이터 → DataFrame
ga4_rows = []
for row in response.rows:
    ga4_rows.append({
        "page": row.dimension_values[0].value,
        "sessions": int(row.metric_values[0].value),
        "avg_duration": float(row.metric_values[1].value)
    })
df_ga4 = pd.DataFrame(ga4_rows)

# GSC 데이터 → DataFrame
gsc_rows = []
for row in response_gsc.get("rows", []):
    gsc_rows.append({
        "query": row["keys"][0],
        "page": row["keys"][1],
        "impressions": row["impressions"],
        "clicks": row["clicks"],
        "ctr": row["ctr"],
        "position": row["position"]
    })
df_gsc = pd.DataFrame(gsc_rows)

# URL 기준으로 병합
df_merged = pd.merge(df_gsc, df_ga4, on="page", how="left")

병합된 DataFrame에는 검색어, 노출수, 클릭수, CTR(클릭률), 평균 순위, 세션 수, 체류 시간이 한 행에 담깁니다. 여기서부터 실질적인 분석이 시작됩니다.

GA4 Search Console 데이터 분석으로 얻을 수 있는 인사이트

데이터를 병합한 후 다음 세 가지 분석을 우선적으로 진행하는 것이 효율적입니다.

노출은 높은데 CTR이 낮은 페이지 탐지

low_ctr = df_merged[
    (df_merged["impressions"] > 500) &
    (df_merged["ctr"] < 0.03)
].sort_values("impressions", ascending=False)
print(low_ctr[["page", "query", "impressions", "ctr", "position"]].head(10))

노출 500회 이상이면서 CTR이 3% 미만인 페이지는 제목 태그나 메타 설명 개선이 필요한 후보입니다.

순위 10위 이내인데 세션이 낮은 페이지

missed_traffic = df_merged[
    (df_merged["position"] <= 10) &
    (df_merged["sessions"] < 10)
].sort_values("impressions", ascending=False)
print(missed_traffic[["page", "query", "position", "sessions", "clicks"]].head(10))

순위는 10위권인데 실제 세션이 낮다면 검색 의도와 콘텐츠 내용 사이에 불일치가 있을 가능성이 높습니다.

결과를 CSV로 저장

df_merged.to_csv("gsc_ga4_30days.csv", index=False, encoding="utf-8-sig")

저장된 CSV는 Google Sheets나 Looker Studio로 바로 불러와 시각화할 수 있습니다. utf-8-sig 인코딩을 사용하면 한글이 포함된 경우에도 엑셀에서 깨지지 않습니다.

주의할 점과 한계

이 방법을 사용하기 전에 몇 가지 확인이 필요합니다.

  • GA4와 GSC의 데이터 집계 방식은 다릅니다. GA4는 이벤트 기반, GSC는 노출·클릭 기반이므로 세션 수와 클릭 수가 항상 일치하지 않습니다.
  • GSC 데이터는 최대 16개월치만 제공됩니다. 장기 트렌드 분석이 목적이라면 정기적으로 데이터를 수집해 별도 저장소에 쌓아야 합니다.
  • 키 파일 보안에 주의합니다. 서비스 계정 JSON 키는 외부에 노출되지 않도록 .gitignore에 추가하거나 환경변수로 관리합니다.
  • API 할당량(Quota)이 존재합니다. GSC API는 하루 요청 횟수에 제한이 있으므로 대규모 데이터를 수집할 때는 할당량을 미리 확인합니다.

자주 묻는 질문

Q. GA4와 Search Console을 연결하면 이 스크립트가 필요 없지 않나요?

GA4 내에서 GSC를 연결하면 기본 보고서에서 일부 데이터를 볼 수 있습니다. 그러나 커스텀 필터링, 자동화, 대용량 데이터 추출, 외부 저장은 API 직접 호출 방식이 훨씬 유연합니다. 반복 분석이 목적이라면 스크립트 방식이 적합합니다.

Q. Python을 모르면 이 방법을 쓸 수 없나요?

위 코드는 복사해서 속성 ID와 사이트 URL만 변경하면 실행 가능한 수준으로 작성되었습니다. Python 기초 문법을 모르더라도 Google Colab에서 셀 단위로 실행하면서 결과를 확인하는 방식으로 접근할 수 있습니다.

Q. 30일이 아닌 다른 기간도 설정할 수 있나요?

GA4 API에서는 start_date"7daysAgo", "90daysAgo", 또는 "2025-01-01" 형식으로 지정할 수 있습니다. GSC API도 동일하게 날짜 문자열을 직접 입력하면 됩니다.


GA4 Search Console 데이터를 Python으로 자동 분석하는 구조 자체는 단순합니다. API 권한 설정이 가장 까다로운 단계이고, 그 이후는 코드를 복사해서 값을 바꾸는 수준입니다. 매달 같은 작업을 반복해야 한다면 이 스크립트를 스케줄러에 등록해두는 것이 현실적으로 가장 효율적인 방법입니다.

썸네일: Myriam Jessier on Unsplash

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤