El artículo que muestro a continuación es la traducción del que hice en inglés y que me publicaron el día 26 de abril en el conocido website Oncrawl especializado en SEO. Puedes buscarlo en Google fácilmente 😉 Empezamos …

Entendiendo la implementación propuesta

En cualquier estrategia enfocada a la optimización de motores de búsqueda (SEO) el análisis de los datos es esencial. Cada vez hay más especialistas en este ámbito que optan por desarrollarse en torno al análisis del tráfico de búsqueda orgánico (organic search), el cual de por si tiene un comportamiento y particularidades muy diferentes al resto: paid search, email, organic social, direct, etc. En este sentido y gracias a la gran variedad de herramientas disponibles en la actualidad, este tipo de estudios ha conseguido evolucionar hasta un grado impensable años atrás. Esto se debe principalmente a la aparición de nuevas metodologías y desarrollos que han permitido que podamos generar modelos analíticos abstrayéndonos de utilizar complicadas operaciones matemáticas. Tenemos la suerte de tener a nuestra disposición técnicas y algoritmos ya testados y listos para comenzar a trabajar con ellos. En el caso de lo que a continuación se va a tratar en este artículo, nos vamos a centrar en la creación de un modelo predictivo para un conjunto de datos de una serie temporal donde la tendencia calculada se ajusta a la estacionalidad y la periodicidad previa. Más concretamente, predecir el tráfico de búsqueda orgánico de nuestra propiedad de Google Analytics 4 (de ahora en adelante GA4). Son muchas las opciones para poder llevarlo a cabo, sin embargo, en este caso he optado por realizar el desarrollo íntegramente en Python.

El script sobre el que se basa este artículo consta de tres partes claramente diferenciadas:

  • Extracción de datos. Cómo utilizar la nueva API de GA4 paso a paso para recoger el tráfico de búsqueda orgánico.
  • Modelado de datos. Utilización de Prophet, la librería open source de Facebook para realizar predicciones de series temporales.
  • Visualización de datos. Mostrar los cambios de tendencia y la predicción modelada.

Extracción de datos de GA4 a través de su API usando Python

Lo primero que debemos saber cuando nos enfrentamos a Google Analytics Data API (GA4) es su estado de desarrollo. Tal y como detalla Google en su página, actualmente se encuentra en una versión en fase temprana. Concretamente, a fecha en que se ha redactado este artículo, sería la fase Beta.

Cabe recordar que GA4 fue publicado el 14 de octubre de 2020. Apenas han pasado unos meses. De hecho, quienes ya tuvieran una propiedad Universal Analytics y creen una nueva de tipo GA4, van a poder seguir usándola en paralelo sin restricción alguna como hasta ahora. No se sabe con certeza cuando dejará de funcionar. En cualquier caso, mi recomendación es crear cuanto antes una nueva propiedad de tipo GA4. De esta forma tendremos un histórico de datos más amplio. También se debe tener en cuenta que cada día que pasa GA4 integra nuevas funcionalidades o mejora las ya existentes. En estos momentos se encuentra en constante evolución.

A causa de esto, lógicamente podrán llegar a darse pequeños cambios en el código a continuación descrito. Aunque con seguridad, serán mínimos. Valga como ejemplo, nimiedades tales como el cambio de nombre del campo entity (fase Alpha) por property (fase Beta) dentro de la clase RunReportRequest().

Lo primero y esencial, antes de construir la llamada a la API, es entender qué elementos están disponibles. Básicamente se trata de seguir la siguiente estructura …

Tipos de objetos de RunReportRequest de la GA4 Data v1 Beta API

Tipos de objetos de RunReportRequest de la GA4 Data v1 Beta API.

A simple vista es bastante intuitivo, aunque la realidad es otra bien distinta. Para poder realizar las llamadas es necesario tener siempre a mano al menos la siguiente documentación:

Esto se debe simplemente a que los nombres de los campos varían levemente con respecto a la documentación oficial, la cual representa los campos en formato JSON. Un ejemplo es el campo fieldName de la clase Filter. En Python deberemos describirlo como field_name. Por norma general siempre será pasar de un campo tipo camel case a uno snake case.

Antes de continuar, detengámonos un instante para inicializar nuestro proyecto. Como en la gran mayoría de casos a la hora de desarrollar scripts en Python, hemos de dedicarle un tiempo a la importación de las librerías necesarias y la preparación del entorno de ejecución.

  1. Crear un nuevo proyecto en Python. En este caso se ha utilizado el software PyCharm.
  2. Habilitar Google Analytics Data API en Google Cloud Platform y descargar el archivo de la cuenta de servicio creada (tipo JSON) y guardarlo en la carpeta donde se haya creado el proyecto de Python. Al abrir este archivo se ha de copiar el valor del campo client_email, el cual será algo parecido a nombre-correo@project-id.iam.gserviceaccount.com.
  3. Añadir este valor del client_email a la propiedad de GA4 de donde se extraerán los datos. Concretamente en el apartado de gestión de usuarios. Al menos habrá que otorgarle el nivel de permisos ‘Lectura & Análisis’.
  4. A través de la terminal del cliente (PyCharm) instalar en el directorio del proyecto la librería de Google Analytics Data con la que se harán las llamadas a la API …
pip install google-analytics-data

A partir de aquí ya solo falta crear la llamada, la cual como se puede ver a continuación consta básicamente de tres partes (client, request y response), y visualizar o guardar los datos recogidos.

Código Python para hacer una request simple a GA4

Código Python para hacer una request simple a GA4.

Cualquier dimensión, métrica, filtro, orden de los datos, rango de fechas, etc. que se añada a la variable request deberá agregarse como una clase (ver imagen previa “Tipos de objetos de RunReportRequest”) vinculada a una variable (metrics=[Metric(..)]). Esto facilita mucho la manera de entender la estructura de los datos a recoger. En este sentido, por cada clase del nivel más alto se debe realizar una importación específica. Es decir, si se desea añadir una dimensión y una métrica para un rango de tiempo concreto se requerirá al menos lo siguiente …

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

Lógicamente también cabe la posibilidad de añadir valores concretos a determinadas variables (name=’eventCount’). Por ello es esencial entender e interiorizar la documentación previamente descrita.

Además de esto, se debe prestar especial atención a la variable os.environ[“GOOGLE_APPLICATION_CREDENTIALS”], la cual contendrá el path al fichero descargado previamente en el paso 2. Esta línea de código nos va a evitar algunos problemas a la hora de gestionar los permisos a la API de Google.

Si el código se ha ejecutado correctamente, se verá un resultado con un aspecto similar a este: {Date, Events}, {20210418, 934}, {…}, …

Predicción de datos a través de Facebook Prophet

Hoy en día son muchas las opciones existentes y gratuitas para llevar a cabo cualquier tipo de predicción basada en el histórico de nuestros datos. En este caso específico he optado por la librería Prophet, pero ¿qué es realmente?

Es una librería open-source (R y Python) creada por el equipo Data Science de Facebook para estimar el comportamiento de un conjunto de datos de una serie temporal basándose en un modelo aditivo donde las tendencias no-lineales se ajustan a una estacionalidad diaria, semanal y anual teniendo en cuenta los efectos de los días de vacaciones.

Volviendo sobre la implementación propuesta (predicción de tráfico de búsqueda orgánico), lo primero será instalar las siguientes librerías:

  • Pandas (pip install pandas). Maneja y análisis de estructuras de datos.
  • Plotly (pip install plotly). Creación de gráficos de todo tipo.
  • Prophet (conda install -c conda-forge fbprophet -y).

Después, como siempre, se deberá llevar a cabo las importaciones asociadas a dichas librerías. Tras esto solo queda realizar la modelización de la predicción y su correspondiente visualización. Para ello, en el caso de Prophet únicamente se ha de seguir este proceso:

  1. Inicializar un nuevo objeto Prophet con los atributos deseados para generar la predicción.
  2. Llamar al método fit pasándole los datos extraídos de GA4 como dataframe. Esta llamada puede llegar a tardar en algunos casos varios segundos. El dataframe con los datos recogidos debe estar conformado únicamente por dos columnas cuyos nombres son siempre los mismos: ds (campo de tipo fecha) e y (métrica a estudiar).
  3. Crear un nuevo dataframe a futuro estableciendo el número de períodos hasta donde debería alcanzar la predicción a partir del rango de fechas seleccionadas y la frecuencia con que se agregarán los datos (weekly, monthly, etc.)
  4. Llamar al método predict, el cual asignará a cada fila del nuevo dataframe a futuro un valor predicho (yhat).
  5. Llamar al método plot para poder visualizar las predicciones generadas.

Llamar al método plot_components el cual ayuda a entender de manera visual la tendencia y la estacionalidad de los datos.

m = Prophet()
m.fit(df)future = m.make_future_dataframe(periods=365)
forecast = m.predict(future)
m.plot(forecast)
m.plot_components(forecast)

Aunque en tan solo seis pasos se ha generado la predicción deseada y parece algo relativamente sencillo, se han de tener en cuenta varios elementos que serán claves para generar la predicción de una u otra forma. Al final se trata de generar una predicción que se amolde a la lógica, en el caso de este artículo, de nuestro tráfico de búsqueda orgánico. Para ello es necesario entender algunas configuraciones algo más avanzadas de Prophet.

  • Días especiales y vacaciones. Existe la posibilidad de añadir días especiales con la intención de que estos no influyan en la predicción a generar.
  • Se han de eliminar en caso de que afecten a la estimación.
  • Detección de cambios de tendencia a lo largo del tiempo analizado.
  • Diagnóstico. Validación basada en la medición del error de predicción según el estudio histórico de los datos.
  • Selección entre lineal o logístico.
  • Elección entre aditiva o multiplicativa.

Todo esto y muchas más opciones se detallan a la perfección en esta documentación de la librería Prophet.

Creando el script completo para poder visualizar la predicción de tráfico

Ya solo queda unir todas las piezas del puzzle en un único script. Lo habitual para acometer este tipo de rompecabezas es crear una función para cada uno de los procesos detallados previamente, de tal forma que estas puedan ser ejecutadas de manera ordenada y limpia tal que así:

def ga4(property_id, start_date, end_date):
[…]
def forecasting(dim, met, per, freq): […]
if __name__ == "__main__":
dimension, metric = ga4(PROPERTY_ID, START_DATE, END_DATE)
forecasting(dimension, metric, PERIODS, FREQ)

Antes de visualizar el resultado final de la predicción es oportuno observar el tráfico de búsqueda orgánico analizado. En un primer vistazo se puede ver cómo las diferentes estrategias y las acciones realizadas han ido surgiendo efecto a lo largo del tiempo. A distinción de otros canales (por ejemplo, campañas de Paid Search), el tráfico generado desde Organic Search suele tener pocas oscilaciones apreciables (valles o picos). Suele crecer o disminuir paulatinamente a lo largo del tiempo e influido a veces por hechos estacionales. Las fluctuaciones habitualmente apreciables suelen estar asociadas a actualizaciones en el algoritmo del motor de búsqueda (Google, Bing, etc.).  

El resultado final del script se puede observar en las siguientes imágenes donde se detallan factores tan importantes como: la tendencia, la estacionalidad, la predicción o la frecuencia de los datos.

Si analizamos la predicción obtenida, se podría concluir de manera genérica que “continuando con la misma estrategia SEO puesta en marcha hasta la fecha, el tráfico desde motores de búsqueda seguirá creciendo paulatinamente”. Podemos asegurar que “nuestros esfuerzos mejorando el rendimiento del sitio web, generando contenido de calidad, proveyendo enlaces relevantes, etc. han merecido la pena”.

Visualización de la tendencia, la estacionalidad y la predicción del tráfico orgánico recogido.

Visualización de la tendencia, la estacionalidad y la predicción del tráfico orgánico recogido.

Para concluir, te comparto el código en su totalidad para que únicamente tengas que copiarlo y ejecutarlo en tu IDE (Entorno de Desarrollo Integrado) de Python. Lógicamente se deben haber instalado todas las librerías anteriormente mencionadas.

import pandas as pd
import fbprophet
from fbprophet import Prophet
from fbprophet.plot import add_changepoints_to_plot
import matplotlib.pyplot as plt
import os

from google.analytics.data_v1beta import BetaAnalyticsDataClient from google.analytics.data_v1beta.types import DateRange from google.analytics.data_v1beta.types import Dimension from google.analytics.data_v1beta.types import Metric from google.analytics.data_v1beta.types import Filter from google.analytics.data_v1beta.types import FilterExpression from google.analytics.data_v1beta.types import FilterExpressionList from google.analytics.data_v1beta.types import RunReportRequestPROPERTY_ID = '[Add here the GA4 property_id]'
START_DATE = '2020-01-01' END_DATE = '2021-03-31' PERIODS = 4 FREQ = 'M'os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "[Add here the path of the json file with the credentials]"

def ga4(property_id, start_date, end_date):
      client = BetaAnalyticsDataClient()

      request = RunReportRequest(property='properties/' + property_id,       dimensions=[Dimension(name='date')],       metrics=[Metric(name='eventCount')],       date_ranges=[DateRange(start_date=start_date, end_date=end_date)],       dimension_filter=FilterExpression( and_group=FilterExpressionList(expressions=[ FilterExpression(filter=Filter(field_name='sessionDefaultChannelGrouping', string_filter=Filter.StringFilter( value='Organic Search', match_type=Filter.StringFilter.MatchType( 1)))), FilterExpression(filter=Filter(field_name='eventName', string_filter=Filter.StringFilter( value='session_start', match_type=Filter.StringFilter.MatchType( 1)))) ])) )

      response = client.run_report(request)

      x, y = ([] for i in range(2))       for row in response.rows:             x.append(row.dimension_values[0].value)             y.append(row.metric_values[0].value)             print(row.dimension_values[0].value, row.metric_values[0].value)

      return x, y

def forecasting(x, y, p, f):       print('Prophet %s' % fbprophet.__version__)data = {'ds': x, 'y': y}       df = pd.DataFrame(data, columns=['ds', 'y'])

      m = Prophet(growth='linear', changepoint_prior_scale=0.5, seasonality_mode='additive', daily_seasonality=False, weekly_seasonality=True, yearly_seasonality=True, holidays=None, )
      m.fit(df)       future = m.make_future_dataframe(periods=p, freq=f)       forecast = m.predict(future)
      print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].head())
      fig = m.plot(forecast, xlabel='Date', ylabel='Visits')       add_changepoints_to_plot(fig.gca(), m, forecast)       m.plot_components(forecast)       plt.show()

if __name__ == "__main__":       channel_group, event_count = ga4(PROPERTY_ID, START_DATE, END_DATE)       forecasting(channel_group, event_count, PERIODS, FREQ)

Espero que este artículo te haya servido de inspiración y que te sea de gran utilidad en tus próximos proyectos. Si quieres seguir aprendiendo sobre este tipo de implementaciones o saber más en torno al Marketing Digital más técnico te invito a que visites el resto de artículos de mi Blog. ¡Seguro que no te defraudarán!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *