Francesco Giammanco Exit Reader Mode

SEO tecnico per ASP.NET

Nella routine di un consulente SEO si lavora solo con una frazione di linguaggi di programmazione e frameworks, quasi dimenticandosi di quelli meno utilizzati, come ASP.NET.

Chi utilizza o possiede un sito in ASP.NET è un clienteche ha costruito la sua infrastruttura informatica tempo addietro o che ha dei bisogni specifici da soddisfare con soluzioni ad hoc.

Si tratta quindi di un cliente che ha (o ha avuto) un budget superiore alla fascia di siti semi-professionali che arricchiscono il monte ore lavorativo di uno specialista SEO.

Nonostante queste premesse, bisogna ricordarsi che i problemi di programmazione non sono problemi SEO, e se anche non saranno presenti due specialisti il lavoro di ottimizzazione sarà tangente al framework ma non ne richiederà la maestria.

Proprio per questo i capitoli dell’articolo saranno tecnici, ma non avranno la pretesa di trasformare uno specialista SEO in un programmatore, ma solo di segnalare semplici soluzione da adottare.

Una sorta di cassetta degli attrezzi da tirare fuori all’occorrenza.

Cos’è ASP.NET

ASP.NET è un’applicazione Microsoft che si basa sul CLR o Common Language Runtime.

Si tratta di un framework, un intermediario tra il sistema operativo e il software che lo utilizza, che supporta i maggiori linguaggi di programmazione tra i quali C#, Python e Perl, e che di fatto può utilizzare linee di HTML frammiste al proprio codice, che inizierà sempre con un’indicazione non duplicabile del tipo:

<%@ Page Language="C#" %>

Come ottimizzare il codice

Di seguito un elenco delle ottimizzazioni più comuni da realizzare, alcune delle quali possono essere approfondite su CodeProject.com.

Il primo caso e forse il più comune riguarda la duplicazione di contenuto percepito da Google in un sito che riporta il file della root nell’URL, ma che di fatto coincide con la Home del sito (es. www.example.com e www.example.com/default.aspx).

Si tratta dunque di porre rimedio integrando delle istruzioni nel codice o più semplicemente un redirect, valido anche per contrastare eventuali piccole discrepanze di segnalazione della URL/dominio al momento dell’installazione.

Il caso più comune è iniziare una procedura di installazione segnalando il sito senza il www. e in un secondo momento invece indicare la home includendolo.

Title

A meno che non venga segnalato diversamente, un sito in ASP.NET segnalerà un unico title in tutte le pagine.

Per far si che venga riconosciuto il tag title della pagina bisognerà aggiungere:

//assuming, that your <head runat="server" id="myHead"> 
if (Request.CurrentExecutionFilePath.Contains("example.aspx"))
{
    HtmlTitle title = new HtmlTitle();
    title.Text = "Example";
    myHead.Controls.Add(title);
}

Sitemap

La sitemap è fondamentale per indicare a Google tramite Search Console l’architettura del sito. Invece di installare un tool esterno, il framework è capace di generare un file XML per completare autonomamente la procedura.

using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Web;
using System.Xml;

namespace Mikesdotnetting
{
    
    public class Sitemap : IHttpHandler
    {

        public void ProcessRequest(HttpContext context) {
            context.Response.ContentType = "text/xml";
            using (XmlTextWriter writer = new XmlTextWriter(context.Response.OutputStream, Encoding.UTF8)) {
                writer.WriteStartDocument();
                writer.WriteStartElement("urlset");
                writer.WriteAttributeString("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9");
                writer.WriteStartElement("url");

                string connect = ConfigurationManager.ConnectionStrings["MyConnString"].ConnectionString;
                string url = "http://www.mikesdotnetting.com/";
                using (SqlConnection conn = new SqlConnection(connect)) {
                    using (SqlCommand cmd = new SqlCommand("GetSiteMapContent", conn)) {
                        cmd.CommandType = CommandType.StoredProcedure;
                        conn.Open();
                        using (SqlDataReader rdr = cmd.ExecuteReader()) {
                            // Get the date of the most recent article
                            rdr.Read();
                            writer.WriteElementString("loc", string.Format("{0}Default.aspx", url));
                            writer.WriteElementString("lastmod", string.Format("{0:yyyy-MM-dd}", rdr[0]));
                            writer.WriteElementString("changefreq", "weekly");
                            writer.WriteElementString("priority", "1.0");
                            writer.WriteEndElement();
                            // Move to the Article IDs
                            rdr.NextResult();
                            while (rdr.Read()) {
                                writer.WriteStartElement("url");
                                writer.WriteElementString("loc", string.Format("{0}Article.aspx?ArticleID={1}", url,  rdr[0]));

                                if (rdr[1] != DBNull.Value)
                                    writer.WriteElementString("lastmod", string.Format("{0:yyyy-MM-dd}", rdr[1]));
                                writer.WriteElementString("changefreq", "monthly");
                                writer.WriteElementString("priority", "0.5");
                                writer.WriteEndElement();
                            }
                            // Move to the Article Type IDs
                            rdr.NextResult();
                            while (rdr.Read()) {
                                writer.WriteStartElement("url");
                                writer.WriteElementString("loc", string.Format("{0}ArticleTypes.aspx?Type={1}", url, rdr[0]));
                                writer.WriteElementString("priority", "0.5");
                                writer.WriteEndElement();
                            }
                            // Finally move to the Category IDs
                            rdr.NextResult();
                            while (rdr.Read()) {
                                writer.WriteStartElement("url");
                                writer.WriteElementString("loc", string.Format("{0}Category.aspx?Category={1}", url, rdr[0]));
                                writer.WriteElementString("priority", "0.5");
                                writer.WriteEndElement();
                            }
                            writer.WriteEndElement();
                            writer.WriteEndDocument();
                            writer.Flush();
                        }
                        context.Response.End();
                    }
                }
            }
        }

        public bool IsReusable {
            get {
                return false;
            }
        }
    }
}

Migliorare il percorso per i crawler e validare le pagine

Sebbene non se ne senta più parlare molto, è meglio non utilizzare strumenti in Flash.

Alla stessa maniera, per evitare di dimenticarsi una piccola indicazione in HTML sarebbe opportuno analizzare le pagine con http://validator.w3.org/ , uno strumento che non passerà mai di moda per quanto mi riguarda.

Hreflang

Il tag hreflang per far riconoscere il target geografico dei contenuti è facile da implementare, e di fatto non è molto dissimile da come viene implementato su altre piattaforme.

Bisogna rendere il tag <link /> un controllo lato server aggiungendo gli attributi ID e runat:

<link id="AlternateLink" runat="server" rel="alternate" hreflang="zh-cn" />

per poi recuperare il valore dell’attributo hreflang con un codice del tipo:

string hrefLangAttr = AlternateLink.Attributes["hreflang"].ToString();

Description

Vi riporto del codice in C# valido per inserire la description nelle pagine, e poco sotto quello per il meta keywords, deprecato per Google ma non su Yandex.

Eliminare il codice relativo al meta nel caso in cui l’implementazione fosse pensata per un solo motore di ricerca (Google):

protected void Page_Init(object sender, EventArgs e)
{
  // Add meta description tag
  HtmlMeta metaDescription = new HtmlMeta();
  metaDescription.Name = "Description";
  metaDescription.Content = "Short, unique and keywords rich page description.";
  Page.Header.Controls.Add(metaDescription);
 
  // Add meta keywords tag
  HtmlMeta metaKeywords = new HtmlMeta();
  metaKeywords.Name = "Keywords";
  metaKeywords.Content = "selected,page,keywords";
  Page.Header.Controls.Add(metaKeywords);
}

Immagini e attributo ALT

Qui di seguito un esempio di come modificare il codice in modo tale che riporti l’attributo ALT delle immagini:

<asp:Image ID="imLogo" runat="server" AlternateText="Logo agenzia" ImageUrl="logo-ita.png" />

Il codice indicato sopra produrrà il seguente risultato HTML:

<img id="imLogo" src="logo.gif" alt="Logo agenzia" style="border-width:0px;" />

Problemi generati dal codice

Esistono una serie di problemi specifici di questo framework, generati da errore di trasposizione del codice o peggio ancora dall’evoluzione dei motori di ricerca non supportata dalle indicazioni più utilizzate dai programmatori.

Ecco un paio di esempi

Response.Redirect

Response.Redirect è un metodo utilizzato per portare il traffico alla versione della pagina prediletta, peccato solo che si tratti di un Redirect 302, di conseguenza percepito come temporaneo dai motori di ricerca.

Per risolvere il problema, da ASP.NET 4.0 è preferibile usare il comando Response.RedirectPermanent.

Datagrid e paging

Datagrid permette di generare una pagina con una serie di risultati, e molto spesso si utilizzare per generare un elenco di risultati di grandi dimensioni con un numero elevato di link, cosa che potrebbe peggiorare la considerazione che i crawler hanno della pagina/sito.

Per ovviare al problema basta usare paging, che genera gli stessi risultati ma suddivisi per pagine, creando appunto una paginazione.

Problemi generati da LinkButtons

Si tratta di un problema generato dalla struttura ASP.NET stessa, e che riguarda LinkButtons e la generazione dei link, appunto.

Si tratta di un modo per passare informazioni al server da un tag a hrefs che utilizza Javascript.

Si tratta di una soluzione che comporta l’utilizzo dell’URL rewriting per rendere più crawl friendly i link, non tanto perché risulterebbero incomprensibili, ma sicuramente più difficili da digerire delle normali indicazioni re-indirizzate.

Notifica per la pagina AMP. Il sistema serve per memorizzare la tua decisione sulla registrazione dei cookie.