Skip to content

Latest commit

 

History

History
356 lines (289 loc) · 12.1 KB

README-CLOUD-FUNCTION.md

File metadata and controls

356 lines (289 loc) · 12.1 KB

Configuração com o uso da Cloud Function

Para enviar os dados dos eventos para o Big Query utilizando Cloud Functions é necessário realizar os passos a seguir:

  • Criação de dataset e tabela no Big Query;
  • Criação de Cloud Function;
  • Adequação do custom template para envio de requisições para a Cloud Function.

Criação de dataset e tabela no Big Query

Para criar a tabela acesse o GCP (Google Cloud Plataform) e crie um dataset com o nome dp6_media_quality e uma tabela com o nome media-quality-raw.

As colunas criadas na tabela são:

Nome da Coluna Descrição
client_id Client id do Google Analytics
media_name Nome da mídia que foi disparada
tracking_id Id de acompanhamento da mídia disparada
media_event Nome do evento disparado
tag_name Nome completo da tag disparada no GTM
status Status de disparo da tag
datalayer_event Nome do evento do DataLayer que acionou a tag
timestamp Data e hora do registro

Ao criar a tabela selecione a opção para realizar o particionamento diário dos dados utilizando a coluna timestamp. O código abaixo contém um JSON com o esquema da tabela criada.

// Esquema da tabela criada no Big Query
[
  {
    name: 'client_id',
    type: 'STRING',
    mode: 'NULLABLE',
    description: 'Client id do Google Analytics',
    maxLength: '100',
  },
  {
    name: 'media_name',
    type: 'STRING',
    mode: 'NULLABLE',
    description: 'Nome da midia que foi disparada',
    maxLength: '100',
  },
  {
    name: 'tracking_id',
    type: 'STRING',
    mode: 'NULLABLE',
    description: 'Id de acompanhamento da midia disparada',
    maxLength: '100',
  },
  {
    name: 'media_event',
    type: 'STRING',
    mode: 'NULLABLE',
    description: 'Nome do evento disparado',
    maxLength: '100',
  },
  {
    name: 'tag_id',
    type: 'STRING',
    mode: 'NULLABLE',
    description: 'ID da tag disparada no GTM',
    maxLength: '100',
  ,{
    name: 'tag_name',
    type: 'STRING',
    mode: 'NULLABLE',
    description: 'Nome completo da tag disparada no GTM',
    maxLength: '100',
  },
  {
    name: 'status',
    type: 'STRING',
    mode: 'NULLABLE',
    description: 'Status de disparo da tag',
    maxLength: '50',
  },
  {
    name: 'datalayer_event',
    type: 'STRING',
    mode: 'NULLABLE',
    description: 'Nome do evento do DataLayer que acionou a tag',
    maxLength: '100',
  },
  {
    name: 'timestamp',
    type: 'TIMESTAMP',
    mode: 'REQUIRED',
    description: 'Data e hora do registro',
  },
];

Criação de Cloud Function

Para criar a Cloud Function acesse o GCP (Google Cloud Plataform) e utilize código diponibilizado abaixo (index.js e package.json). Foram utilizados Runtime: Node.js 16 e Entry point: gtm_monitor. É importante verificar se a Cloud Function está acessível, portanto, verifique a secção Permissions para habilitar as permissões necessárias. Para a criação da function foram usados os arquivos index.js e package.json.

A function recebe uma requisição HTTP que pode conter dados em JSON ou uma URL com query params. Para selecionar uma das opções é preciso alterar o valor da constante input_option localizada nas primeiras linhas de código (no arquivo index.js).

Os dados em formato JSON recebidos pela function estão no seguinte formato:

{
    "client_id": "1101944939.1645464696"
    "media_name": "media_name",
    "tracking_id": "123",
    "media_event": "media_event",
    "tag_id": "3"
    "tag_name": "tag_name",
    "status": "status",
    "datalayer_event": "datalayer_event",
    "timestamp": 1652359111.576
}

Caso os dados recebidos pelo Cloud Function seja uma URL ela será do seguinte formato:

https://{{URL da Cloud Function}}/?client_id={{client_id}}&media_name={{media_name}}&tracking_id={{tracking_id}}&media_event={{media_event}} ...

As informações provenientes da URL são organizadas em um dicionário após a extração por meio de expressões regulares. Posteriormente os dados são enviados para o Big Query.

index.js

// Import the Google Cloud client library
const { BigQuery } = require('@google-cloud/bigquery');
const bigquery = new BigQuery();
// Request origin allowed in cloud function
var request_origin = process.env.REQUEST_ORIGIN;
request_origin = request_origin.split(',');

// Select what kind of data req.body contains. If the data
// comes from sendPixel method (used on GTM custom template) use "url" else use "json"
const input_option = 'json'; // url ou json

async function insertRowsAsStream(request, input_option) {
  const datasetId = 'dp6_media_quality';
  const tableId = 'media-quality-raw';
  var json_data;
  var json_data_raw;

  if (input_option == 'url') {
    const url = decodeURI(request.protocol + '://' + request.get('host') + request.originalUrl);

    json_data = {
      client_id: url.match('client_id=([^&]+)')[1],
      media_name: url.match('media_name=([^&]+)')[1],
      tracking_id: url.match('tracking_id=([^&]+)')[1],
      media_event: url.match('media_event=([^&]+)')[1],
      tag_id: url.match('tag_id=([^&]+)')[1],
      tag_name: url.match('tag_name=([^&]+)')[1],
      status: url.match('status=([^&]+)')[1],
      datalayer_event: url.match('datalayer_event=([^&]+)')[1],
      timestamp: Date.now() / 1000,
      page: url.match('page=([^&]+)')[1],
      container_version: url.match('container_version=([^&]+)')[1],
    };
  }

  if (input_option == 'json') {
    try {
      // Parse a JSON
      json_data_raw = JSON.parse(request.body);
    } catch (e) {
      json_data_raw = request.body;
    }

    json_data_raw['timestamp'] = Date.now() / 1000;

    lst_allowed_fields = [
      'client_id',
      'media_name',
      'tracking_id',
      'media_event',
      'tag_id',
      'tag_name',
      'status',
      'datalayer_event',
      'timestamp',
      'page',
      'container_version',
    ];
    json_data = Object.fromEntries(Object.entries(json_data_raw).filter(([key]) => lst_allowed_fields.includes(key)));
  }

  // Insert data into a table
  await bigquery.dataset(datasetId).table(tableId).insert(json_data);
}

exports.gtm_monitor = (req, res) => {
  if (req.body && request_origin.includes(req.headers.origin)) {
    insertRowsAsStream(req, input_option);
    res.sendStatus(200);
  } else {
    console.log('Requisição inválida. Verifique o payload ou a variável REQUEST_ORIGIN...');
    res.sendStatus(403);
  }
};

package.json

{
    "name": "dp6-cf-media-quality",
    "version": "1.0.0",
    "description": "envia dados para o bigquery atraves de cloud function",
    "author": "dp6",
    "dependencies": {
      "@google-cloud/bigquery": "^2.1.0"
    },
    "license": "ISC"
  }

Adequação do custom template para envio de requisições para a Cloud Function

Existem duas maneiras de enviar os dados para a Cloud Function, uma utilizando o método sendPixel e a outra utizando Fetch.

Opção 1: sendPixel

O sendPixel é utilizado para realizar requisições do tipo GET. Ela recebe como parâmetro uma URL que é composta por URL = endpoint + query params. O endpoint é a URL da Cloud Function enquanto que os query params contém os dados de mídia que serão enviados para a Cloud Function.

Opção 2: Fetch

O fetch permite realizar requisições do tipo POST e o envio de dados no formato JSON. No GTM deve-se criar uma variável do tipo custom javascript e inserir a função responsável pela requisição. Na tag do GTM o campo sendFetchReference deve ser preenchido com a variável criada.

Código javascript utilizado no template de Media Quality (GTM)

...

const encodeUri = require('encodeUri');
const sendPixel = require('sendPixel');
const sendRequestFetch = data.sendFetchReference;

...
function sendToCF(method) {

    const endpoint = data.cfEndpoint;
    const event = readFromDataLayer('event');
    const fetch = data.fetchReference;

    addEventCallback(function(containerId, eventData) {

        const tagData = eventData.tags.filter(t => t.exclude === 'false');
        for (let i in tagData) {

            let entry = tagData[i];
            let body = {
                client_id: data.clientId,
                media_name: data.autoCollect ? entry.media_name : entry.name.split(' - ')[0].split(' (')[0],
                tracking_id: entry.tracking_id,
                media_event: data.autoCollect ? entry.media_event : entry.name.split(' - ')[1],
                tag_name: entry.name,
                status: entry.status,
                datalayer_event: event
            };
            for (let j in data.params) {
                let name = data.params[j].param;
                let value = data.params[j].value;
                body[name] = value;
            }

            //Send data via GET method
            if (method == 'get') {
                var url = "";
                for (let item in body) {
                    url += '&' + item + '=' + body[item];
                }
                url = endpoint+ "/?" + encodeUri(url);
                sendPixel(url,null,null);
            }
            //Send data via POST method
            else if (method == 'post') {
                fetch(endpoint, body);
            }
        }
    });
}

...

Função Fetch (utilizada na custom javascript variable do GTM)

function(){
  function CustomFetch(endpoint, payload){
    fetch(endpoint, {
    method: "POST",
    mode: 'no-cors',
    body: JSON.stringify(payload),
    headers: {'Content-Type': 'application/json'}
    });
  }
  return CustomFetch;
}

Imagens da Implementação da Cloud Function

Para criar a Cloud function acesse o console do Google Cloud e clique em Create Function (Figura 1).

Figura 1 - Preenchimento do campo Endpoint com URL da Cloud Function

Na etapa de configuração selecione Allow unauthenticated invocations e marque Require HTTPS

Figura 2 - Preenchimento do campo Endpoint com URL da Cloud Function

Crie uma variável de ambiente com o nome REQUEST_ORIGIN e adicione as URLs das página web separadas por vígula (ex.: https://dp6.com.br,https://dp6.github.io). A Cloud Function apenas será disparada se a requisição for proveniente dos sites listados na variável REQUEST_ORIGIN.

Figura 3 - Preenchimento do campo Endpoint com URL da Cloud Function

Na aba de permissões, allUsers deve possuir o papel Cloud Functions Invoker

Figura 4 - Preenchimento do campo Endpoint com URL da Cloud Function

Imagens da Implementação no GTM

Passo 1: Criação da variável javascript

Criação de variável javascript com o código responsável pelas requisições HTTP. Caso seja utilizada a outra forma de envio de dados (sendPixel) não é necessário criar essa variável.

Figura 5 - Criação de custom javascript com a função fetch.

Passo 2: Configuração da TAG no GTM

Após habilitar na tag o "Endpoint de destino" como Cloud Function deve-se inserir a URL de trigger da Cloud Function, a variável javascript criada anteriormente e um segredo (é o secret da cloud function) a ser adicionado na requisição HTTP, conforme o exemplo abaixo (Figura 2).

Figura 6 - Preenchimento do campo Endpoint com URL da Cloud Function