Un enfoque de ciencia de datos para optimizar la estructura de enlaces internos


Obtener el enlace interno optimizado es importante si le importa que las páginas de su sitio tengan suficiente autoridad para clasificar sus palabras clave objetivo. Por vinculación interna nos referimos a páginas de su sitio web que reciben enlaces de otras páginas.

Esto es importante porque es la base por la cual Google y otras búsquedas calculan la importancia de la página en relación con otras páginas de su sitio web.

También afecta la probabilidad de que un usuario descubra contenido en su sitio. El descubrimiento de contenido es la base del PageRank de Google algoritmo.

Hoy, estamos explorando un enfoque basado en datos para mejorar el enlace interno de un sitio web con el fin de lograr un SEO técnico de sitios más eficaz. Eso es para garantizar que la distribución de la autoridad de dominio interno se optimice de acuerdo con la estructura del sitio.

Mejora de las estructuras de enlaces internos con ciencia de datos

Nuestro enfoque basado en datos se centrará en solo un aspecto de la optimización de la arquitectura de enlaces internos, que es modelar la distribución de enlaces internos por profundidad del sitio y luego apuntar a las páginas que carecen de enlaces para la profundidad de su sitio en particular.

Anuncio publicitario

Continuar leyendo a continuación

Comenzamos importando las bibliotecas y los datos, limpiando los nombres de las columnas antes de obtener una vista previa de ellos:

import pandas as pd
import numpy as np
site_name="ON24"
site_filename="on24"
website="www.on24.com"

# import Crawl Data
crawl_data = pd.read_csv('data/'+ site_filename + '_crawl.csv')
crawl_data.columns = crawl_data.columns.str.replace(' ','_')
crawl_data.columns = crawl_data.columns.str.replace('.','')
crawl_data.columns = crawl_data.columns.str.replace('(','')
crawl_data.columns = crawl_data.columns.str.replace(')','')
crawl_data.columns = map(str.lower, crawl_data.columns)
print(crawl_data.shape)
print(crawl_data.dtypes)
Crawl_data

(8611, 104)

url                          object
base_url                     object
crawl_depth                  object
crawl_status                 object
host                         object
                             ...   
redirect_type                object
redirect_url                 object
redirect_url_status          object
redirect_url_status_code     object
unnamed:_103                float64
Length: 104, dtype: object
Datos de SitebulbAndreas Voniatis, noviembre de 2021

Lo anterior muestra una vista previa de los datos importados desde la aplicación de rastreo de escritorio de Sitebulb. Hay más de 8.000 filas y no todas serán exclusivas del dominio, ya que también incluirán URL de recursos y URL de enlaces salientes externos.

También tenemos más de 100 columnas que son superfluas para los requisitos, por lo que se requerirá alguna selección de columnas.

Anuncio publicitario

Continuar leyendo a continuación

Sin embargo, antes de ingresar en eso, queremos ver rápidamente cuántos niveles de sitio hay:

crawl_depth
0             1
1            70
10            5
11            1
12            1
13            2
14            1
2           303
3           378
4           347
5           253
6           194
7            96
8            33
9            19
Not Set    2351
dtype: int64

Entonces, de lo anterior, podemos ver que hay 14 niveles de sitio y la mayoría de estos no se encuentran en la arquitectura del sitio, sino en el mapa del sitio XML.

Puede notar que Pandas (el paquete de Python para manipular datos) ordena los niveles del sitio por dígitos.

Eso es porque los niveles del sitio son en esta etapa cadenas de caracteres en lugar de numéricos. Esto se ajustará en el código posterior, ya que afectará la visualización de datos (‘a saber’).

Ahora, filtraremos filas y seleccionaremos columnas.

# Filter for redirected and live links
redir_live_urls = crawl_data[['url', 'crawl_depth', 'http_status_code', 'indexable_status', 'no_internal_links_to_url', 'host', 'title']]
redir_live_urls = redir_live_urls.loc[redir_live_urls.http_status_code.str.startswith(('2'), na=False)]
redir_live_urls['crawl_depth'] = redir_live_urls['crawl_depth'].astype('category')
redir_live_urls['crawl_depth'] = redir_live_urls['crawl_depth'].cat.reorder_categories(['0', '1', '2', '3', '4',
                                                                                 '5', '6', '7', '8', '9',
                                                                                        '10', '11', '12', '13', '14',
                                                                                        'Not Set',
                                                                                       ])
redir_live_urls = redir_live_urls.loc[redir_live_urls.host == website]
del redir_live_urls['host']
print(redir_live_urls.shape)
Redir_live_urls

(4055, 6)
Datos de SitebulbAndreas Voniatis, noviembre de 2021

Al filtrar filas para direcciones URL indexables y seleccionar las columnas relevantes, ahora tenemos un marco de datos más optimizado (piense en la versión Pandas de una pestaña de hoja de cálculo).

Explorando la distribución de enlaces internos

Ahora estamos listos para visualizar los datos y tener una idea de cómo vínculos internos se distribuyen globalmente y por profundidad del sitio.

from plotnine import *
import matplotlib.pyplot as plt
pd.set_option('display.max_colwidth', None)
%matplotlib inline

# Distribution of internal links to URL by site level
ove_intlink_dist_plt = (ggplot(redir_live_urls, aes(x = 'no_internal_links_to_url')) + 
                    geom_histogram(fill="blue", alpha = 0.6, bins = 7) +
                    labs(y = '# Internal Links to URL') + 
                    theme_classic() +            
                    theme(legend_position = 'none')
                   )

ove_intlink_dist_plt
Vínculos internos a la URL vs Sin vínculos internos a la URLAndreas Voniatis, noviembre de 2021

De lo anterior, podemos ver abrumadoramente que la mayoría de las páginas no tienen enlaces, por lo que mejorar el enlace interno sería una oportunidad significativa para mejorar el SEO aquí.

Consigamos algunas estadísticas a nivel del sitio.

Anuncio publicitario

Continuar leyendo a continuación

crawl_depth
0             1
1            70
10            5
11            1
12            1
13            2
14            1
2           303
3           378
4           347
5           253
6           194
7            96
8            33
9            19
Not Set    2351
dtype: int64

La tabla anterior muestra la distribución aproximada de los enlaces internos por nivel de sitio, incluida la media (media) y la mediana (cuantil del 50%).

Esto es junto con la variación dentro del nivel del sitio (std para la desviación estándar), que nos dice qué tan cerca del promedio están las páginas dentro del nivel del sitio; es decir, qué tan consistente es la distribución del enlace interno con el promedio.

De lo anterior podemos suponer que el promedio por nivel de sitio, con la excepción de la página de inicio (profundidad de rastreo 0) y las páginas de primer nivel (profundidad de rastreo 1), varía de 0 a 4 por URL.

Para un enfoque más visual:

# Distribution of internal links to URL by site level
intlink_dist_plt = (ggplot(redir_live_urls, aes(x = 'crawl_depth', y = 'no_internal_links_to_url')) + 
                    geom_boxplot(fill="blue", alpha = 0.8) +
                    labs(y = '# Internal Links to URL', x = 'Site Level') + 
                    theme_classic() +            
                    theme(legend_position = 'none')
                   )

intlink_dist_plt.save(filename="images/1_intlink_dist_plt.png", height=5, width=5, units="in", dpi=1000)
intlink_dist_plt
Enlaces internos a URL frente a enlaces a nivel de sitioAndreas Voniatis, noviembre de 2021

El gráfico anterior confirma nuestros comentarios anteriores de que la página de inicio y las páginas sin rodeos vinculadas reciben la mayor parte de los enlaces.

Anuncio publicitario

Continuar leyendo a continuación

Con las escalas como están, no tenemos mucha visión de la distribución de los niveles inferiores. Enmendaremos esto tomando un logaritmo del eje y:

# Distribution of internal links to URL by site level
from mizani.formatters import comma_format

intlink_dist_plt = (ggplot(redir_live_urls, aes(x = 'crawl_depth', y = 'no_internal_links_to_url')) + 
                    geom_boxplot(fill="blue", alpha = 0.8) +
                    labs(y = '# Internal Links to URL', x = 'Site Level') + 
                    scale_y_log10(labels = comma_format()) + 
                    theme_classic() +            
                    theme(legend_position = 'none')
                   )

intlink_dist_plt.save(filename="images/1_log_intlink_dist_plt.png", height=5, width=5, units="in", dpi=1000)
intlink_dist_plt
Enlaces internos a URL frente a enlaces a nivel de sitioAndreas Voniatis, noviembre de 2021

Lo anterior muestra la misma distribución de los enlaces con la vista logarítmica, lo que nos ayuda a confirmar los promedios de distribución para los niveles inferiores. Esto es mucho más fácil de visualizar.

Dada la disparidad entre los dos primeros niveles del sitio y el sitio restante, esto es indicativo de una distribución sesgada.

Anuncio publicitario

Continuar leyendo a continuación

Como resultado, tomaré un logaritmo de los enlaces internos, lo que ayudará a normalizar la distribución.

Ahora tenemos el número normalizado de enlaces, que visualizaremos:

# Distribution of internal links to URL by site level
intlink_dist_plt = (ggplot(redir_live_urls, aes(x = 'crawl_depth', y = 'log_intlinks')) + 
                    geom_boxplot(fill="blue", alpha = 0.8) +
                    labs(y = '# Log Internal Links to URL', x = 'Site Level') + 
                    #scale_y_log10(labels = comma_format()) + 
                    theme_classic() +            
                    theme(legend_position = 'none')
                   )

intlink_dist_plt
Registrar enlaces internos a URL frente a enlaces a nivel de sitioAndreas Voniatis, noviembre de 2021

A partir de lo anterior, la distribución parece mucho menos sesgada, ya que los cuadros (rangos intercuartílicos) tienen un cambio escalonado más gradual desde el nivel del sitio hasta el nivel del sitio.

Esto nos prepara muy bien para analizar los datos antes de diagnosticar qué URL no están optimizadas desde el punto de vista del enlace interno.

Anuncio publicitario

Continuar leyendo a continuación

Cuantificando los problemas

El siguiente código calculará el 35º cuantil inferior (término de ciencia de datos para percentil) para la profundidad de cada sitio.

# internal links in under/over indexing at site level
# count of URLs under indexed for internal link counts

quantiled_intlinks = redir_live_urls.groupby('crawl_depth').agg({'log_intlinks': 
                                                                 [quantile_lower]}).reset_index()
quantiled_intlinks = quantiled_intlinks.rename(columns = {'crawl_depth_': 'crawl_depth', 
                                                          'log_intlinks_quantile_lower': 'sd_intlink_lowqua'})
quantiled_intlinks
Profundidad de rastreo y enlaces internosAndreas Voniatis, noviembre de 2021

Lo anterior muestra los cálculos. Los números no tienen sentido para un profesional de SEO en esta etapa, ya que son arbitrarios y tienen el propósito de proporcionar un límite para las URL con enlaces insuficientes en cada nivel de sitio.

Ahora que tenemos la tabla, los fusionaremos con el conjunto de datos principal para determinar si la URL fila por fila está subvinculada o no.

Anuncio publicitario

Continuar leyendo a continuación

# join quantiles to main df and then count
redir_live_urls_underidx = redir_live_urls.merge(quantiled_intlinks, on = 'crawl_depth', how = 'left')

redir_live_urls_underidx['sd_int_uidx'] = redir_live_urls_underidx.apply(sd_intlinkscount_underover, axis=1)
redir_live_urls_underidx['sd_int_uidx'] = np.where(redir_live_urls_underidx['crawl_depth'] == 'Not Set', 1,
                                                   redir_live_urls_underidx['sd_int_uidx'])

redir_live_urls_underidx

Ahora tenemos un marco de datos con cada URL marcada como subenlazada debajo de la columna » sd_int_uidx ‘como un 1.

Esto nos coloca en posición de sumar la cantidad de páginas de sitios con enlaces insuficientes por profundidad del sitio:

# Summarise int_udx by site level
intlinks_agged = redir_live_urls_underidx.groupby('crawl_depth').agg({'sd_int_uidx': ['sum', 'count']}).reset_index()
intlinks_agged = intlinks_agged.rename(columns = {'crawl_depth_': 'crawl_depth'})
intlinks_agged['sd_uidx_prop'] = intlinks_agged.sd_int_uidx_sum / intlinks_agged.sd_int_uidx_count * 100
print(intlinks_agged)

  crawl_depth  sd_int_uidx_sum  sd_int_uidx_count  sd_uidx_prop
0            0                0                  1      0.000000
1            1               41                 70     58.571429
2            2               66                303     21.782178
3            3              110                378     29.100529
4            4              109                347     31.412104
5            5               68                253     26.877470
6            6               63                194     32.474227
7            7                9                 96      9.375000
8            8                6                 33     18.181818
9            9                6                 19     31.578947
10          10                0                  5      0.000000
11          11                0                  1      0.000000
12          12                0                  1      0.000000
13          13                0                  2      0.000000
14          14                0                  1      0.000000
15     Not Set             2351               2351    100.000000

Ahora vemos que a pesar de que la página de profundidad 1 del sitio tiene un número de enlaces por URL superior al promedio, todavía hay 41 páginas que están subenlazadas.

Para ser más visual:

# plot the table
depth_uidx_plt = (ggplot(intlinks_agged, aes(x = 'crawl_depth', y = 'sd_int_uidx_sum')) + 
                    geom_bar(stat="identity", fill="blue", alpha = 0.8) +
                    labs(y = '# Under Linked URLs', x = 'Site Level') + 
                    scale_y_log10() + 
                    theme_classic() +            
                    theme(legend_position = 'none')
                   )

depth_uidx_plt.save(filename="images/1_depth_uidx_plt.png", height=5, width=5, units="in", dpi=1000)
depth_uidx_plt
En URL vinculadas frente a nivel de sitioAndreas Voniatis, noviembre de 2021

Con la excepción del Mapa del sitio XML URL, la distribución de URL con enlaces insuficientes parece normal, como lo indica la forma de campana cercana. La mayoría de las URL con enlaces insuficientes se encuentran en los niveles de sitio 3 y 4.

Anuncio publicitario

Continuar leyendo a continuación

Exportación de la lista de URL subenlazadas

Ahora que tenemos un control sobre las URL con vínculos inferiores por nivel de sitio, podemos exportar los datos y encontrar soluciones creativas para cerrar las brechas en la profundidad del sitio, como se muestra a continuación.

# data dump of under performing backlinks
underlinked_urls = redir_live_urls_underidx.loc[redir_live_urls_underidx.sd_int_uidx == 1]
underlinked_urls = underlinked_urls.sort_values(['crawl_depth', 'no_internal_links_to_url'])
underlinked_urls.to_csv('exports/underlinked_urls.csv')
underlinked_urls
Datos de SitebulbAndreas Voniatis, noviembre de 2021

Otras técnicas de ciencia de datos para enlaces internos

Cubrimos brevemente la motivación para mejorar los enlaces internos de un sitio antes de explorar cómo se distribuyen los enlaces internos en el sitio por nivel de sitio.

Anuncio publicitario

Continuar leyendo a continuación

Luego procedimos a cuantificar el alcance del problema de los vínculos subyacentes tanto numérica como visualmente antes de exportar los resultados para las recomendaciones.

Naturalmente, el nivel del sitio es solo un aspecto de los enlaces internos que se pueden explorar y analizar estadísticamente.

Otros aspectos que podrían aplicar técnicas de ciencia de datos a enlaces internos incluyen y obviamente no se limitan a:

  • Autoridad de nivel de página fuera del sitio.
  • Relevancia del texto de anclaje.
  • Intención de búsqueda.
  • Buscar el recorrido del usuario.

¿Qué aspectos le gustaría ver cubiertos?

Deje un comentario a continuación.

Más recursos:

Anuncio publicitario

Continuar leyendo a continuación


Imagen destacada: Shutterstock / Optimarc





Consultar el artículo en la publicación original

Un enfoque de ciencia de datos para optimizar la estructura de enlaces internos
A %d blogueros les gusta esto: