[프로젝트] GA(Google Analytics) 데이터 활용 유저분석

김대현·2024년 7월 13일

PROJECT

목록 보기
2/7

아래는 약 1년( 2016년 8월 ~ 2017년 8월 ) 의 기간 동안 A회사 자사 웹사이트에서 발생한 GA(Google Analytics) 데이터를 통해 웹사이트 아용자 행동 패턴 및 트래픽을 분석한 프로젝트이다.


Google 애널리틱스(Google Analytics, GA)란?

Google 애널리틱스(Google Analytics, GA)는 웹사이트 및 앱의 트래픽과 사용자 행동을 추적하고 분석하기 위한 도구이다. 이를 통해 마케팅 캠페인의 성과를 측정하고, 사용자 경험을 개선하며, 비즈니스 의사 결정을 내릴 수 있게 도움을 준다. GA 데이터는 여러 가지 중요한 정보를 포함하고 있다. 주요 요소들은 사용자(User), 세션(Session), 페이지뷰(Pageviews), 이탈률(Bounce Rate), 전환(Conversions), 트래픽 소스(Traffic Sources) 등이 있다.

GA 데이터를 활용해
사용자의 행동을 분석해 어떤 페이지가 가장 많이 방문되었는지, 사용자가 어느 페이지에서 많이 이탈하는지를 파악하여 사용자 경험을 개선하거나 사용자 흐름(User Flow)을 분석하여 사이트 내에서 사용자의 경로를 파악하고 최적화할 수 있다.

또한
마케팅 캠페인 성과를 측정해 다양한 채널(검색, 소셜 미디어, 이메일 등)에서 유입된 트래픽을 분석하여 어떤 마케팅 채널이 효과적인지 평가할 수 있다. 그리고 캠페인별 목표 전환율을 분석하여 ROI(Return on Investment)를 측정할 수 있다.

마지막으로
페이지 로딩 속도, 이탈률 등을 분석하여 웹 사이트 성능 최적화에 도움을 줄 수 있으며 A/B 테스트를 통해 여러 가지 디자인, 콘텐츠, 기능을 실험하고 최적의 선택을 할 수 있게 도움을 준다.



문제 상황은 이렇다:

A사는 자사의 웹사이트에 대한 사용자의 행동 패턴과 트래픽 출처에 대한 깊은 이해를 갖기 원한다. 최근 웹사이트 방문자 수의 변동이 있었으나,원인을 정확히 파악하지 못하고 있다.
그래서 GA(Google Analytics) 데이터를 통해 웹사이트의 사용자 행동 및 트래픽의 주요 원인을 파악하려 한다.

⛳ 문제정의

▶ 웹사이트의 트래픽과 사용자 행동 패턴의 변동원인에 대한 정보부족

⛳ 기대효과

▶ 사용자의 주요 행동 패턴과 유입 채널을 파악하여 효율적인 마케팅 전략 수립 및 웹사이트 개선 방향 설정.

⛳ 해결방안

▶ GA 데이터를 통해 주요 트래픽 소스 및 채널 그룹핑 분석
▶ 사용자의 지리적 위치와 기기 정보에 따른 세그먼트 분석
▶ 방문자의 세션 및 방문 시간 흐름 분석

⛳ 성과측정

▶ 분석을 통해 도출된 주요 트래픽 소스와 유저 행동 패턴의 변화를 기반으로 웹사이트의 방문자 수 및 사용자 행동(페이지 뷰, 체류 시간 등)에 어떤 영향을 주는지 측정


데이터셋 정의


# ▶ pd.set option
import numpy as np
import pandas as pd
import json
from pandas import json_normalize

# 데이터프레임 출력 시 최대 열 수와 행 수를 100으로 설정하여 
# 데이터프레임의 모든 열과 행을 볼 수 있도록 설정
pd.set_option('display.max_columns',100)
pd.set_option('display.max_rows',100)

# ▶ Data read
json_cols = ['device', 'geoNetwork', 'totals', 'trafficSource']

def load_df(filename):
    # path = "../input/" + filename
    df = pd.read_csv(filename, converters={column: json.loads for column in json_cols},
                     dtype={'fullVisitorId': 'str'})
	# CSV 파일을 읽어오며, json_cols에 포함된 열은 JSON 형식으로 로드하고, fullVisitorId는 문자열로 로드
    # converters를 통해 특정 열을 JSON으로 변환, dtype을 통해 특정 열의 데이터 타입을 지정
  
    # JSON 형식의 데이터를 개별 열로 확장
    for column in json_cols:
        # JSON 데이터를 DataFrame으로 변환하여 각 하위 열을 개별 열로 확장
        column_as_df = json_normalize(df[column])
        # 새로운 열 이름을 "기존 열 이름_하위 열 이름" 형식으로 변경
        column_as_df.columns = [f"{column}_{subcolumn}" for subcolumn in column_as_df.columns]
        # 원래의 JSON 열을 삭제하고 확장된 개별 열을 데이터프레임에 병합
        df = df.drop(column, axis=1).merge(column_as_df, right_index=True, left_index=True)
    return df

# 지정된 파일명을 통해 데이터프레임을 로드
df = load_df("S_PJT10_DATA.csv")

df.head()

  • 컬럼 정보
channelGrouping: 채널 그룹핑, 사용자가 웹사이트에 도달한 트래픽 소스 그룹 
  				(예: Organic Search, Direct, Referral 등).
date: 데이터가 수집된 날짜
fullVisitorId: 방문자를 식별하기 위한 방문자 전체의 고유 ID (익명 처리됨).
sessionId: 세션을 식별하기 위한 고유 ID.
socialEngagementType: 사용자가 소셜 네트워크를 통해 사이트와 상호작용했는지 여부, 소셜 참여 유형
visitId: 방문(세션)을 식별하기 위한 고유 ID.
visitNumber: 사용자가 해당 사이트를 몇 번째 방문했는지 나타내는 숫자, 방문 횟수
visitStartTime: 방문이 시작된 시간 (Unix 타임스탬프 형식).

# device_ (기기 정보 관련 컬럼)
device_browser: 사용자가 사용한 브라우저 (예: Chrome, Firefox 등).
device_browserVersion: 브라우저의 버전.
device_browserSize: 브라우저 창 크기.
device_operatingSystem: 사용자가 사용한 운영체제 (예: Windows, Macintosh, Linux 등).
device_operatingSystemVersion: 운영체제의 버전.
device_isMobile: 사용자가 모바일 기기를 사용했는지 여부 (True/False).
device_mobileDeviceBranding: 모바일 기기 브랜드 (예: Samsung, Apple 등).
device_mobileDeviceModel: 모바일 기기 모델.
device_mobileInputSelector: 모바일 기기의 입력 방식 (예: 터치스크린).
device_mobileDeviceInfo: 모바일 기기 정보.
device_mobileDeviceMarketingName: 모바일 기기의 마케팅 이름.
device_flashVersion: 플래시 버전.
device_language: 사용자의 브라우저 언어 설정.
device_screenColors: 화면 색상 설정.
device_screenResolution: 화면 해상도.
device_deviceCategory: 기기 카테고리 (예: desktop, mobile, tablet).


# geoNetwork_ (지리 정보 관련 컬럼) 지리적 네트워크 정보
geoNetwork_continent: 사용자가 위치한 대륙.
geoNetwork_subContinent: 사용자가 위치한 아대륙.
geoNetwork_country: 사용자가 위치한 국가.
geoNetwork_region: 사용자가 위치한 지역.
geoNetwork_metro: 사용자가 위치한 도시권.
geoNetwork_city: 사용자가 위치한 도시.
geoNetwork_cityId: 사용자가 위치한 도시의 ID.
geoNetwork_networkDomain: 사용자가 접속한 네트워크 도메인.
geoNetwork_latitude: 위도.
geoNetwork_longitude: 경도.
geoNetwork_networkLocation: 네트워크 위치.

  
# totals_ (총합 정보 관련 컬럼) 즉 총계
totals_visits: 총 방문 수.
totals_hits: 총 히트 수 (페이지뷰 등).
totals_pageviews: 총 페이지뷰 수.
totals_bounces: 이탈한 세션 수 (한 페이지 보고 나간 세션).
totals_newVisits: 신규 방문 수.
totals_transactionRevenue: 거래 수익. 얼마만큼의 수익을 거둬두었는가
trafficSource_ (트래픽 소스 관련 컬럼)
trafficSource_campaign: 캠페인 이름.
trafficSource_source: 트래픽 소스 (예: google, bing 등).
trafficSource_medium: 트래픽 매체 (예: organic, cpc 등).
trafficSource_keyword: 사용된 키워드.
trafficSource_adwordsClickInfo.criteriaParameters: 애드워즈 클릭 정보 기준 파라미터.
trafficSource_isTrueDirect: 직접 트래픽 여부 (True/False).
trafficSource_referralPath: 추천 경로.
trafficSource_adwordsClickInfo.page: 애드워즈 클릭이 발생한 페이지.
trafficSource_adwordsClickInfo.slot: 애드워즈 광고 슬롯.
trafficSource_adwordsClickInfo.gclId: 애드워즈 광고 클릭 ID.
trafficSource_adwordsClickInfo.adNetworkType: 애드워즈 광고 네트워크 유형.
trafficSource_adwordsClickInfo.isVideoAd: 비디오 광고 여부 (True/False).
trafficSource_adContent: 광고 내용.
trafficSource_campaignCode: 캠페인 코드.
# ▶ Data 형태 확인
# ▶ 903,653 row, 8 col로 구성됨
print('df', df.shape)

> df (903653, 55)

확인 결과 903653 개의 데이터가 있으며 55개의 컬럼으로 이루어져 있는 대용량 데이터임을 확인할 수 있다.


데이터 전처리 및 EDA

(1) Data shape(형태) 확인

# ▶ Data 형태 확인
# ▶ 903,653 row, 8 col로 구성됨
print('df', df.shape)
  
  
> df (903653, 55)
  • 903653 개의 데이터가 있으며 55개의 컬럼으로 이루어져 있음.

(2) Data type 확인

# ▶ Data type 확인
df.info()
  
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 903653 entries, 0 to 903652
Data columns (total 55 columns):
 #   Column                                             Non-Null Count   Dtype 
---  ------                                             --------------   ----- 
 0   channelGrouping                                    903653 non-null  object
 1   date                                               903653 non-null  int64 
 2   fullVisitorId                                      903653 non-null  object
 3   sessionId                                          903653 non-null  object
 4   socialEngagementType                               903653 non-null  object
 5   visitId                                            903653 non-null  int64 
 6   visitNumber                                        903653 non-null  int64 
 7   visitStartTime                                     903653 non-null  int64 
 8   device_browser                                     903653 non-null  object
 9   device_browserVersion                              903653 non-null  object
 10  device_browserSize                                 903653 non-null  object
 11  device_operatingSystem                             903653 non-null  object
 12  device_operatingSystemVersion                      903653 non-null  object
 13  device_isMobile                                    903653 non-null  bool  
 14  device_mobileDeviceBranding                        903653 non-null  object
 15  device_mobileDeviceModel                           903653 non-null  object
 16  device_mobileInputSelector                         903653 non-null  object
 17  device_mobileDeviceInfo                            903653 non-null  object
 18  device_mobileDeviceMarketingName                   903653 non-null  object
 19  device_flashVersion                                903653 non-null  object
 20  device_language                                    903653 non-null  object
 21  device_screenColors                                903653 non-null  object
 22  device_screenResolution                            903653 non-null  object
 23  device_deviceCategory                              903653 non-null  object
 24  geoNetwork_continent                               903653 non-null  object
 25  geoNetwork_subContinent                            903653 non-null  object
 26  geoNetwork_country                                 903653 non-null  object
 27  geoNetwork_region                                  903653 non-null  object
 28  geoNetwork_metro                                   903653 non-null  object
 29  geoNetwork_city                                    903653 non-null  object
 30  geoNetwork_cityId                                  903653 non-null  object
 31  geoNetwork_networkDomain                           903653 non-null  object
 32  geoNetwork_latitude                                903653 non-null  object
 33  geoNetwork_longitude                               903653 non-null  object
 34  geoNetwork_networkLocation                         903653 non-null  object
 35  totals_visits                                      903653 non-null  object
 36  totals_hits                                        903653 non-null  object
 37  totals_pageviews                                   903553 non-null  object
 38  totals_bounces                                     450630 non-null  object
 39  totals_newVisits                                   703060 non-null  object
 40  totals_transactionRevenue                          11515 non-null   object
 41  trafficSource_campaign                             903653 non-null  object
 42  trafficSource_source                               903653 non-null  object
 43  trafficSource_medium                               903653 non-null  object
 44  trafficSource_keyword                              400724 non-null  object
 45  trafficSource_adwordsClickInfo.criteriaParameters  903653 non-null  object
 46  trafficSource_isTrueDirect                         274005 non-null  object
 47  trafficSource_referralPath                         330941 non-null  object
 48  trafficSource_adwordsClickInfo.page                21460 non-null   object
 49  trafficSource_adwordsClickInfo.slot                21460 non-null   object
 50  trafficSource_adwordsClickInfo.gclId               21561 non-null   object
 51  trafficSource_adwordsClickInfo.adNetworkType       21460 non-null   object
 52  trafficSource_adwordsClickInfo.isVideoAd           21460 non-null   object
 53  trafficSource_adContent                            10946 non-null   object
 54  trafficSource_campaignCode                         1 non-null       object
dtypes: bool(1), int64(4), object(50)
memory usage: 373.2+ MB

총 55개의 열 데이터가 있으며 총 거래 수익을 의미하는 중요한 데이터가 있는 totals_transactionRevenue 가 숫자형 데이터가 아닌 object 타입으로 지정되어 있다. 따라서 이를 숫자형 데이터로 변경시켜줘야 한다.

또한 시간을 나타내는 데이터인 date 또한 object 타입으로 구성되어 있어 이를 날짜형 데이터 타입으로 변경시켜줄 것이다.

# ▶ object type > float type으로 변경
df['totals_transactionRevenue'] = df['totals_transactionRevenue'].astype(float)
  
df['date'] = pd.to_datetime(df['date'], format='%Y%m%d')

(3) Null값 확인 (※ 빈 값의 Data)

# ▶ Null 값 확인
print(df.isnull().sum())

channelGrouping                                           0
date                                                      0
fullVisitorId                                             0
sessionId                                                 0
socialEngagementType                                      0
visitId                                                   0
visitNumber                                               0
visitStartTime                                            0
device_browser                                            0
device_browserVersion                                     0
device_browserSize                                        0
device_operatingSystem                                    0
device_operatingSystemVersion                             0
device_isMobile                                           0
device_mobileDeviceBranding                               0
device_mobileDeviceModel                                  0
device_mobileInputSelector                                0
device_mobileDeviceInfo                                   0
device_mobileDeviceMarketingName                          0
device_flashVersion                                       0
device_language                                           0
device_screenColors                                       0
device_screenResolution                                   0
device_deviceCategory                                     0
geoNetwork_continent                                      0
geoNetwork_subContinent                                   0
geoNetwork_country                                        0
geoNetwork_region                                         0
geoNetwork_metro                                          0
geoNetwork_city                                           0
geoNetwork_cityId                                         0
geoNetwork_networkDomain                                  0
geoNetwork_latitude                                       0
geoNetwork_longitude                                      0
geoNetwork_networkLocation                                0
totals_visits                                             0
totals_hits                                               0
totals_pageviews                                        100
totals_bounces                                       453023
totals_newVisits                                     200593
totals_transactionRevenue                            892138
trafficSource_campaign                                    0
trafficSource_source                                      0
trafficSource_medium                                      0
trafficSource_keyword                                502929
trafficSource_adwordsClickInfo.criteriaParameters         0
trafficSource_isTrueDirect                           629648
trafficSource_referralPath                           572712
trafficSource_adwordsClickInfo.page                  882193
trafficSource_adwordsClickInfo.slot                  882193
trafficSource_adwordsClickInfo.gclId                 882092
trafficSource_adwordsClickInfo.adNetworkType         882193
trafficSource_adwordsClickInfo.isVideoAd             882193
trafficSource_adContent                              892707
trafficSource_campaignCode                           903652
dtype: int64
  • null 값 확인 결과 일부 데이터가 다 수집이 안되어 null 값이 많은 것을 확인할 수 있음. 상당히 많은 양의 null 값을 가지고 있어서 분석을 했을 때 부정확한 결과가 나올 확률이 높다. 그래서 경우에 따라 null 값을 제거해주거나 또는 같은 팀 동료와 상의해서 지워야 하는지 커뮤니케이션 후 처리해주어야 할 거 같다.

(4) Outlier 확인 (이상치, 정상적인 범주를 벗어난 Data)

# ▶ Outlier 확인
df.describe()

		date			visitId			visitNumber		visitStartTime	totals_transactionRevenue
count	9.036530e+05	9.036530e+05	903653.000000	9.036530e+05	1.151500e+04
mean	2.016589e+07	1.485007e+09	2.264897		1.485007e+09	1.337448e+08
std		4.697698e+03	9.022124e+06	9.283735		9.022124e+06	4.482852e+08
min		2.016080e+07	1.470035e+09	1.000000		1.470035e+09	1.000000e+04
25%		2.016103e+07	1.477561e+09	1.000000		1.477561e+09	2.493000e+07
50%		2.017011e+07	1.483949e+09	1.000000		1.483949e+09	4.945000e+07
75%		2.017042e+07	1.492759e+09	1.000000		1.492759e+09	1.076550e+08
max		2.017080e+07	1.501657e+09	395.000000		1.501657e+09	
  • describe() 을 통해 전체 통계량을 확인해봤을 때 마이너스 값이나 너무 큰 값으로 이루어져 있는 이상치는 확인되지 않는다.

(5) 데이터 EDA

# ▶ 총 분석 기간, 1년치 Data
df['date'].min(), df['date'].max()	
  
> (Timestamp('2016-08-01 00:00:00'), Timestamp('2017-08-01 00:00:00'))

요약: 수집된 데이터는 2016년 8월~2017년 8월까지의 데이터로 전체적인 데이터 정보들은 아래와 같다.

1. 사용자의 방문 경로를 나타내는 그룹

  • [ trafficSource_ (트래픽 소스 관련 컬럼) channelGrouping: 사용자가 웹사이트에 도달한 트래픽 소스 그룹 (예: Organic Search, Direct, Referral 등).]

2. 데이터가 수집된 날짜를 말하는

  • date

3. 방문자를 식별하기 위한 고유 ID (익명 처리됨)

  • fullVisitorId

4. 사용자의 행동 및 방문 세션을 식별하기 위한 고유 ID인

  • sessionId, visitId, visitNumber, visitStartTime

5. 사용자가 소셜 네트워크를 통해 사이트와 상호작용했는지 여부인

  • socialEngagementType

6. 그리고 종합적으로

  • device_ (기기 정보 관련 컬럼), geoNetwork_ (지리 정보 관련 컬럼) , totals_ (총합 정보 관련 컬럼), trafficSource_ (트래픽 소스 관련 컬럼)

유저 행동 패턴 주요 지표(KEY Porfarmance Indicator) 추출

이제 전체적인 데이터 EDA를 완료했으니 A회사의 유저 주요 행동 패턴을 파악하기 위해 지표를 기획 및 개발하여 각 지표를 비교해 유저의 행동 패턴을 파악해보자.

웹사이트에서 사용자의 행동 패턴 또는 방문자 수는 매출에 많은 영향을 미쳐서 사용자 행동 패턴을 파악하고 있는 것은 매우 중요하다. 사용자 행동 패턴은 크게 아래 세 가지 지표로 파악할 수가 있다.

  • 월 별 MAU : 특정 월에 웹사이트나 앱을 사용한 고유 사용자의 수를 나타낸다. 서비스의 인기도와 사용자 참여도를 평가하는 데 사용된다.
  • 월 별 Transcation AMT: 특정 월에 발생한 총 거래 금액을 나타낸다. 전자상거래 사이트나 앱에서 매출 성과를 직접적으로 나타내는 지표이다.
  • 월 별 Conversion Rate: 전환율은 특정 월에 방문자 중 목표 행동(예: 구매, 회원가입 등)을 완료한 비율을 나타낸다. 사용자 패턴을 파악해 마케팅 및 사용자 경험 최적화의 효과를 평가하는 중요한 지표이다.

(1) 월 별 MAU

MAU 정의

  • MAU (Monthly Active Users)는 월별로 고유하게 웹사이트나 앱을 방문하거나 사용하는 사용자 수를 의미한다. 이는 특정 기간 동안의 사용자 활동을 측정하여 서비스의 성장을 평가하고, 사용자 인기도와 유지율 및 참여도를 분석하고 평가할 수 있는 중요한 지표이다.
# ▶ 월 기준 VisitorID Count
df.groupby(df['date'].dt.strftime('%Y-%m'))['fullVisitorId'].nunique()
  
date
2016-08    61699
2016-09    59121
2016-10    84901
2016-11    99734
2016-12    63839
2017-01    53041
2017-02    51364
2017-03    57888
2017-04    55681
2017-05    52233
2017-06    52067
2017-07    58569
2017-08     2293
Name: fullVisitorId, dtype: int64

date 열 데이터에서 dt.strftime 명령어를 통해 년 월을 추출하고 이 '년-월'이 추출된 'date' 열을 기준으로 방문자 전체id(fullvisitorID)를 nunique() 하여 고유한 값들만 추출해 계산한다.

계산 결과 2016년 8월부터 2017년 8월까지의 방문자 id 수를 확인할 수 있으며 2017년 8월 1일까지의 데이터가 수집됐기에 8월 달의 데이터가 적은 것은 정상이라고 할 수 있다.

# ▶ 월 기준 VisitorID Count 시각화
import pandas as pd
import matplotlib.pyplot as plt
# Matplotlib의 스타일을 다크 배경으로 설정
plt.style.use('dark_background')

# 'date' 컬럼을 연-월 형식으로 변환한 후, 'fullVisitorId'의 고유값을 카운트하여 데이터프레임 생성
df_mau = pd.DataFrame(df.groupby(df['date'].dt.strftime('%Y-%m'))['fullVisitorId'].nunique())

# 시각화를 위한 Figure와 크기 설정
plt.figure(figsize=(12, 3))

# 막대 그래프 생성 (x축: 연-월, y축: 고유 방문자 수)
plt.bar(df_mau.index, df_mau['fullVisitorId'])

# x축의 레이블 각도를 45도로 설정하여 가독성 향상
plt.xticks(rotation=45)

# x축 레이블 설정
plt.xlabel('Date')

# y축 레이블 설정
plt.ylabel('Value')

# 레이아웃을 자동으로 조정하여 그래프 요소들이 겹치지 않도록 설정
plt.tight_layout()

# 그래프 표시
plt.show()

  • 전체적인 MAU 갯수에 대해서 살펴보기 위해 시각화를 진행했다. 2016년 8월 ~ 2017년 8월 까지의 날짜가 X축을 이루고 Y축은 방문자 고객의 수를 지정한 것이다.
  • 2016년 8월을 시작으로 10월, 11월에 유입된 고객이 가장 많고 이후 12월부터 다시 기존의 8월달의 고객 유입 수준까지 낮아졌다.
  • 10월, 11월에 유입된 고객 수가 증가한 이유에 대한 조금 더 정확하고 구체적인 분석을 위해서는 2017년 10월의 데이터가 있다면 이유나 패턴을 확인할 수 있겠지만 현재로서는 확인이 불가능하다.

(2) 월 별 Transaction AMT

AMT (Transaction Amount) 정의

AMT는 특정 월에 발생한 총 거래 금액을 나타내며 이는 전자상거래 사이트나 앱에서 매출 성과를 직접적으로 나타내는 지표이다. 월별 거래 금액을 확인해 매출 성과를 분석하거나 재무 상태를 평가하고 수익성을 파악할 수도 있다.

현재 데이터에서 우리가 중요하게 봐야 하는 것은 총 거래 수익 totals_transactionRevenue 이다.

이후 중복이 제거된 고유한 구매건들을 customer id 별로 계산한다.

# ▶ 'totals_transactionRevenue' 기준 년 월 별 Transaction AMT 시각화
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('dark_background')

df_amt = pd.DataFrame(df.groupby(df['date'].dt.strftime('%Y-%m'))['totals_transactionRevenue'].sum())

plt.figure(figsize=(12,3))
plt.bar(df_amt.index, df_amt['totals_transactionRevenue'])
plt.xticks(rotation=45)
plt.xlabel('Date')
plt.ylabel('Value')
plt.tight_layout()
plt.show()  

  • 12월 달 4월 달의 수익이 증가한 모습을 보인다. 앞서 살펴봤던 MAU에서는 10월 달과 11월 달에 가장 많은 고객이 유입 됐지만 10월 달과 11월 달의 거래 수익이 많지 않다.
  • 하지만 기존 totals_transactionRevenueNULL 값들이 상당히 많아 실제로 거래가 되지 않은 건지 또는 NULL 값이 많아 데이터가 수집이나 인풋이 되지 않았는지에 대한 것도 확인해봐야 한다.
  • 데이터가 잘못되지 않았다면 고객 유입 수 대비 매출이 작은 것이 실제 문제가 되겠지만 NULL 값이 많아 데이터가 좀 잘못된 거라면 데이터 전처리르 다시 진행해보아야 한다.
  • 이처럼 데이터 분석을 할 때 가장 중요한 것은 분석하고자 하는 데이터에 대한 신뢰성이 확보가 됐냐 되지 않았냐이다.
  • 일단 현재로서는 10월 달과 11월 달의 매출이 고객 유입 수에 비해 작다는 결론을 내릴 수 있다.

(3) 월 별 Conversion Rate

월 별 Conversion Rate 정의

월 별 Conversion Rate 는 전환율을 의미한다. 전환율은 특정 월에 방문자 중 목표 행동(예: 구매, 회원가입 등)을 완료한 비율을 나타낸다.
이는 마케팅 및 사용자 경험 최적화의 효과를 평가하는 중요한 지표이다.

즉 웹사이트에 들어와서 구매 전환까지 이어진 비율을 애기한다. 즉 월별 유입 고객 수 대비 여기서는 totals_transactionRevenue 값이 있으면 구매를 했다라고 보고 totals_transactionRevenue 값이 없으면 구매를 안 했다라고 가정하였다.

Conversion Rate 계산 : (실제 구매까지 이어진 전체 구매 금액 (totals_transactionRevenue) / 구매를 위한 행동을 한 기록이 있는 데이터 전체 session id) * 100

# ▶ 월 별 Conversion Rate 
  
# 년 월 날짜 데이터 변경, 이후 '년-월' 날짜 데이터 별 sessionId와 totals_transcationRevenue의 갯수를 카운트,
df_cov = pd.DataFrame(df.groupby(df['date'].dt.strftime('%Y-%m'))[['sessionId', 'totals_transactionRevenue']].agg(['count'])).reset_index()

df_cov.columns = ['date', 'total', 'Revenue']
# 이후 df_cov 데이터 프레임의 column 들을 재설정
  
df_cov['cov_rate'] = round((df_cov['Revenue']/df_cov['total'])*100,2)  
# (실제 구매까지 이어진 전체 구매 금액 (totals_transactionRevenue) / 구매를 위한 행동을 한 기록이 있는 데이터 전체 session id) * 100
# 구매전환율은 소숫점 둘 째자리까지 표시하여 cov_rate 열을 데이터프레임에 새로 생성  

	date	total	Revenue	cov_rate
0	2016-08	74759	1119	1.50
1	2016-09	71032	859		1.21
2	2016-10	97506	872		0.89
3	2016-11	113972	919		0.81
4	2016-12	79124	1395	1.76
5	2017-01	64694	697		1.08
6	2017-02	62192	708		1.14
7	2017-03	69931	883		1.26
8	2017-04	67126	928		1.38
9	2017-05	65371	1115	1.71
10	2017-06	63578	946		1.49
11	2017-07	71812	1031	1.44
12	2017-08	2556	43		1.68  

각 월 별 전체 세션 id를 total 컬럼으로,
월 별 실제 구매 건 수는 Revenue로,
결과적인 구매 전환율은 cov_rate로 정의하였다.

숫자로만 분포를 확인하기 어려워 구매 전환율(cov_rate)를 시각화 해보았다.

# ▶ 월 별 Conversion Rate 시각화
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('dark_background')

plt.figure(figsize=(12,3))
plt.bar(df_cov.date, df_cov['cov_rate'])
plt.xticks(rotation=45)
plt.xlabel('Date')
plt.ylabel('Value')
plt.tight_layout()
plt.show()

  • 10월과 11월 달이 유입 고객이 많았던 것에 비해 서 구매한 고객은 많이 없기 때문에 구매 전환율(conversion rate)도 떨어지는 것을 확인 가능했다.
  • 하지만 매출은 좀 떨어지고 있었지만 구매 전환율(conversion rate)는 2016년 12월 기점으로 점점 증가하고 있는 추세를 보이고 있다.

지표 기획

사용자의 행동 패턴은 어느정도 분석이 완료됐으며 다음으로 웹사이트의 트래픽 유입 채널에 대한 정보를 파악해보도록 하자.

인터넷 비즈니스에서 회사를 홍보하고 회사의 매출을 높히기 위해 기본적으로 마케팅 캠페인을 진행한다. 마케팅 캠페인 진행 후 성과를 분석을 해야 하는데, 그 성과가 앞서 살펴봤던 유저행동 패턴과 웹사이트 트래픽 유입으로 간접적으로 알 수 있다.

예를 들어 각 유입 채널(컴퓨터, 모바일, 사용한 브라우저, 이메일 접속, 사용한 기기정보, 이용국가) 별로 얼마나 많은 수익을 창출하는지 분석함으로써, 회사가 진행했던 마케팅 캠페인이 중 어떤 것이 가장 효과적인지 파악할 수 있다. 이를 통해 컴퓨터 인터넷 유료 검색 광고 비중을 높힐 것인지, 소셜 미디어 캠페인 비중을 높힐 것인지, 이메일 마케팅을 비중을 높힐 것인지 등 유저에게 다양한 유입 채널을 제공하고 이후 성과를 비교할 수 있다.

이렇게 유입 채널을 세분화하고 성과에 따라 비중을 분류한다면 이후 새로운 마케팅 캠페인을 진행하거나 의사결정을 할 때 수익이 높은 채널에 더 많은 예산을 할당하고, 수익이 낮은 채널의 예산을 조정함으로써 마케팅 ROI를 극대화하며 마케팅 예산을 최소화 할 수 있다. 즉 마케팅 예산의 효율성을 높여 더 많은 수익을 창출할 수 있다는 것이다.

또한 단순히 방문자 수가 많은 채널이 아닌, 실제로 수익을 창출하는 고품질 트래픽을 유도하는 채널을 식별하여 현재 많이 유입되는 채널, 수익이 많은 채널을 파악해 채널의 트렌드를 파악할 수도 있다. 예를 들어, 특정 채널에서 유입된 트래픽은 방문자 수는 많지만 전환율이 낮을 수 있다. 반면, 다른 채널에서 유입된 트래픽은 방문자 수는 적지만 전환율이 높을 수 있다.

그래서
사용 기기 및 브라우저별 수익 성과,
국가 위치별 수익 성과,
광고 캠페인 별 수익 성과,
광고 캠페인이 이용한 매체 별 수익 성과

로 트래픽 유입 채널에 대한 정보를 파악해 보았다.

(1) Device Attributes Analysis 사용 기기 및 브라우저별 수익 성과

import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# 첫 번째 그래프 데이터
df_device_browser = pd.DataFrame(df.groupby(df['device_browser'])['totals_transactionRevenue'].mean()).reset_index()
df_device_browser = df_device_browser.dropna().sort_values("totals_transactionRevenue", ascending = True)

# 두 번째 그래프 데이터
df_device_category = pd.DataFrame(df.groupby(df['device_deviceCategory'])['totals_transactionRevenue'].mean()).reset_index()
df_device_category = df_device_category.dropna().sort_values("totals_transactionRevenue", ascending = True)

# 1x2 서브플롯 생성
fig = make_subplots(rows=1, cols=2, subplot_titles=('Transaction Revenue by Device Category', 'Transaction Revenue by Device Browser'))

# `Device Category` 그래프를 첫 번째 서브플롯에 추가 (수평 막대그래프로 변경)
fig.add_trace(
    go.Bar(x=df_device_category['totals_transactionRevenue'], y=df_device_category['device_deviceCategory'], orientation='h'),
    row=1, col=1
)

# `Device Browser` 그래프를 두 번째 서브플롯에 추가 (수평 막대그래프로 변경)
fig.add_trace(
    go.Bar(x=df_device_browser['totals_transactionRevenue'], y=df_device_browser['device_browser'], orientation='h'),
    row=1, col=2
)

# 레이아웃 업데이트 및 출력
fig.update_layout(title_text="Transaction Revenue Analysis")
fig.show()						 5.607940e+07

  • 확인 결과 desktop을 이용한 유저로부터 가장 많은 수익이 발생했으며 mobiletablet을 이용한 유저로부터의 수익은 큰 차이는 없었다.

  • 또한 desktop 유저가 사용하는 브라우저별 수익도 의미있는 데이터라 생각해 device_browser를 시각화 해보니 Firefox 브라우저의 수익이 월등히 높게 나왔으며 다음은 chrome, edge 순으로 수익이 발생하였다.

  • 이로써 desktopFirefox 브라우저의 마케팅 캠페인 비용 비중을 늘려야 할 것으로 보이며 만약 mobile, tablet의 마케팅 캠페인 비용 비중이 감당이 되지 않는다면 비중을 줄여야 할 것으로 보인다.


(2) GeoNetwork Attributes Analysis, 국가 및 위치별 수익 성과

국가 및 위치별 수익 성과를 통해서는 어떤 지역 또는 국가들의 유저가 많은 수익을 창출하는지 파악하여, 시장을 세분화하여 마케팅 캠페인 조정에 도움을 줄 수 있겠다. 이는 각 국가의 고객 특성에 맞춘 맞춤형 마케팅 전략을 세우는 데 도움을 준다. 특정 지역에서의 수익률이 높다면, 해당 국가에 대한 추가적인 마케팅 및 서비스 확장 등의 의사결정에 도움을 줄 수 있다.

import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots


# 첫 번째 그래프 데이터
df_geoNetwork_continent = pd.DataFrame(df.groupby(df['geoNetwork_continent'])['totals_transactionRevenue'].mean()).reset_index()
df_geoNetwork_continent = df_geoNetwork_continent.dropna().sort_values("totals_transactionRevenue", ascending = True)

# 두 번째 그래프 데이터
df_device_category = pd.DataFrame(df.groupby(df['geoNetwork_subContinent'])['totals_transactionRevenue'].mean()).reset_index()
df_device_category = df_device_category.dropna().sort_values("totals_transactionRevenue", ascending = True)

# 1x2 서브플롯 생성
fig = make_subplots(rows=1, cols=2, subplot_titles=('Transaction Revenue by geoNetwork_subContinent', 'Transaction Revenue by geoNetwork_continent'))

# `Device Category` 그래프를 첫 번째 서브플롯에 추가 (수평 막대그래프로 변경)
fig.add_trace(
    go.Bar(x=df_device_category['totals_transactionRevenue'], y=df_device_category['geoNetwork_subContinent'], orientation='h'),
    row=1, col=1
)

# `Device Browser` 그래프를 두 번째 서브플롯에 추가 (수평 막대그래프로 변경)
fig.add_trace(
    go.Bar(x=df_geoNetwork_continent['totals_transactionRevenue'], y=df_geoNetwork_continent['geoNetwork_continent'], orientation='h'),
    row=1, col=2
)

# 레이아웃 업데이트 및 출력
fig.update_layout(title_text="Transaction Revenue Analysis")
fig.show()

  • 확인 결과 Eastern AfricaWestern Africa에서 이용한 유저로부터 대부분의 수익이 발생했으며 동일하게 Africa 대륙에서도 많은 수익이 발생한 것으로 보인다.

  • 이로써 주요 고객 국가인 Eastern AfricaWestern Africa 국가들의 마케팅 캠페인 비용 비중을 늘려야 할 것으로 보이며 이들의 구매 전환율을 높이는 것에 더 집중해야 할 것이다.


(3) 트래픽 별 수익 성과 분석

먼저 트래픽 데이터가 존재하는 열을 모두 확인해보았다.

# ▶ trafficSource로 시작하는 Col 출력
df.filter(like='trafficSource').columns.tolist()

>['trafficSource_campaign',
 'trafficSource_source',
 'trafficSource_medium',
 'trafficSource_keyword',
 'trafficSource_adwordsClickInfo.criteriaParameters',
 'trafficSource_isTrueDirect',
 'trafficSource_referralPath',
 'trafficSource_adwordsClickInfo.page',
 'trafficSource_adwordsClickInfo.slot',
 'trafficSource_adwordsClickInfo.gclId',
 'trafficSource_adwordsClickInfo.adNetworkType',
 'trafficSource_adwordsClickInfo.isVideoAd',
 'trafficSource_adContent',
 'trafficSource_campaignCode']
  • trafficSource_campaign: 방문자를 사이트로 유도한 광고 캠페인의 이름을 나타내는 것이다. 예를 들어, 특정 광고 캠페인을 통해 웹사이트에 방문한 사용자의 경우, 그 광고 캠페인의 이름이 이 컬럼에 기록되게 된다. 주로 마케팅 팀이 다양한 광고 캠페인의 성능을 분석할 때 사용한다.
    컬럼의 값 예시로 "Black Friday Sale", "Summer Promotion" 등이 있을 수 있다.

  • trafficSource_source: 방문자가 사이트에 도달한 경로를 나타내는 컬럼이다.
    예를 들어, 사용자가 Google에서 검색하여 사이트에 접속한 경우 'google'이라는 값이 저장될 것이고 페이스북 링크를 통해 클릭하여 접속한 경우 'facebook.com'이라는 값이 저장될 것이다.
    예시: "google", "facebook.com", "bing", "newsletter" 등

  • trafficSource_medium : 방문자가 사이트에 도달한 매체를 나타내는 컬럼이다. 이는 컬'source'보다 더 구체적인 정보를 제공한다. 예를 들면, 방문자가 검색을 통해 사이트에 도달한 경우 'organic'이라는 값이 저장된다. 만약 유료 광고 클릭을 통해 도달한 경우 'cpc' (Cost Per Click) 값이 저장되게 된다. 주로 사용되는 값들은:
    "organic" (무료 검색 트래픽),
    "cpc" (유료 검색 트래픽),
    "referral" (다른 사이트를 통한 트래픽),
    "email" (이메일 마케팅을 통한 트래픽)
    CPM (Cost Per Mille): 광고 1,000회 노출에 따른 금액 책정
    등이 있다.

  • 현재 유저들이 어떠한 광고 캠페인에 관심을 두고 있는지, 그리고 어떠한 매체로 웹사이트에 접속하는지 직접적으로 확인하기 위해 trafficSource_campaigntrafficSource_medium 데이터로 시각화를 해봤다.

import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots


# 첫 번째 그래프 데이터
df_trafficSource_campaign = pd.DataFrame(df.groupby(df['trafficSource_campaign'])['totals_transactionRevenue'].mean()).reset_index()
df_trafficSource_campaign = df_trafficSource_campaign.dropna().sort_values("totals_transactionRevenue", ascending = True)

# 두 번째 그래프 데이터
df_device_category = pd.DataFrame(df.groupby(df['trafficSource_medium'])['totals_transactionRevenue'].mean()).reset_index()
df_device_category = df_device_category.dropna().sort_values("totals_transactionRevenue", ascending = True)

# 1x2 서브플롯 생성
fig = make_subplots(rows=1, cols=2, subplot_titles=('Transaction Revenue by trafficSource_medium', 'Transaction Revenue by trafficSource_campaign'))

# `Device Category` 그래프를 첫 번째 서브플롯에 추가 (수평 막대그래프로 변경)
fig.add_trace(
    go.Bar(x=df_device_category['totals_transactionRevenue'], y=df_device_category['trafficSource_medium'], orientation='h'),
    row=1, col=1
)

# `Device Browser` 그래프를 두 번째 서브플롯에 추가 (수평 막대그래프로 변경)
fig.add_trace(
    go.Bar(x=df_trafficSource_campaign['totals_transactionRevenue'], y=df_trafficSource_campaign['trafficSource_campaign'], orientation='h'),
    row=1, col=2
)

# 레이아웃 업데이트 및 출력
fig.update_layout(title_text="Transaction Revenue Analysis")
fig.show()

  • trafficSource_medium 방문자 도달 매체별 광고 수익에 대해 확인해보니 웹사이트 광고 1,000회 노출에 따른 금액 책정 CPM (Cost Per Mille) 이 가장 많은 것으로 나타난다. 다른 사이트를 통한 접속 방법인 referral, 'organic' 검색을 통한 사이트 접속, 광고 클릭 당 금액을 책정하는 유료 검색 트래픽인 cpc가 뒤를 이었다. 이를 통해 cpm 이외에 organiccpc의 유저 트래픽 수를 늘릴 효과적인 마케팅 전략을 수립해야 할 것으로 보인다.
  • trafficSource_campaign 광고 캠페인 이름 별 수익에 대해서 확인해보니 아직 정의되지 않은 광고 매체 이름이 가장 많은 것으로 나타났는데 이 데이터에 대한 확실한 정의가 필요해보인다. 그리고 AW-Accessories, AW - Dynamic Search Ads Whole SiteAW의 광고 캠페인을 보고 접속한 유저들의 구매가 많았다. 현재 잘하고 있는 AW의 광고 캠페인은 어떻게 더 유저들을 유입시킬 것인지 고도화 전략이 필요하며 나머지 광고 캠페인들에 대해서는 더 효과적인 마케팅 캠페인 전략을 세워야 할 것으로 보인다.


결론

  • 2016년 8월을 시작으로 10월, 11월에 유입된 고객이 가장 많고 이후 2016년 12월부터 다시 2016년 8월달의 고객 유입 수준까지 낮아졌다.

  • 하지만 12월 달 4월 달에는 수익이 증가한 모습을 보인다. 앞서 살펴봤던 MAU에서는 10월 달과 11월 달에 가장 많은 고객이 유입 됐지만 10월 달과 11월 달의 거래 수익이 많지 않았다.
    기존 totals_transactionRevenueNULL 값들이 상당히 많아 실제로 거래가 되지 않은 건지 또는 NULL 값이 많아 데이터가 수집이나 인풋이 되지 않았는지에 대한 것도 확인해 보아야 한다.

  • 구매 전환율을 확인해봤을 때에는 10월과 11월 달이 유입 고객이 많았던 것에 비해서 구매한 고객은 많이 없기 때문에 구매 전환율(conversion rate)도 떨어지는 것을 확인 가능했다.
    하지만 매출은 좀 떨어지고 있었지만 구매 전환율(conversion rate)은 2016년 12월 기점으로 점점 증가하고 있는 추세를 보이고 있다.

  • 구매 전환율도 높고 수익을 가져다주는 desktopFirefox 브라우저의 마케팅 캠페인 비용 비중을 늘려야 할 것으로 보이며 만약 mobile, tablet의 마케팅 캠페인 비용 비중이 감당이 되지 않는다면 비중을 줄여야 할 것으로 보인다.

  • 유저들의 국가별 위치별로 가장 많은 수익을 가져다주는 국가 및 대륙은 Eastern AfricaWestern Africa에서 이용한 유저로부터 대부분의 수익이 발생했으며 동일하게 Africa 대륙에서도 많은 수익이 발생한 것으로 보인다.
    이로써 주요 고객 국가인 Eastern AfricaWestern Africa 국가들의 마케팅 캠페인 비용 비중을 늘려야 할 것으로 보이며 이들의 구매 전환율을 높이는 것에 더 집중해야 할 것이다.

  • trafficSource_medium 방문자 도달 매체별 광고 수익에 대해 확인해보니 웹사이트 광고 1,000회 노출에 따른 금액 책정 CPM (Cost Per Mille) 이 가장 많은 것으로 나타난다. 다른 사이트를 통한 접속 방법인 referral, 'organic' 검색을 통한 사이트 접속, 광고 클릭 당 금액을 책정하는 유료 검색 트래픽인 cpc가 뒤를 이었다. 이를 통해 cpm 이외에 organiccpc의 유저 트래픽 수를 늘릴 효과적인 마케팅 전략을 수립해야 할 것으로 보인다.
  • trafficSource_campaign 광고 캠페인 이름 별 수익에 대해서 확인해보니 아직 정의되지 않은 광고 매체 이름이 가장 많은 것으로 나타났는데 이 데이터에 대한 확실한 정의가 필요해보인다. 그리고 AW-Accessories, AW - Dynamic Search Ads Whole SiteAW의 광고 캠페인을 보고 접속한 유저들의 구매가 많았다. 현재 잘하고 있는 AW의 광고 캠페인은 어떻게 더 유저들을 유입시킬 것인지 고도화 전략이 필요하며 나머지 광고 캠페인들에 대해서는 더 효과적인 마케팅 캠페인 전략을 세워야 할 것으로 보인다.
profile
데이터 분석 스쿨 블로그 입니다.

0개의 댓글