#!/usr/bin/env python # coding: utf-8 # . #
# JPierre-DATA ANALIST #

Conversion Rate Optimization For E-COMMERCE

#
#
# JPierre-DATA ANALIST #

Table of Contents

#
# JPierre-DATA ANALIST #

Introducción

# # En este proyecto se aborda el caso de un comercio tipo ecommerce que presenta estancamiento en sus ventas. Se aplicaran técnicas analíticas a los registros transaccionales con el fin de obtener lineas de accion para el diseño de una estrategia basada en datos. Al final del preoyecto, se entregan resultados de diagnóstico en las áreas analizadas, seguido de las acciones estratégicas de resolución para incrementar el CRO. # # # # **Objetivos del Proyecto** # # # Impulsar el crecimieno en ventas del E-Commerce por medio de: # # * Analizar situación actual en base a tres áreas de enfoque: Ventas, Clientes y Productos.(Establecer el baseline). # # * Determinar las mejores estrategias de CRO (Conversion Rate Optimization) adecuadas en base a los datos obtenidos. # # # # Procesos ETL. # # # **Herramientas:** #

El proyecto se aborda implementando Python por medio de Jupyter notebook, con los siguientes paquetes: Pandas, Numpy, Matplotlib, Scipy, Plotly, Seaborn y SqlAlchemy.

# # **Data Set:** #

La empresa cuenta con una base de datos SQL Server desde donde administra toda su información transaccional.

# #
# ## Importación de librerias. # In[1]: # Se importan los pquetes requeridos import numpy as np import pandas as pd import matplotlib.pyplot as plt get_ipython().run_line_magic('matplotlib', 'inline') import seaborn as sns import sqlalchemy as sa #Automcompletar rápido get_ipython().run_line_magic('config', 'IPCompleter.greedy=True') #Formato de display pd.options.display.float_format = '{:15.2f}'.format #Estilo de sns sns.set_theme(style="whitegrid") # ## Conexión a base de datos. # In[2]: # Conexión a la base de datos y carga de los datos iniciales. con = sa.create_engine('sqlite:///../Datos/ecommerce.db') # In[3]: # Inspeccion de tablas existentes. from sqlalchemy import inspect insp = inspect(con) tablas = insp.get_table_names() tablas # In[4]: # Creando df a partir de las tablas. oct = pd.read_sql('2019-Oct', con) nov = pd.read_sql('2019-Nov', con) dic = pd.read_sql('2019-Dec', con) ene = pd.read_sql('2020-Jan', con) feb = pd.read_sql('2020-Feb', con) # In[5]: # integración de tablas y datos en un único DataFrame df = pd.concat([oct,nov,dic,ene,feb], axis = 0) df # ## Calidad de Datos: # In[6]: # Tipos de Variables df.info() # In[7]: # Eliminar la columna Index df.drop(columns = 'index', inplace = True) # In[8]: # Corregir tipo de datos. pasar event_time a datetime def datetime_rapido(dt,formato): def divide_fecha(fecha): division = fecha.split() date = division[0] time = division[1] cadena = date + ' ' + time return cadena resultado = pd.to_datetime(dt.apply(lambda x: divide_fecha(x)), format = formato) return resultado # In[9]: # llamando a la función y mostando cambios formato = '%Y-%m-%d %H:%M:%S' df.event_time = datetime_rapido(df.event_time,formato) df.info() # In[10]: # Renombramos las variables a español df.columns = ['fecha', 'evento', 'producto', 'categoria', 'categoria_cod', 'marca', 'precio', 'usuario', 'sesion'] # In[11]: # Análisis de nulos df.isna().sum().sort_values(ascending = False) # # # **Summary:** # # * categoria_cod tiene casi todos los registros a nulo # * marca tiene casi la mitad de los registros a nulo # * hay 500 nulos en sesión # # Acciones: # # * eliminar las variables categoria_cod y marca # * eliminar los nulos de sesión ya que es una variable relevante # # # In[12]: df = df.drop(columns = ['categoria_cod','marca']).dropna() # In[13]: # Seleccion de variables con precio positivo df = df[df.precio > 0] df # In[14]: # Cantidad de eventos df.evento.nunique() # In[15]: # Frcuencia de eventos df.evento.value_counts() # In[16]: # Cantidad de prodctos distintos. df.producto.nunique() # In[17]: # Cantidad de categorias de producto. df.categoria.nunique() # In[18]: #Asignando la fecha como indice df.set_index('fecha', inplace = True) # * **TRANSFORMACION DE DATOS** # * Creando 3 nuevas variables a partir de la fecha # In[19]: # Funcion para segmentar dateTime def componentes_fecha(dataframe): date = dataframe.index.date año = dataframe.index.year mes = dataframe.index.month dia = dataframe.index.day hora = dataframe.index.hour minuto = dataframe.index.minute segundo = dataframe.index.second return(pd.DataFrame({'date':date, 'año':año,'mes':mes, 'dia':dia, 'hora':hora, 'minuto':minuto, 'segundo':segundo})) # In[20]: # LLamando a la funcion y creando nuevo df df = pd.concat([df.reset_index(),componentes_fecha(df)], axis = 1).set_index('fecha') df # In[21]: # Indicadores exógenos de feriados importantes. df['black_friday'] = 0 df.loc['2019-11-29','black_friday'] = 1 df['san_valentin'] = 0 df.loc['2020-02-14','san_valentin'] = 1 # In[22]: # Tablón Analitico final df.head() # JPierre-DATA ANALIST # # Procesos EDA # ## Analizando las ventas: # In[23]: # Frecuencia de eventos eventos = df.evento.value_counts() eventos # In[24]: # Generación de kpi Customer Journey kpi_visualizaciones_p = 100 kpi_carrito_p = eventos.loc['cart'] / eventos.loc['view'] * 100 kpi_abandono_p = eventos.loc['remove_from_cart'] / eventos.loc['cart'] * 100 kpi_compra_p = eventos.loc['purchase'] / eventos.loc['cart'] * 100 kpis = pd.DataFrame({'kpi':['visitas','carrito','compra'], 'valor':[kpi_visualizaciones_p,kpi_carrito_p,kpi_compra_p]}) kpis # In[25]: # Visualizando el embudo de Ventas from plotly import graph_objects as go fig = go.Figure(go.Funnel( y = kpis.kpi, x = kpis.valor.round(2), marker = {'color': ['red','blue','green']}, opacity = 0.3 )) fig.update_layout( title = 'Funnel Conversión Inicial') fig.show() # # Conclusiones: # # * Las tasas de partida son un 60% de carrito sobre visualiazaciones y un 22% de compra sobre carrito # * Por tanto, existe un **40% de visitas** sobre las que hay que trabajar para conseguir más carritos, y un **78% de carritos** sobre los que trabajar para conseguir más compras # In[26]: # generando dataframe agregado para analizar sesiones. sesion_prod = df.groupby(['sesion','evento']).producto.count() sesion_prod = sesion_prod.unstack().fillna(0) sesion_prod = sesion_prod[['view','cart','remove_from_cart','purchase']] # In[27]: # media de cada evento por sesión media_eventos_sesion = sesion_prod.mean() media_eventos_sesion # # Conclusión: # # En cada sesión, de media: # # * Se ven 2.2 productos # * Se añaden 1.3 productos al carrito # * Se eliminan 0.9 productos del carrito # * Se compran 0.3 productos # # **Estos números representan el objetivo de las acciones de CRO para lograr los incrementos.** # In[28]: # generando dataframe agregado para analizar sesiones. eventos_hora = df.groupby(['evento','hora']).producto.count() eventos_hora = eventos_hora.unstack(level = 0) # In[29]: # crear una nueva variable que sea el ratio de compras por visita en cada hora. eventos_hora['compras_visitas'] = eventos_hora.purchase / eventos_hora.view * 100 eventos_hora = eventos_hora[['view','cart','remove_from_cart','purchase','compras_visitas']] # In[30]: # Analizamos los horarios de compra. plt.figure(figsize = (10,4)) sns.lineplot(data = eventos_hora, x = eventos_hora.index, y = 'compras_visitas') plt.xticks(eventos_hora.index); # In[31]: # titpificar variables para unificar escalas y generar mapa de calor por hora def tipificar(variable): media = variable.mean() dt = variable.std() return(variable.apply(lambda x: (x - media) / dt)) # In[32]: # llamando a la función eventos_hora_tip = eventos_hora.apply(tipificar) # In[33]: # Mapa de calor agregado por eventos en cada horario plt.figure(figsize = (12,12)) sns.heatmap(data = eventos_hora_tip); # # # **INSIGHT #1**: Todas las métricas se maximizan en las franjas entre las 9:00 y las 13:00 y entre las 18:00 y las 20:00 # * Esta info es muy relevante, por ejemplo, de cara a paid ads, tanto de generación de tráfico como de retargeting. # * Además, parece haber algún segmento de clientes que compra a la 01:00 am, que aunque no sea muy frecuente, compra mucho. # # # In[34]: # Media de facturacion mensual df.loc[df.evento == 'purchase'].groupby('mes').precio.sum().mean() # **Esta variable es importante porque representa el ticket medio por mes (125000 $), el cual será nuestro barómetro de crecimiento.** # # # In[35]: # Analizando la tendencia de facturacion mensual tendencia = df.groupby('evento').resample('W').evento.count().unstack(level = 0) tendencia = tendencia[['view','cart','remove_from_cart','purchase']] tendencia.plot(subplots = True, figsize = (12,6), sharex = True, xticks = tendencia.index, x_compat=True, rot = 90); # # # **INSIGHT #2:** La gran conclusión es que todo el pastel de las compras navideñas se reparte en la semana del black friday # * La tendencia es plana en todas las métricas, lo que confirma la necesidad de las acciones de CRO. # * hay un pico muy pronunciado el 27 de Enero, seguramente algún evento local # # # ## Analizando a los Clientes: # In[36]: # Creando un df agregado por clientes y 3 variables importantes. clientes = df.loc[df.evento == 'purchase'].groupby(['usuario']).agg({'producto':'count', 'sesion':'nunique', 'precio': 'mean', 'date': 'max'}) clientes.columns = ['productos_tot_num','compras_tot_num','precio_medio_prod','ult_compra'] # In[37]: # Generando 2 nuevas variables clientes['gasto_tot'] = clientes.productos_tot_num * clientes.precio_medio_prod clientes['productos_por_compra'] = clientes.productos_tot_num / clientes.compras_tot_num clientes # In[38]: # analizando la distribucion de clientes en cuanto a gasto sns.histplot(data = clientes, x = 'gasto_tot', bins = 50) plt.xlim([0,300]); # La gran mayoría de los clientes han gastado menos de 50€ en el período. # In[39]: # Analizando clientes por su frecuencia de compra. sns.countplot(data = clientes, x = 'compras_tot_num'); # # # **INSIGHT #3:** La gran mayoría de los clientes sólo hace una compra. # # Existe gran recorrido para mejorar este ratio mediante: # # * email marketing con newletters y ofertas personalizadas # # # In[40]: # Analizando clientes por cantidad de productos en cada compra. clientes.productos_por_compra.describe() # # # **INSIGHT #4:** La compra mediana incluye 5 productos. # # Pero un 25% de los clientes compran más de 10 productos en la misma compra. # # Existe gran recorrido para mejorar este ratio mediante: # # * sistemas de recomendación en el momento de la compra # # # In[41]: # Analizando clientes por gasto total medio clientes.gasto_tot.describe() # # # **INSIGHT #5:** Existen clientes con gasto medio bastante alto, hasta decenas de veces superior a la media. Representan al segmento de alta facturación. # # Se sugiere atraer a estos clientes mediante programas de fidelización. # # # ## Analizando a los Productos: # In[42]: # Creando un df agregado a nivel de productos prod = df.groupby(['producto','evento']).size() prod = prod.unstack(level = 1).fillna(0) # In[43]: # Se crea una matriz de precios para hacer join con el df, y se reordena. maestro_precios = df.groupby('producto', as_index = False).precio.mean() prod = pd.merge(left = prod, right = maestro_precios, how = 'left', on = 'producto') prod = prod[['producto','view','cart','remove_from_cart','purchase','precio']] prod # In[44]: # produtos que no se venden prod[prod.purchase == 0] # # # **INSIGHT #6:** Casi la mitad de los productos no han tenido ninguna venta en los 5 meses del histórico. # # * ¿No se ven? # * ¿Se ven pero no se compran? # * ¿Es porque se sustituyen por otros productos propios? # * ¿Es porque se venden a precios mas bajos en la competencia? # * Etc # # Se podrían eliminar del catálogo, o como mínimo de la tienda, newsletter, etc, para que no ocupen espacio de los productos que sí se venden. # # # In[45]: # Analizando la relación entre precio y volumen de ventas de los productos. # Ya que este análisis incluye las ventas vamos a eliminar los productos que no han tenido ninguna. sns.scatterplot(data = prod[prod.purchase > 0], x = 'precio', y = 'purchase', hue = 'precio'); # **Sí que existe una clara relación decreciente.** # In[46]: # analizando 20 de los productos mas vistos prod.view.sort_values(ascending = False)[0:20].plot.bar(); # # # Es posible **incrementar las ventas y el ticket medio destacando estos productos en la tienda** Siempre que además de ser vistos también se vendan. # # # In[47]: # Analizando productos muy vistos y poco comprados # Por ejemplo productos que miran muchos clientes pero que luego no los compran. sns.scatterplot(data = prod, x = 'view', y = 'purchase'); # In[48]: # quitando el atípico y haciendo zoom en la ventana de muchas vistas pocas compras. sns.scatterplot(data = prod.loc[prod.view < 4000], x = 'view', y = 'purchase', hue = 'precio') plt.xlim(1000,3000) plt.ylim(0,150); # **Hay una oportunidad con estos productos,** porque por algún motivo generan el interés de los clientes, pero finalmente no los compran. # JPierre-DATA ANALIST # # Conclusiones: # # #

La tendencia actual es plana en todas las métricas, lo que confirma la necesidad de las acciones de CRO (Conversion Rate Optimization).

# # Tras el análisis realizado sobre los datos transaccionales, se ha desarrollado un plan CRO de 8 iniciativas concretas, organizadas en 5 grandes palancas o áreas de negocio que, con alta probabilidad y de acuerdo a los datos ahora conocidos, van a impulsar los baselines, consiguiendo un incremento global de los ingresos del ecommerce. **Los datos trazan el camino mas eficiente para obtener resultados ganadores.** # #
# ## Baseline # # # Los resultados analiticos indican que el Ecommerce presenta los siguientes **valores promedio por cada sesión:** # # * KPIs por sesión: Se ven 2.2 productos # * KPIs por sesión: Se añaden 1.3 productos al carrito # * KPIs por sesión: Se eliminan 0.9 productos del carrito # * KPIs por sesión: Se compran 0.3 productos # # * Venta cruzada: mediana de 5 productos por compra # # * Recurrencia: el 10% de los clientes vuelve a comprar tras el primer mes # # * Conversión: 60% de añadir al carrito sobre visualizaciones # * Conversión: 22% de compra sobre añadidos a carrito # * Conversión: 13% de compra sobre visualizaciones # # * Facturación media mensual: 125.000€ # # # ## Acciones de incremento de visualizaciones # # # 1. Revisar las campañas de paid (generación y retargeting) para concentrar la inversión en franjas entre las 9 y las 13 y entre las 18 y las 20 # 2. Concentrar la inversión del período navideño y post-navideño en la semana del black friday # # # ## Acciones de incremento de conversión # # # 3. Preconfigurar la home con los productos identificados en los análisis most viewed y most sold. # 4. Trabajar sobre los productos muy vistos pero poco comprados # # # ## Acciones de incremento de venta cruzada # # # 5. La compra mediana incluye 5 productos. Incrementar este ratio mediante la implementación en tiempo real de un sistema de recomendación. # # # ## Acciones de incremento de frecuencia de compra # # # El 90% de los clientes sólo hace una compra. # # 6. Crear una newsletter periódica en base aun sistema de recomendación para incrementar la frecuencia de visita # 7. Campañas promocionales sobre los segmentos top de la cartera de clientes. # # # ## Acciones de fidelización de clientes # # # 8. Crear un programa de fidelización sobre los segmentos top de la cartera de clientes. # # # # Business Case # # # Es recomendable en este caso, **generar un BUSINESS CASE** para observar: # # 1. las 8 acciones de CRO recomendadas dentro de un plan. # 2. Los Presupuestos, proyecciones y escenarios de rentabilidad. # # #
# # Ir al Business Case # #
# # Consideraciones finales: # # Este proyecto es experimental, pero se basa en un enfoque bastante realista. Los datos para este proyecto se obtienen de Kaggle, un sitio web que ofrece conjuntos de datos experimentales. Puedes encontrarlos en https://www.kaggle.com/datasets # . #
# # Visita mi perfil en GitHub ➡️ # #
# # .