Cualquier compañía hace grandes esfuerzos en publicitar sus productos y servicios en redes sociales como Facebook. A menudo se plantea la necesidad de evaluar dichas campañas y contrastar su rendimiento con otros parámetros de la empresa. Lo que nos proponemos, en resumen, es obtener datos de la Marketing API de Facebook e introducirlos en un flujo de datos de SSIS.

Estrategia general:

Para poder manejar las peticiones a la API y sus respuestas de una manera cómoda desde SSIS nos vamos a ayudar de un pequeño script de Python al que llamaremos desde un paquete de SSIS. Este script realizará cierta llamada a la api que configuraremos fija en el script, de esta manera el script realizará un papel similar a «obtenme este dato». Podría haber varios scripts que realizasen distintas llamadas con distintos agendados o distinto procesamiento de los datos; también podría componerse un script interactivo que realizase distintas llamadas en función de los parámetros que se aportasen a su ejecución.

Utilizaremos el SDK oficial de Facebook, que es sencillo de instalar y que nos provee de todo tipo de objetos y métodos para gestionar la conversación con la API. Nos centraremos en la obtención de «Campaign Insights», es decir, datos relativos a las campañas de publicidad realizadas en Facebook mediante un AdAccount de un Business Manager. En general, necesitamos una cuenta de Business Manager que monitorizar. Dicha cuenta debe tener al menos un AdAccount y este tendrá dentro campañas de publicidad. Es de estas últimas de las que vamos a extraer los datos.

Autenticación:

Para desarrollar una aplicación que consuma datos de la api de facebook debemos registrar una aplicación en la web de desarrolladores de Facebook, dándonos de alta como desarrolladores, si no lo somos ya, y seleccionando Add New App en el menú de arriba a la derecha.

Se nos pedirá un nombre para la aplicación y un email de contacto:

En la nueva aplicación debemos indicar que queremos consumir la marketing API, seleccionándola en el menú «Add a Product»

Una vez añadido, veremos en el menú de la izquierda la Marketing Api lista para configurar

Con esto ya disponemos de las credenciales necesarias por parte de la aplicación, en la opción Settings / Advanced del menú de la izquierda: App ID y Client Token

Una vez terminada la creación de la app en el portal de desarrolladores de Facebook, necesitamos relacionar el AdAccount del Business Manager con la aplicación. En un entorno real, enviaríamos la aplicación a revisión por parte de Facebook y después de ser aprobada, podríamos pasar el id de la aplicación al dueño del Business Manager y relacionarlos sin problema. Sin embargo, como estamos desarrollando la aplicación nos encontramos en el nivel de acceso de desarrollo y no podremos relacionar nuestra aplicación con Business Manager que no sean de nuestra propiedad. Esto implica que, al menos en fase de desarrollo el Business Manager del que obtenemos los datos de la API debe ser propiedad del usuario que creó la aplicación. Una vez la aplicación ha sido enviada a revisión ya no existe esta limitación.

Teniendo en cuenta esta limitación, en el Business Manager podemos crear «Usuarios de sistema» que son usuarios que no se corresponden con personas reales sino con bots, cuyo cometido es justamente canalizar las automatizaciones como la que estamos implementando. Para ello necesitamos primero relacionar la app con el AdAccount que vayamos a monitorizar.

En el panel de control del Business Manager, después de asegurarnos de que existe un AdAccount con campañas, vamos al menú Accounts / Apps y allí pulsamos el botón «Add», seleccionamos «Add an App» y escribimos el App ID de nuestra aplicación. La solicitud se aprobará automáticamente porque nuestro usuario es administrador de la App.

Tras añadir la app, en el menú Users aparecerá la opción «System Users» (si no aparece, bastará con refrescar la página para verla). En esta opción podemos agregar usuarios de sistema (botón «Add») y asignarles un nombre y un rol, que dado que no vamos a crear ni a tocar nada de las campañas y nos limitamos a leer estadísticas, basta con que sea «usuario regular».

Bajo el nombre del usuario de sistema aparecerá su ID. Debemos copiar este ID para indicar a la aplicación que este usuario de sistema debe tener acceso como desarrollador a la aplicación:

Volvemos a la página de la aplicación y añadimos al usuario de sistema como developer en el menú «Roles» / «Roles», pulsando en «Add Developers» e introduciendo el id del usuario de sistema

Cuando ya está registrada la App en el Business Manager y el usuario del Business Manager en la App, volvemos a la página del usuario en el Business Manager y generamos un token para él:

En el popup, debemos seleccionar la aplicación y, tras darle a aceptar, seleccionar los permisos que necesitamos, en nuestro caso sólo read_insigths para poder ver los datos de las campañas:

Obtenemos el token y lo guardamos:

Script Python para consumir la API

Para la extracción de datos de la API utilizaremos un script en Python utilizando el SDK de la Marketing API, que nos ofrece los objetos y métodos de la API ya mapeados y listos para usar.

Necesitaremos, en primer lugar, instalar el paquete facebook_business desde pip, abriendo una consola de comandos, yendo a la carpeta donde está instalado Python y, en ella, a la carpeta Scripts/ que aloja el ejecutable de pip (el gestor de paquetes de Python) y ejecutándolo:

pip install facebook_business

El paquete se instalará y ya estará preparado para ser llamado por el intérprete de Python

Una vez cargada la información en los objetos que el SDK pone a nuestra disposición mapeando las respuestas y métodos de la API, tendremos que decidir qué hacer con los datos. En tanto que queremos integrar el script en una solución de SSIS, nos limitaremos a componer un csv y dejarlo en disco, de manera que luego lo leamos con SSIS y podamos modificar el flujo de los datos.

El script de Python comienza importando las partes del módulo facebook_business que nos serán necesarias para gestionar una AdAccount, una Campaña, los Insights de los anuncios y el usuario que los gestiona. Además importamos la clase que gestiona las llamadas a la api.

from facebook_business.adobjects.adaccount import AdAccount
from facebook_business.adobjects.campaign import Campaign
from facebook_business.adobjects.adsinsights import AdsInsights
from facebook_business.adobjects.adaccountuser import AdAccountUser as AdUser
from facebook_business.api import FacebookAdsApi

Guardamos en variables los datos de autenticación (token de usuario, id de aplicación y token de aplicación), y usando el token inicializamos la API.

access_token = 'INSERT_USER_ACCESS_TOKEN'
app_secret = 'INSERT_USER_ACCESS_TOKEN'
app_id = 'INSERT_APP_ID'
   
FacebookAdsApi.init(access_token=access_token)

A continuación obtenemos el usuario identificado por ‘me’, que se refiere al usuario dueño del token de usuario que se utilizó para inicializar la API. Una vez obtenido el usuario, pedimos sus AdAccounts con el método get_ad_accounts()

me = AdUser(fbid='me')
my_accounts = list(me.get_ad_accounts())

Para cada AdAccount realizamos las peticiones siguientes:

  • De cada AdAccount extraemos sus campañas [get_campaigns()]. Al método que obtiene las campañas se le pasan los parámetros fields y params. El primero de ellos selecciona qué campos del objeto queremos obtener y el segundo modula la petición. En nuestro caso, queremos saber el nombre de la campaña, el objetivo, las fechas de inicio y fin y el estado actual de la campaña, y modularemos la petición pidiendo solo campañas activas o pausadas. Los parámetros y campos de esta query se detallan en la documentación del objeto
for a in my_accounts: # each account
  fields = ['name','objective','start_time','stop_time','effective_status']
  params = {'effective_status': ['ACTIVE', 'PAUSED']}
  camp = AdAccount(a['id']).get_campaigns(fields=fields,params=params)
  • Una vez tenemos las campañas iteramos sobre ellas para obtener los insights de las campañas. Antes, hemos rellenado la variable fields con los campos que queremos obtener (todos ellos referenciados por medio de la clase del SDK AdsInsights) y también hemos compuesto un params donde, en este caso, obtenemos toda la historia de las campañas con una resolución de un día.
fields=[AdsInsights.Field.date_start,AdsInsights.Field.date_stop, AdsInsights.Field.reach,
        AdsInsights.Field.impressions, AdsInsights.Field.spend, AdsInsights.Field.frequency,
        AdsInsights.Field.clicks, AdsInsights.Field.unique_clicks, AdsInsights.Field.cpc,
        AdsInsights.Field.cpm, AdsInsights.Field.ctr, AdsInsights.Field.unique_ctr, 
        AdsInsights.Field.cost_per_unique_click, AdsInsights.Field.website_purchase_roas,
        AdsInsights.Field.account_name]  
params = {'date_preset': 'lifetime','time_increment':1}
  • Preparamos el rellenado del csv:
filename = 'c:/tmp/'+a['account_id']+'.csv' 
separator = ","
# Header
header = "name,campaign_id,"
for f in fields:
  header+=str(f)
  header+=separator
with open(filename, 'w') as output:
  output.write(header)
  output.write("\n")
  • Para cada campaña, entonces, obtenemos los insights
for c in camp: # Each campaign
  insigths = c.get_insights(fields=fields,params=params)
  for i in insigths: # Each campaign element
    data = c['name']
    data += separator
    data += c['id']
    data += separator
    for f in fields:
      if len(i) > 0: # There is data
        if f in i: # Field is present
          data += str(i[f])
      data += separator
    output.write(data)
    output.write("\n")

Es importante notar que tal y como está montado el script recoge información de TODAS las AdAccount que son visibles al usuario de sistema, dentro de ellas, de TODAS las campañas; y la salida es un csv con el idde la campaña (un entero).

Llamada al script

Para llamar al script de Python desde SSIS necesitamos un bloque «Execute Process Task». En él, llamaremos al ejecutable de Python (generalmente C:\Users\{Usuario}\AppData\Local\Programs\Python\Python36\python.exe) y como argumento le pasamos la localización del script de Python. Esto, dado que en el script hemos abierto el archivo de destino con el atributo ‘w’, reescribirá sobre el archivo de destino la información, borrando la anterior.

Integrando el dato.

Una vez ejecutado el script de Python iteraremos con un bloque foreach por los archivos de la carpeta donde se dejan los resultados (un archivo por AdAccount encontrada para el usuario). Para ello configuramos el foreach con el enumerator «Foreach File Enumerator», le decimos el directorio en el que hay que buscar los archivos y utilizamos una wildcard como *.csv para limitar los archivos que entran a los de ese tipo.

Mapeamos una variable string, en este caso User::fileName al índice 0 de la colección de valores para pasar el nombre del archivo por el que se está iterando a una conexión a archivo plano.

Creamos la nueva conexión a Archivo plano. Seleccionamos uno de los archivos csv en c:/tmp y marcamos como delimitador la coma y, una vez creado el conector a archivo plano, añadimos en sus propiedades una expresión que relacione la connection string del manager con la variable User::fileName que rellena el bucle foreach.

Dentro del bucle ya podemos incluir dentro bloque foreach un dataflow que contenga un origen de archivo plano que utilice ese connection manager que acabamos de crear y que procese los datos como más conveniente nos sea (por ejemplo, insertándolo en una tabla de sql). A partir de aquí el dato de la Marketing API está dentro de nuestro sistema.

Pablo Gómez

SolidQ Data Platform Specialist. Training, learning and working at SolidQ since 2016.
Pablo Gómez