Visualització dels guanyadors i perdedors de Google Core Update amb Python


Per als experts en SEO, les actualitzacions bàsiques de Google són una forma de vida. Es produiran almenys una vegada, si no diverses vegades, a l’any.

Naturalment, hi haurà guanyadors i perdedors.

Així, tot i que Google no en revela la majoria factors de classificació darrere de les actualitzacions de l’algorisme, hi ha coses que podem fer per entendre millor què està passant, en termes de:

  • Quin contingut del lloc es veu afectat.
  • Llocs que operen al vostre espai de cerca.
  • Tipus de resultats.

El límit és la teva imaginació, les teves preguntes (basades en els teus coneixements de SEO) i, per descomptat, les teves dades.

Aquest codi cobrirà les agregacions al nivell de la pàgina de resultats del motor de cerca (SERP) (comparació de categories entre llocs) i els mateixos principis es poden aplicar a altres vistes de l’actualització bàsica, com ara els tipus de resultats (penseu fragments i altres punts de vista esmentats anteriorment).

Ús de Python per comparar SERP

El principi general és comparar les SERP abans i després de l’actualització bàsica, cosa que ens donarà algunes pistes sobre què està passant.

Començarem important les nostres biblioteques de Python:

import re
import time
import random
import pandas as pd
import numpy as np
import datetime
from datetime import timedelta
from plotnine import *
import matplotlib.pyplot as plt
from pandas.api.types import is_string_dtype
from pandas.api.types import is_numeric_dtype
import uritools  
pd.set_option('display.max_colwidth', None)
%matplotlib inline

Definint algunes variables, ens centrarem a ON24.com, ja que van perdre amb l’actualització bàsica.

root_domain = 'on24.com'
hostdomain = 'www.on24.com'
hostname="on24"
full_domain = 'https://www.on24.com'
site_name="ON24"

Llegint les dades, estem utilitzant una exportació de GetSTAT que té un informe útil que us permet comparar les SERP de les vostres paraules clau abans i després.

Aquest informe de SERP està disponible a altres proveïdors de seguiment de classificació, com ara Monitor de SEO i Rànquing web avançat – No hi ha preferències ni avals del meu costat!

getstat_ba_urls = pd.read_csv('data/webinars_top_20.csv', encoding = 'UTF-16', sep = 't')
getstat_raw.head()
Seguiment de SERPsCaptura de pantalla de l’autor, gener de 2022
getstat_ba_urls = getstat_raw

Construeix els URL unint el protocol i la cadena d’URL per obtenir l’URL de classificació complet tant abans com després de l’actualització.

getstat_ba_urls['before_url'] = getstat_ba_urls['Protocol for Nov 19, 2020'] + '://' + getstat_ba_urls['Ranking URL on Nov 19, 2020']
getstat_ba_urls['after_url'] = getstat_ba_urls['Protocol for Dec 17, 2020'] + '://' + getstat_ba_urls['Ranking URL on Dec 17, 2020']
getstat_ba_urls['before_url'] = np.where(getstat_ba_urls['before_url'].isnull(), '', getstat_ba_urls['before_url'])
getstat_ba_urls['after_url'] = np.where(getstat_ba_urls['after_url'].isnull(), '', getstat_ba_urls['after_url'])


Per obtenir els dominis dels URL de classificació, creem una còpia de l’URL en una columna nova, eliminem els subdominis mitjançant una declaració if incrustada en una llista de comprensió:

getstat_ba_urls['before_site'] = [uritools.urisplit(x).authority if uritools.isuri(x) else x for x in getstat_ba_urls['before_url']]
stop_sites = ['hub.', 'blog.', 'www.', 'impact.', 'harvard.', 'its.', 'is.', 'support.']
getstat_ba_urls['before_site'] = getstat_ba_urls['before_site'].str.replace('|'.join(stop_sites), '')

La comprensió de la llista es repeteix per extreure els dominis després de l’actualització.

getstat_ba_urls['after_site'] = [uritools.urisplit(x).authority if uritools.isuri(x) else x for x in getstat_ba_urls['after_url']]
getstat_ba_urls['after_site'] = getstat_ba_urls['after_site'].str.replace('|'.join(stop_sites), '')
getstat_ba_urls.columns = [x.lower() for x in getstat_ba_urls.columns]
getstat_ba_urls = getstat_ba_urls.rename(columns = {'global monthly search volume': 'search_volume'
                                                   })
getstat_ba_urls
Abans i després dels URLCaptura de pantalla de l’autor, gener de 2022

Desduplica diversos URL de classificació

El següent pas és eliminar els diversos URL de classificació del mateix domini per paraula clau SERP. Dividirem les dades en dos conjunts, abans i després.

A continuació, agruparem per paraula clau i realitzarem la deduplicació:

getstat_bef_unique = getstat_ba_urls[['keyword', 'market', 'location', 'device', 'search_volume', 'rank',
       'result types for nov 19, 2020', 'protocol for nov 19, 2020',
       'ranking url on nov 19, 2020', 'before_url', 'before_site']]
getstat_bef_unique = getstat_bef_unique.sort_values('rank').groupby(['before_site', 'device', 'keyword']).first()
getstat_bef_unique = getstat_bef_unique.reset_index()
getstat_bef_unique = getstat_bef_unique[getstat_bef_unique['before_site'] != '']
getstat_bef_unique = getstat_bef_unique.sort_values(['keyword', 'device', 'rank'])
getstat_bef_unique = getstat_bef_unique.rename(columns = {'rank': 'before_rank', 
                                                          'result types for nov 19, 2020': 'before_snippets'})
getstat_bef_unique = getstat_bef_unique[['keyword', 'market', 'device', 'before_snippets', 'search_volume', 
                                         'before_url', 'before_site', 'before_rank'
                                        ]]
getstat_bef_unique
seguiment de paraules clauCaptura de pantalla de l’autor, gener de 2022

El procediment es repeteix per al conjunt de dades posterior.

getstat_aft_unique = getstat_ba_urls[['keyword', 'market', 'location', 'device', 'search_volume', 'rank',
       'result types for dec 17, 2020', 'protocol for dec 17, 2020',
       'ranking url on dec 17, 2020', 'after_url', 'after_site']]
getstat_aft_unique = getstat_aft_unique.sort_values('rank').groupby(['after_site', 'device', 'keyword']).first()
getstat_aft_unique = getstat_aft_unique.reset_index()
getstat_aft_unique = getstat_aft_unique[getstat_aft_unique['after_site'] != '']
getstat_aft_unique = getstat_aft_unique.sort_values(['keyword', 'device', 'rank'])
getstat_aft_unique = getstat_aft_unique.rename(columns = {'rank': 'after_rank', 
                                                          'result types for dec 17, 2020': 'after_snippets'})
getstat_aft_unique = getstat_aft_unique[['keyword', 'market', 'device', 'after_snippets', 'search_volume', 
                                         'after_url', 'after_site', 'after_rank'
                                        ]]

Segmenta els llocs SERP

Quan es tracta de actualitzacions bàsiques, la majoria de les respostes solen estar a les SERP. Aquí és on podem veure quins llocs estan sent recompensats i altres que perden.

Amb els conjunts de dades deduplicats i separats, analitzarem els competidors comuns perquè puguem començar a segmentar-los manualment, cosa que ens ajudarà a visualitzar l’impacte de l’actualització.

serps_before = getstat_bef_unique
serps_after = getstat_aft_unique
serps_before_after = serps_before_after.merge(serps_after, left_on = ['keyword', 'before_site', 'device', 'market', 'search_volume'], 
                                                right_on = ['keyword', 'after_site', 'device', 'market', 'search_volume'], how = 'left')

Neteja de les columnes de classificació de valors nuls (NAN no és un nombre) mitjançant la funció np.where() que és l’equivalent de Panda a la fórmula if d’Excel.

serps_before_after['before_rank'] = np.where(serps_before_after['before_rank'].isnull(), 100, serps_before_after['before_rank'])
serps_before_after['after_rank'] = np.where(serps_before_after['after_rank'].isnull(), 100, serps_before_after['after_rank'])


Algunes mètriques calculades per mostrar la diferència de classificació abans i després i si l’URL ha canviat.

serps_before_after['rank_diff'] = serps_before_after['before_rank'] - serps_before_after['after_rank']
serps_before_after['url_change'] = np.where(serps_before_after['before_url'] == serps_before_after['after_url'], 0, 1)
serps_before_after['project'] = site_name
serps_before_after['reach'] = 1
serps_before_after
diferència de rang abans vs desprésCaptura de pantalla de l’autor, gener de 2022

Agrega els llocs guanyadors

Amb les dades netejades, ara podem agregar per veure quins llocs són els més dominants.

Per fer-ho, definim la funció que calcula la classificació mitjana ponderada per volum de cerca.

No totes les paraules clau són tan importants, cosa que fa que l’anàlisi sigui més significativa si us preocupeu per les paraules clau que obtenen més cerques.

def wavg_rank(x):
    names = {'wavg_rank': (x['before_rank'] * (x['search_volume'] + 0.1)).sum()/(x['search_volume'] + 0.1).sum()}
    return pd.Series(names, index=['wavg_rank']).round(1)

rank_df = serps_before_after.groupby('before_site').apply(wavg_rank).reset_index()
reach_df = serps_before_after.groupby('before_site').agg({'reach': 'sum'}).sort_values('reach', ascending = False).reset_index()

commonstats_full_df = rank_df.merge(reach_df, on = 'before_site', how = 'left').sort_values('reach', ascending = False)
commonstats_df = commonstats_full_df.sort_values('reach', ascending = False).reset_index()
commonstats_df.head()
calcular la classificació mitjana ponderada per volum de cercaCaptura de pantalla de l’autor, gener de 2022

Tot i que la classificació mitjana ponderada és important, també ho és l’abast, ja que ens indica l’amplitud de la presència del lloc a Google, és a dir, el nombre de paraules clau.

L’abast també ens ajuda a prioritzar els llocs que volem incloure a la nostra segmentació.

La segmentació funciona utilitzant la funció np.select que és com una fórmula Excel if imbricada mega.

Primer, creem una llista de les nostres condicions.

domain_conds = [
    commonstats_df['before_site'].isin(['google.com', 'medium.com', 'forbes.com', 'en.m.wikipedia.org',
                                        'hbr.org', 'en.wikipedia.org', 'smartinsights.com', 'mckinsey.com',
                                        'techradar.com','searchenginejournal.com', 
                                        'cmswire.com']),
    commonstats_df['before_site'].isin(['on24.com', 'gotomeeting.com', 'marketo.com', 'zoom.us', 'livestorm.co',
                                        'hubspot.com', 'drift.com', 'salesforce.com', 'clickmeeting.com',
                                        'qualtrics.com', 'workcast.com', 'livewebinar.com', 'getresponse.com', 
                                        'superoffice.com', 'myownconference.com', 'info.workcast.com']),
    commonstats_df['before_site'].isin([ 'neilpatel.com', 'ventureharbour.com', 'wordstream.com', 
                                        'business.tutsplus.com', 'convinceandconvert.com']),
    commonstats_df['before_site'].isin(['trustradius.com', 'g2.com', 'capterra.com', 'softwareadvice.com', 
                                        'learn.g2.com']),
    commonstats_df['before_site'].isin(['youtube.com', 'm.youtube.com', 'facebook.com', 'linkedin.com', 
                                        'business.linkedin.com', 
                                       ])
]

Aleshores creem una llista dels valors que volem assignar a cada condició.

segment_values = ['publisher', 'martech', 'consulting', 'reviews', 'social_media']

A continuació, creeu una columna nova i utilitzeu np.select per assignar-li valors utilitzant les nostres llistes com a arguments.

commonstats_df['segment'] = np.select(domain_conds, segment_values, default="other")
commonstats_df = commonstats_df[['before_site', 'segment', 'reach', 'wavg_rank']]
commonstats_df
nova columna per utilitzar np.selectCaptura de pantalla de l’autor, gener de 2022

Ara els dominis estan segmentats, cosa que significa que podem començar la diversió d’agregar per veure quins tipus de llocs es va beneficiar i es va deteriorar amb l’actualització.

# SERPs Before and After Rank
serps_stats = commonstats_df[['before_site', 'segment']]
serps_segments = commonstats_df.segment.to_list()


Estem unint les dades úniques abans de les SERP amb la taula de segments SERP creada immediatament a dalt per segmentar els URL de classificació mitjançant la funció de combinació.

La funció de combinació que utilitza el paràmetre “eft” és equivalent a la funció de concordança d’índex o de recerca virtual d’Excel.

serps_before_segmented = getstat_bef_unique.merge(serps_stats, on = 'before_site', how = 'left')
serps_before_segmented = serps_before_segmented[~serps_before_segmented.segment.isnull()]
serps_before_segmented = serps_before_segmented[['keyword', 'segment', 'device', 'search_volume', 'before_snippets', 
                             'before_rank', 'before_url', 'before_site']]
serps_before_segmented['count'] = 1
serps_queries = serps_before_segmented['keyword'].to_list()
serps_queries = list(set(serps_queries))
serps_before_segmented
unint les dades úniques abans de SERP amb la taula de segments SERPCaptura de pantalla de l’autor, gener de 2022

Agregació de les SERP anteriors:

def wavg_rank_before(x):
    names = {'wavg_rank_before': (x['before_rank'] * x['search_volume']).sum()/(x['search_volume']).sum()}
    return pd.Series(names, index=['wavg_rank_before']).round(1)

serps_before_agg = serps_before_segmented
serps_before_wavg = serps_before_agg.groupby(['segment', 'device']).apply(wavg_rank_before).reset_index()
serps_before_sum = serps_before_agg.groupby(['segment', 'device']).agg({'count': 'sum'}).reset_index()
serps_before_stats = serps_before_wavg.merge(serps_before_sum, on = ['segment', 'device'], how = 'left')
serps_before_stats = serps_before_stats.rename(columns = {'count': 'before_n'})
serps_before_stats
Agregació de les SERP anteriors.Captura de pantalla de l’autor, gener de 2022

Repetiu el procediment per a les SERP posteriors.

# SERPs  After Rank
aft_serps_segments = commonstats_df[['before_site', 'segment']]
aft_serps_segments = aft_serps_segments.rename(columns = {'before_site': 'after_site'})
serps_after_segmented = getstat_aft_unique.merge(aft_serps_segments, on = 'after_site', how = 'left')
serps_after_segmented = serps_after_segmented[~serps_after_segmented.segment.isnull()]
serps_after_segmented = serps_after_segmented[['keyword', 'segment', 'device', 'search_volume', 'after_snippets', 
                             'after_rank', 'after_url', 'after_site']]
serps_after_segmented['count'] = 1
serps_queries = serps_after_segmented['keyword'].to_list()
serps_queries = list(set(serps_queries))
def wavg_rank_after(x):
    names = {'wavg_rank_after': (x['after_rank'] * x['search_volume']).sum()/(x['search_volume']).sum()}
    return pd.Series(names, index=['wavg_rank_after']).round(1)
serps_after_agg = serps_after_segmented
serps_after_wavg = serps_after_agg.groupby(['segment', 'device']).apply(wavg_rank_after).reset_index()
serps_after_sum = serps_after_agg.groupby(['segment', 'device']).agg({'count': 'sum'}).reset_index()
serps_after_stats = serps_after_wavg.merge(serps_after_sum, on = ['segment', 'device'], how = 'left')
serps_after_stats = serps_after_stats.rename(columns = {'count': 'after_n'})
serps_after_stats
Repetiu el procediment per a les SERP posteriorsCaptura de pantalla de l’autor, gener de 2022

Amb les dues SERP resumides, podem unir-les i començar a fer comparacions.

serps_compare_stats = serps_before_stats.merge(serps_after_stats, on = ['device', 'segment'], how = 'left')
serps_compare_stats['wavg_rank_delta'] = serps_compare_stats['wavg_rank_after'] - serps_compare_stats['wavg_rank_before']
serps_compare_stats['sites_delta'] = serps_compare_stats['after_n'] - serps_compare_stats['before_n']
serps_compare_stats
Comparació de la classificació abans i després per paraula clauCaptura de pantalla de l’autor, gener de 2022

Tot i que podem veure que els llocs d’editors semblaven guanyar el màxim gràcies a més paraules clau classificades, una imatge sens dubte diria 1000 paraules més en una plataforma de PowerPoint.

Intentarem fer-ho remodelant les dades en un format llarg que el paquet de gràfics de Python afavoreix “plotnine”.

serps_compare_viz = serps_compare_stats
serps_rank_viz = serps_compare_viz[['device', 'segment', 'wavg_rank_before', 'wavg_rank_after']].reset_index()
serps_rank_viz = serps_rank_viz.rename(columns = {'wavg_rank_before': 'before', 'wavg_rank_after': 'after', })
serps_rank_viz = pd.melt(serps_rank_viz, id_vars=['device', 'segment'], value_vars=['before', 'after'],
                     var_name="phase", value_name="rank")
serps_rank_viz
serps_ba_plt = (
    ggplot(serps_rank_viz, aes(x = 'segment', y = 'rank', colour="phase",
                             fill="phase")) + 
    geom_bar(stat="identity", alpha = 0.8, position = 'dodge') +
    labs(y = 'Google Rank', x = 'phase') + 
    scale_y_reverse() + 
    theme(legend_position = 'right', axis_text_x=element_text(rotation=90, hjust=1)) + 
    facet_wrap('device')
)
serps_ba_plt
Classificació de GoogleCaptura de pantalla de l’autor, gener de 2022

I tenim la nostra primera visualització, que ens mostra com la majoria dels tipus de llocs van guanyar en rànquing, que és només la meitat de la història.

Vegem també el nombre d’entrades als 20 primers.

Escriptori vs telèfon intel·ligentCaptura de pantalla de l’autor, gener de 2022

Ignorant el segment “Altres”, podem veure que Martech i els editors van ser els principals guanyadors que van ampliar l’abast de la seva paraula clau.

Resum

Va necessitar una mica de codi només per crear un únic gràfic amb tota la neteja i l’agregació.

No obstant això, els principis es poden aplicar per aconseguir opinions ampliades de guanyador-perdedor com ara:

  • Nivell de domini.
  • Contingut intern del lloc.
  • Tipus de resultats.
  • Resultats canibalitzats.
  • Classificació dels tipus de contingut d’URL (blocs, pàgines d’oferta, etc.).

La majoria dels informes SERP tindran les dades per realitzar les vistes ampliades anteriors.

Tot i que és possible que no reveli explícitament el factor clau de classificació, les vistes us poden dir molt sobre què està passant, ajudar-vos a explicar l’actualització bàsica als vostres companys i generar hipòtesis per comprovar si sou un dels menys afortunats. per recuperar.

Més recursos:


Imatge destacada: Pixels Hunter/Shutterstock





Source link

Visualització dels guanyadors i perdedors de Google Core Update amb Python