상현
개발 덕후

Today 위젯 구현

( 업데이트: )

📬 무엇을

네이버, 티스토리와 같이 대형 블로그들에 항상 위젯으로있는 투데이 관련 위젯

🤔 왜?

기본적으로 블로그에서 제공해주는 기능이었는데 어떻게 구현할까 궁금하고 직접 해보고싶다.

https://github.com/Hansanghyeon/Hansanghyeon/discussions/683

어떻게?

블로그에서 어떻게 방문자에 대한 데이터를 수집하고있나? GA(Google Analytics)로 방문자 데이터를 수집하고있다. 분명 today 위젯으로 방문자 수를 표현할때와 동일한 기능을 GA에서 하고있다고 생각한다. 그렇다면 이것을 활용해서 하는 것이 추후 블로그를 이전하거나 플랫폼을 변경해도 데이터에 문제가 없을 것이라 생각해서 GA의 방문자 데이터를 가져다 사용하는 것이 좋을 것같다 생각했다.

GA에서는 API를 통해서 프론트, 백엔드 여러가지 언어를 통해서 GA해당하는 데이터를 가져올 수 있다.

참고

GA의 문서가 잘되어있어서 필자는 모두 GA문서만 보고 구현했습니다.

Let’s go

Google Cloud Platform – 프로젝트 만들기

앞으로 Google Cloud Platform을 GCP라 축약해서 부르겠다.

PHP로 벡엔드에서 GA의 리포트 API를 사용하기위해서 인증절차가 필요하다(아무나 나의 데이터를 가져가면 안되니까) 그래서 GCP의 서비스 계정을 이용할 것이다.

서비스계정을 만들고 선택적 권한 목록은 아무것도 안들어가도 된다. 키를 다운받아 잘 보관한다.

키는 추후 벡엔드에서 사용할 것이다 필자는 키를 service-account-credentials.json로 저장하였다.

그리고 서비스 계정으로 인증을 완료하고 GA의 리포트 데이터를 가져오기 위해서 Google Analytics Reporting API를 활성화해준다. (GCP에서 검색으로 활성화)

GA에서 서비스 계정 권한 부여하기

GA의 visitor를 이용할만한 보고서에 서비스 계정 이메일을 유저로 추가해준다 필자는 애널리스트 권한으로 추가하였다.

속성의 다양한 보고서에 접근해서 데이터를 조합해야한다면 속성에 서비스 계정 이메일을 추가해주면 된다.

PHP Google Client사용하기

여기 퀵가이드를 보면서 따라했다.
하지만 GA의 개념을 잘 몰라서 어려웠던 것같다 리포트를 만들기 위해서는 Dimension과 Metric을 잘 이해하면 원하는 데이터를 어떻게 불러올지 전략적으로 사용할 수 있다.

더 자세한 내용은 공식문서를 참고하자.
나는 문서를 보면서 이해하기 어려워서 GA 리포트를 만드는 query 페이지를 통해서 무차별적으로 대입하면서 어떻게 사용해야할지 감을 잡았다.

cohort 사용 의도한 결과 실패 😭

처음에 today, allday, yesterday와 같이 여러가지 리포트를 가져와야해서 reports에서 여러가지를 같이 불러오는 것이라고 이해를 하고 cohort라는 리포트를 보게되었다. 이것은 and와 같이 여러개를 같이 보합해서 date range를 특정 구간구간만 보는 것이었는데 햇갈렸다.
2021-01-01 ~ 2021-01-31 and 2021-03-01 ~ 2021-03-31 두개를 한개의 리포트에서 보려할때 사용해야할 리포트였던 것이다.

<?php

public function cohortRequest(&$analyticsreporting)
{
    // Create the ReportRequest object.
    $request = new ReportRequest();
    $request->setViewId($this->VIEW_ID);

    $cohortDimension = new Dimension();
    $cohortDimension->setName("ga:cohort");

    $acquisitionTrafficChannel = new Dimension();
    $acquisitionTrafficChannel->setName("ga:acquisitionTrafficChannel");

    // Set the cohort dimensions
    $request->setDimensions(array($cohortDimension, $acquisitionTrafficChannel));

    $cohortActiveUsers = new Metric();
    $cohortActiveUsers->setExpression("ga:cohortActiveUsers");

    // Set the cohort metrics
    $request->setMetrics(array($cohortActiveUsers));

    $dateRange1 = new DateRange();
    $dateRange1->setStartDate("2017-07-22");
    $dateRange1->setEndDate("today");

    // Create the first cohort
    $cohort1 = new Cohort();
    $cohort1->setName("cohort_1");
    $cohort1->setType("FIRST_VISIT_DATE");
    $cohort1->setDateRange($dateRange1);

    $dateRange2 = new DateRange();
    $dateRange2->setStartDate("today");
    $dateRange2->setEndDate("today");

    // Create the second cohort which only differs from the first one by the date range
    $cohort2 = new Cohort();
    $cohort2->setName("cohort_2");
    $cohort2->setType("FIRST_VISIT_DATE");
    $cohort2->setDateRange($dateRange2);

    // Create the cohort group
    $cohortGroup = new CohortGroup();
    $cohortGroup->setCohorts(array($cohort1, $cohort2));

    $request->setCohortGroup($cohortGroup);

    // Create the GetReportsRequest object.
    $getReport = new GetReportsRequest();
    $getReport->setReportRequests(array($request));

    // Call the batchGet method.
    $body = new GetReportsRequest();
    $body->setReportRequests(array($request));
    $response = $analyticsreporting->reports->batchGet($body);

    // printResults($response->getReports());
    return $response->getReports();
}Code language: HTML, XML (xml)

VisitorCounter.php

단일 조건으로 가져오는 리포트를 여러번 불러오는 것이 맞는 것같아서 아래와 같이 구성했다.

<?php

namespace App\View\Components;

use Google_Client;
use Roots\Acorn\View\Component;

use Google\Service\AnalyticsReporting;
use Google\Service\AnalyticsReporting\DateRange;
use Google\Service\AnalyticsReporting\Metric;
use Google\Service\AnalyticsReporting\ReportRequest;
use Google\Service\AnalyticsReporting\GetReportsRequest;
use Google\Service\AnalyticsReporting\Dimension;

class VisitorCounter extends Component
{
    public $VIEW_ID = "246095399";

    public $analytics;
    public $today;
    public $allday;
    public $yesterday;

    public function initializeAnalytics()
    {
        $KEY_FILE_LOCATION = get_theme_file_path('/key/service-account-credentials.json');

        // Create and configure a new client object.
        $client = new Google_Client();
        $client->setApplicationName("방문자 카운터");
        $client->setAuthConfig($KEY_FILE_LOCATION);
        $client->setScopes(['https://www.googleapis.com/auth/analytics.readonly']);
        $this->analytics = new AnalyticsReporting($client);
    }

    public function getReport($startDate = 'today', $endDate = 'today')
    {
        // Create the DateRange object.
        $dateRange = new DateRange();
        $dateRange->setStartDate($startDate);
        $dateRange->setEndDate($endDate);

        // Set the dimensions
        $dimension = new Dimension();
        // $dimension->setName("ga:visitorType");
        $dimension->setName("ga:userType");

        // Create the Metrics object.
        $sessions = new Metric();
        // $sessions->setExpression("ga:visitors");
        <meta charset="utf-8">$sessions->setExpression("ga:users");

        // Create the ReportRequest object.
        $request = new ReportRequest();
        $request->setViewId($this->VIEW_ID);
        $request->setDateRanges($dateRange);
        $request->setMetrics(array($sessions));
        $request->setDimensions(array($dimension));

        $body = new GetReportsRequest();
        $body->setReportRequests(array( $request));
        $response = $this->analytics->reports->batchGet($body);
        return $response[0]['data']['totals'][0]['values'][0];
    }

    public function __construct()
    {
        $this->initializeAnalytics();
        $this->allday = $this->getReport('2017-07-22', 'today');
        $this->today = $this->getReport();
        $this->yesterday = $this->getReport('yesterday', 'yesterday');
    }
    public function render()
    {
        return $this->view('components.visitor-counter');
    }
}Code language: HTML, XML (xml)

visitor에서 users

기존에 ga query에서 visitor를 사용했다. 이전에는 ga에 대해서 정확하게 잘 몰랐기 때문에 visitor라 해서 단순 방문자구나? 그렇게 생각하고 해당 쿼리로 가져왔던 것이다.

그래서 ga:visitorsga:users로 변경하였다.

이 제품 변경은 계정 설정 방식과 수집하고 Google 애널리틱스로 보내는 데이터의 종류에 따라 다양한 방식으로 영향을 미칠 수 있습니다.

방문자 웹 측정항목과 활성 사용자 앱 측정항목이 이제 사용자라는 동일한 이름으로 통합되었습니다. 그리고 이제 모든 Google 애널리틱스에서 방문을 세션이라고 합니다. 오늘부터 이러한 변경 사항을 적용하고 다음 주에 점진적으로 배포할 예정입니다.

웹 및 앱 조회수를 모두 수집하여 Google 웹로그 분석 계정의 한 속성으로 보내는 경우 오늘부터 모든 조회수가 모든 보고 보기에 표시됩니다. 웹 데이터와 앱 데이터를 별도로 유지하려면 보고 보기에 필터를 추가해야 합니다.

웹 및 앱 데이터를 계정의 동일한 속성으로 보내지 않으면 데이터가 동일하게 유지됩니다.

그러나 모든 사용자는 보고서에서 통합 측정항목, 측정기준 및 세그먼트 이름을 볼 수 있습니다.

오늘날까지 일부 측정항목과 측정기준은 앱 보기와 웹 보기에서 완전히 동일한 데이터를 표시했음에도 불구하고 다른 이름을 사용했습니다. 이제 웹 또는 앱 데이터에 사용되는지 여부에 관계없이 모든 측정항목, 측정기준 및 세그먼트 이름이 동일합니다. 이를 통해 모든 Google Analytics 데이터를 분석하고 참조할 수 있는 명확하고 일관된 방법을 얻을 수 있습니다.