La gestión del stock de los productos es uno de los conceptos más complejos de un E-commerce. Debemos tener una manera eficiente de detectar los productos sin stock que pueden impactar en la tasa de conversión y los ingresos.
Efectivamente, las fichas de productos suelen ser las páginas que más tráfico generan en un E-commerce. Además, en general tratan tráfico de calidad y bastante avanzado en el embudo de conversión.
Encontrar los productos sin stock con Screaming Frog
La manera más simple de encontrar un producto sin stock es usando Screaming Frog. En este apartado, os voy a explicar cómo hacerlo.
Etapa 1: Encontrar una página con un producto sin stock. Suele hacerse de forma rápida, ya que siempre existe por lo menos un producto sin stock en cualquier E-commerce:
Os aconsejo que habléis con el cliente, si podéis, para que os diga cuáles son las opciones de texto que pueden aparecer en caso de que un producto esté sin stock.
Etapa 2: Copiar el texto. Os aconsejo que uséis lo que aparece en el código fuente, porque es lo que Screaming Frog usa.
Etapa 3: Abrid Screaming Frog, usad la funcionalidad de “Custom Search” y pegad el texto que hayáis copiado previamente.
Etapa 4: Podéis lanzar el crawl y esperar a que acabe para tener un listado de todos los productos que están sin stock.
Es importante revisar el listado de URLs que nos devuelve Screaming Frog para asegurarnos de que no contenga falsos positivos. Podéis también usar la funcionalidad de Custom Extraction de la rana para extraer la misma información.
Este proceso es interesante, pero tiene varias desventajas:
- Es un proceso manual, dado que tenemos que configurar Screaming Frog, esperar a que acabe y extraer los resultados.
- Rastreamos todo el portal, cuando podría ser interesante rastrear únicamente las URLs que realmente nos interesan.
Para eliminar estos dos problemas, vamos a ver cómo integrar este proceso dentro de un proceso automatizado de comprobación con Python.
Encontrar los productos sin stock con Python
En este apartado, os voy a explicar cómo podéis montar un sistema más automático con Python. Al final, lo que queremos no es obtener todas las URLs de productos sin stock (podemos llegar a tener muchas), pero sí tener un listado de URLs sin stock que hayan generado una cantidad importante de ingresos o sesiones durante las últimas semanas.
El proceso será el siguiente:
- Sacar el listado de URLs de productos que más sesiones han generado durante las 4 últimas semanas. Podríamos incluir también los ingresos pero, en este ejemplo, usaré únicamente las sesiones.
- Rastrear estas URLs para extraer el estado de stock.
- Enviar un correo con el listado de productos sin stock, ordenado por sesión.
Configuración Inicial
Primero, os indico todas las librerías que uso:
import ssl
import smtplib
import email
from google2pandas import *
from datetime import datetime
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import time
import requests
import pandas as pd
import requests
import datetime as dt
from requests_html import HTMLSession
import xlsxwriter
Algunas de ellas sirven para enviar el correo, pero las más importantes son:
- Pandas para manipular datos.
- Googl2Pandas que la amo, porque permite recuperar datos con la API de Analytics directamente en DataFrames para después manipularlos con Pandas. Tendréis que configurar los accesos a la API de Analytics para que funcione.
- Requests y Requests_html para rastrear URLs y extraer una parte del contenido usando Xpath.
- xlsxwriter para crear archivos XLSX.
Extracción de los datos con Google2Pandas
Para extraer los datos de Analytics, podéis usar la siguiente función.
def GetAnalyticsData(ga_id, start_date, end_date):
query = {
'ids': ga_id,
'metrics': 'sessions',
'dimensions': ['landingPagePath'],
'start_date': start_date,
'end_date': end_date,
'filters': ['sessions>0'],
'max_results': 10000,
'sort': ['-sessions']
}
df, metadata = conn.execute_query(**query)
df.columns = ['pagePath', 'sessions']
# Create the full URL again
df.pagePath = 'xxxxxxx' + df.pagePath
# Merge URLs with and without parameters
df.pagePath = df.pagePath.str.replace('\?.*', '', regex=True)
aggregation_functions = {'pagePath': 'first', 'sessions':'sum'}
df_new = df.groupby(df['pagePath']).aggregate(aggregation_functions).reset_index(drop=True).sort_values(by='sessions', ascending=False)
return df_new
Lo que hace:
- Recupera el Top 10.000 de páginas durante el periodo que hayáis indicado junto con el número de sesiones asociadas para cada una de estas páginas. Como veréis, he puesto un filtro para excluir las páginas con menos de 1 sesión.
- Reconstruye la URL completa (tenéis que cambiar el ‘xxxxx’ por vuestro dominio como https://www.ejemplo.es).
- Se fusionan los datos de las URLs con y sin parámetros. Esta parte evita rastrear 20 veces la misma URL pero, si los parámetros tienen un impacto sobre el contenido de la página, no os aconsejo que la uséis.
Podéis usar más filtros e incluir más datos si fuera necesario. Para saber cuáles son los nombres de las variables, podéis usar la ayuda de Google.
Os añado unos comentarios adicionales para un mejor uso de la función:
- gaid: ID de vuestra vista en GA
- start_date y end_date tienen que tener el formato ‘AAAA-MM-DD’
Conservar únicamente las URLs de los productos
Para conservar únicamente los datos de los productos, tendremos dos opciones en función de nuestra situación:
Podemos identificar los productos con la URL
En el caso que las URLs de productos tengan un formato específico como por ejemplo: https://mipagina.es/p/mi-producto, podemos aplicar un filtro a lo que nos devuelva la API de Google Analytics sin ningún problema.
data = GetAnalyticsData(ga_id, start_date, end_date)
data = data[data['pagePath'].str.contains('/p')]
Fácil y rápido, como me gusta. Sin embargo, no os voy a engañar: casi nunca se puede usar este método y tenemos que ser un poco más creativos.
No podemos identificar los productos con la URL
En este caso, no existe un solo método, pero la idea es encontrar algo en el código que nos permita asegurarnos que la URL es de un producto. En el código que os indico a continuación, estamos en esta situación y se extrae esta información del DataLayer que usa Google Tag Manager.
Recuperar el estado de stock de nuestros productos
Primero el código, después la explicación 🙂
urls = data['pagePath']
output = [['pagePath','stock']]
for element in urls:
r = session.get(element)
# Xpath + extracción del page_type
page_type = r.html.xpath('//script/text()')[0]
page_type = pd.Series(str(page_type))
page_type = page_type.str.replace(
'.*dataLayer.*pageType\"\:\"', '',
regex=True).str.replace('\"\,\"pageUrl.*', '', regex=True)
page_type = page_type[0]
if page_type == 'product':
try:
stock = r.html.xpath('//button[@id="add-to-cart"]/text()')[0]
except:
stock = 'Error extrayendo los datos'
output.append([element,stock])
i += 1
print('Success for element ' + str(i) + ' out of ' + str(len(urls)))
final = pd.DataFrame(output[1:],columns=output[0])
final = final.merge(
data, on='pagePath', how='left')
final = final.sort_values(by=['sessions'])
# Create a Pandas Excel writer using XlsxWriter as the engine.
writer = pd.ExcelWriter('output.xlsx', engine='xlsxwriter')
final.to_excel(writer, sheet_name='data')
# Close the Pandas Excel writer and output the Excel file.
writer.save()
- Primero, se crea la variable ‘urls’, que es un listado de todas las URLs que vamos a rastrear.
- Se rastrean las URLs una por una y, si el pageType del DataLayer corresponde a “product”, entonces se extrae el estado del stock gracias a su Xpath.
- Creamos una tabla que tiene esta estructura:
URL | STOCK |
https://ww.ejemplo.es/producto-1 | En Stock |
Y que fusionamos con nuestra tabla inicial, que tenía esta estructura…
URL | Sesiones |
https://www.ejemplo.es/producto-1 | 1456 |
… para obtener la siguiente tabla final:
URL | Sesiones | Stock |
https://www.ejemplo.es/producto-1 | 1456 | En Stock |
Vamos, que hemos hecho un BuscarV 🙂
- Finalmente, guardamos los resultados en un archivo Excel. Podríamos guardar únicamente los resultados de los productos sin stock pero, en este caso, hemos decidido guardar todo por si acaso.
Envío del correo
Esta parte del código es la más importante, porque es lo que nos permite automatizar todo el proceso. En efecto, si subimos nuestro script Python a un servidor y creamos una tarea CRON para que se ejecute, por ejemplo, una vez a la semana, recibiremos un correo una vez a la semana con el estado de stock de nuestro E-commerce con las sesiones asociadas. Genial, ¿no?
Para esta parte, os aconsejo que miréis https://realpython.com/python-send-email/ de dónde he sacado el código que uso. Tengo ciertos conocimientos de Pyhton, sobre todo enfocados a analizar datos y, la verdad, es que la parte de E-mail se me escapa un poco.
Conclusión
Como habréis visto, existen varias maneras de extraer el stock de vuestro E-commerce, pero sin tener en cuenta el método que uséis, os aconsejo que lo miréis de vez en cuando, porque sin stock no se puede vender nada con un E-commerce.