brunch

You can make anything
by writing

C.S.Lewis

by 발모어책방 Apr 23. 2022

GA4 데이터 수집 시 PII 제거하기

모든 데이터가 가치 있는 것은 아니다

앞서 언급했듯이 PII (Personally Identifiable Information)는 구글이 데이터 수집 시 금지하고 있다. 구글 애널리틱스 뿐만 아니라 구글 Ads, SA360, DV360, CM 등 GMP의 모든 툴들에서 공통적으로 적용이 되는 부분이다. 이를 위반할 시 구글은 Terms & Condition을 위반하는 것으로 간주하고 account를 임의로 삭제할 수 있다. 개인정보보호가 강화되는 추세 속에서 이런 data hygeine은 아무리 강조해도 지나치지 않다.


기존 GA classic (Universal Analytics)의 경우 PII Audit을 통해 PII의 패턴을 파악했다면, 예방적인 조치를 취할 수 있다. 가장 보편적인 방법은 customTask를 통해 GA hit payload에서 특정 패턴의 데이터, querystring parameter를 삭제하고 hit을 GA 서버로 보내는 방법이다. 가장 유명한 것은 Simo가 소개한 방법이고 이를 customise한 여러 가지 script들이 존재한다. 예를 들면 아래와 같이 문제가 되는 querystring parameter value들을 무조건 삭제하는 방법도 있다.


function() {

  return function(model) {

    // Regex patterns for PII redaction.

    var piiRegex = [{

      // Always redact these query parameters.

      find: /\b(querystring_with_PII)=([^&]+)\b/gi,

      replacement: "$1=[REDACTED]"

    }]

    var globalSendTaskName = '_' + model.get('trackingId') + '_sendHitTask';

    // Fetch reference to the original sendHitTask

    var originalSendTask = window[globalSendTaskName] = window[globalSendTaskName] || model.get('sendHitTask');

    var i, hitPayload, parts, val;

    // Overwrite sendHitTask with PII purger

    model.set('sendHitTask', function(sendModel) {

      hitPayload = sendModel.get('hitPayload').split('&');

      for (i = 0; i < hitPayload.length; i++) {

        parts = hitPayload[i].split('=');

        // Double-decode, to account for web server encode + analytics.js encode

        try {

          val = decodeURIComponent(decodeURIComponent(parts[1]));

        } catch(e) {

          val = decodeURIComponent(parts[1]);

        }

        piiRegex.forEach(function(pii) {

          val = val.replace(pii.find,pii.replacement);

        });

        parts[1] = encodeURIComponent(val);

        hitPayload[i] = parts.join('=');

      }

      sendModel.set('hitPayload', hitPayload.join('&'), true);

      originalSendTask(sendModel);

    });

  };

}


이 custom JavaScript variable을 아래와 같이 GA setting variable에 넣으면 모든 payload에서 위 패턴만 찾아 삭제 후 나머지 payload를 그대로 보내게 된다.


문제는 customTask가 아직 GA4를 지원하지 않는 것이다. 따라서 David Vallejo는 sendBeacon을 이용해서 payload를 customTask와 같은 functionality로 삭제하는 방법에 대해 소개하기도 했다. 다만 이는 David이 스스로 언급했듯이 이상적이지 않다. browser의 sendBeacon을 이용하기 때문에 이 script에 문제가 있을 때는 같은 페이지 내 다른 sendBeacon을 이용하는 script까지 다 error를 일으키기 때문이다.


따라서 현재로서 가장 안전하며 강력한 solution은 아래와 같이 문제가 되는 querystring parameter들을 page_location에서 제외하고 hit을 GA4로 보내는 방법이다.


function() {

  //Update params with queries to be removed from URL

  var params = ['querystring_with_PII'];

  var a = document.createElement('a');

  var param,

      qps,

      iop,

      ioe,

      i;

  a.href = {{Page URL}};

  if (a.search) {

    qps = '&' + a.search.replace('?', '') + '&';

    for (i = 0; i < params.length; i++) {

      param = params[i];

      iop = qps.indexOf('&' + param + '=');

      if(iop > -1) {

        ioe = qps.indexOf('&', iop + 1);

        qps = qps.slice(0, iop) + qps.slice(ioe, qps.length);

      }

    }

    a.search = qps.slice(1, qps.length - 1);   

  }

  return a.href;

}


이런 custom JavaScript을 GA config tag에서 page_loation field에 세팅해주면, 해당 querystring parameter만 제외하고 데이터를 수집하게 된다. 이는 PII가 analyst가 통제할 수 없는 URL 중 querystring parameter를 통해 수집된다는 점에 기인하고, 나머지 event는 analyst 스스로가 문제가 되는 variable을 수집하지 않는다는 전제에 효과적이다.


이에 customTask 같은 솔루션이 GA4 등장하기 전에 중요한 것은 GA4 event 수집  custom parameter {{Page URL}} 넣지 않는 것이다. 많은 회사가 GA classic에서 Event Label {{Page URL}} 수집하는 경우가 있는데, 이것은 best practice 아니다. 그리고  많은 경우, PII 같은 원치 않는 데이터를  하나의 dimension 수집하는 문제를 야기한다. 따라서 데이터를 수집하는 analyst 스스로 data hygeine 대한 문제의식을 가지고, 필요한 데이터만 수집하는 것이 중요하다.


너무 아무도 안 궁금한(?) 개인적인 이야기만 쓰는 것 같이 technical한 걸 하나 써야겠다 생각해서 썼는데 30분 만에 써서 기분이 좋다. 내 이야기를 쓰는 건 며칠이 걸리고 이런 건 뚝딱 쓰니, 확실히 성향이 변한 것 같기도...

나는 세상에 필요하다 나는 세상에 필요하다 나는 세상에 필요하다
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari