Tal como adelante en esta entrada, voy a realizar una web sin utilizar WordPress, la plataforma donde llevo trabajando desde hace más de 10 años. La voy a hacer en dos fases principales, en una primera utilizando solamente HTML, CSS y JavaScript, y en una segunda incorporando PHP.

Foto de Markus Spiske en Pexels

Como IDE usaré PhpStorm con el plugin de Bootstrap 5, el marco de trabajo de HTML, CSS y JavaScript más popular para crear sitios web adaptables a móviles.

Tabla de contenidos,

Primer día, creación de una web básica

Elección de plantilla de Bootstrap 5

Con PhpSorm podremos crear una plantilla básica; pero tendríamos todo el trabajo de diseño por delante, ya que con ella solamente se muestra por pantalla el texto «Hello world! This is HTML5 Boilerplate.»

phpStorm

Para bootstrap 5 multitud de diseñadores han diseñado plantillas al igual que hacen los diseñadores de temas de WordPress, con lo que es una buen punto de partida para empezar a trabajar.

Plantillas de Bootstrap las podemos encontrar en sitios como:

Después de mirar unas decenas de plantillas, elijo el Construct – Free Construction HTML Template por las siguientes razones:

  • Me gusta el diseño limpio a ancho completo. Foto principal sobre el que se superpone el logo y el menú. Una caja en blanco se superpone por la esquina inferior derecha. Menú que cambia al ir bajando. Etc.
  • Buena adaptación a móviles. Sin este punto, no hubiera servido para nada que el diseño para escritorio me gustara.
  • Calidad del código. Cada sección está claramente diferenciada por lo que voy a poder mover, eliminar y personalizar con facilidad el html. El CSS y el JavaScript está muy bien construido.
  • Si bien tiene un esquema de colores atractivo, los voy a cambiar porque no son exactamente los que estoy buscando.

Construct – Free Construction HTML Template

No todo es perfecto. He encontrado en la plantilla un defecto muy gordo, un error de SEO muy grave que tendré que solventar manualmente: todos los elementos principales de la página son H1, cuando en una dirección web solamente ha de haber un H1. No se puede cambiar simplemente los H1 a H2, porque perderían las características del tipo de letra, tendré que hacer cambios en el CSS.

Adaptación de colores, textos y secciones

A continuación, he realizado unos primeros cambios en los colores, sombras imágenes y textos para comprobar si la primera impresión de la plantilla era correcta y es la plantilla que quiero utilizar para este proyecto.

Dado que el fondo del logo es diferente cuando carga la página respecto a cuando me desplazo, el logo que tenía preparado no sería por lo que he tenido que hacer un logo blanco a partir del original utilizando Pixlr.

He tocado el CSS para cambiar el tamaño del logo, ya que el que venía en la plantilla era para mi gusto demasiado pequeño.

El resultado conseguido hasta ahora es el siguiente:

Bajando por la página vamos viendo el resto del contenido. Como se puede observar el menú cambia de color de fondo.

Seguimos bajando.

Y llegamos al pie de página

Segundo día, corrección de errores

El segundo día lo dedicaremos a corregir errores.

Error en la versión móvil

La versión móvil tiene un error, ya que el ancho de pantalla es superior al contenido.

Si bajamos por la página encontramos dónde está el problema.

La imagen es más ancha que el tamaño de la pantalla, lo que hace descuadrar todo. La solución es reducir el tamaño de la imagen.

Mal valor para atributo href

Para comprobar que todo va correctamente he realizado una validación del html con Markup Validation Service. Encontrado el siguiente error:

Aunque el funcionamiento del enlace es correcto, eliminamos los espacios del enlace. El css queda así:

<p>
  Teléfono: <a href="tel:+34911670620" rel="nofollow" target="_blank" >+34 911 670 620</a>
</p>

Sustitución de H1 por H2 para no penalizar el SEO

Para no tener problemas con el SEO vamos a sustituir los h1 por h2, en una url determinada solamente puede haber un h1s. Para no perder el formato de la web, voy aprovechar que en el html no hay h5. En el archivo main.css elimino todas las referencias a h5. Después sustituyo todos los h4 por h5. Después los h3 por h4, los h2 por h3 y por último los h1 por h2, salvo en la clase «hero-content» donde mantendré el h1, que será el correspondiente a la página principal de la web.

Como podemos ver a través de la extensión de Chrome de Moz, la página ya tiene solamente un H1.

Problemas con el CSS

PHPStorm te alerta de problemas con el CSS, que si bien no afectan a la apariencia de la web, crean errores en la carga que retrasan su carga y penalizan su posicionamiento en Google.

En nuestro caso ha detectado 55 problemas. Si te pones encima de cada uno te da más detalles del mismo y PHPStorm te sugiere como lo puedes corregir.

Análisis de rendimiento

Antes de continuar, es un buen momento de conocer el rendimiento de la web en estos momentos. Para ello voy a utilizar la herramienta de Google PageSpeed.

Y en el escritorio:

De momento el rendimiento de la página tanto en móvil como escritorio es excelente.

Tercer día, plantilla de página y página de artículo de blog

Para la página de Contacto y otras páginas partiremos de la página principal. Vamos a crear una página vacía que usaremos como base del resto de las páginas. En la página vacía mantendremos el menú y el pie de pagina. Tendremos que poner una cabecera con fondo azul para poder mantener el efecto del menú cambiando de color al desplazarse el scroll hacia abajo.

Plantilla de página

La cabecera en la página principal se llamaba «hero» y tenía como clases hero-area y hero-content, ahora las clases serán header-area y header-content. En main.css duplicamos las reglas css de hero y las renombramos a header, cambiando el fondo. El resultado final es:

Antes de continuar, vamos a probar la página en el móvil.

Resultando todo correcto por lo que podemos continuar.

Página de artículo de blog

Basado en la plantilla de página he creado una página con un artículo para el blog.

He creado dos secciones nuevas, una con clase post-section-header y otra con clase post-section. La diferencia es que en la primera la foto principal queda sobreescrita parcialmente en escritorio por el texto. En post-section si añadiera fotos, aparecería en su lugar correspondiente del texto. Para conseguir esto he tenido que poner la parte correspondiente de css en main.css.

.post-section-header .post-image {
  position: absolute;
  right: 0;
  top: 0;
  width: 52%;
  height: 100%;
  z-index: -1;
}
.post-section-header .post-image img {
  width: 100%;
  height: 100%;
  object-position: center;
  object-fit: cover;
}

Para visualizar la página en el móvil voy a añadir unas reglas en el css para que la foto se vea en la parte superior del artículo y para reducir el tamaño de los h2 y h3:

@media (max-width: 1000px) {
  .post-section-header .post-content {
    padding: 020px 30px 0px 30px;
  }
  .post-section-header .post-image {
    top: 100px;
    width: 100%;
  }
  .post-section-header .post-image img {
    object-fit: contain;
  }
  .post-section h2 {
    font-size: 30px;
    font-weight: 900;
    color: #DB0EB7;
    margin-bottom: 15px;
    display: inline-flex;
    align-items: center;
  }
  .post-section h3 {
    font-size: 25px;
    font-weight: 900;
    color: #01012c;
    margin-bottom: 15px;
    display: inline-flex;
    align-items: center;
  }
}

Quedaría así:

Cuarto día: página de contacto y de agradecimiento

Pasamos a realizar la parte más importante de esta fase de la web, la página de contacto donde incluiremos un formulario y la página de agradecimiento donde podremos ver los datos enviados en el formulario mediante javascript.

Página de Contacto

Como ya hemos hecho con la página del artículo de blog vamos a partir de una copia de la plantilla de página. En esta ocasión añadiremos una sección a la que asignaremos la clase «contact-section». En cada campo utilizaremos las clases que nos proporciona bootstrap 5.0 para darle formato a los campos.

El formulario lo voy a hacer de tipo get, para recoger en la página destino el contenido en la url.

<form action="https://aprendizajeprofundo.es/gracias.html" method="GET" id="contact-form" class="contact-form">

Los campos para el nombre, el email, el teléfono y un mensaje son similares entre ellos. Por ejemplo para el campo obligatorio email, el código sería:

<div class="col-md-6">
  <div class="single-form">
    <input type="email" class="form-input" id="email" name="email" placeholder="Email" required>
  </div>
</div>

En placeholder escribo el texto que quiero que aparezca en el campo.

En el formulario quiero que se elija de una lista de servicios, para ello escribo:

<div class="col-md-6 pt-2">
  <div class="form-group">
                    <select class="form-control" id="subject" name="subject">
                        <option value="">Selecciona un servicio...</option>
                        <option value="Limpieza de datos">Limpieza de datos</option>
                        <option value="Chat Boots">Chat Boots</option>
                        <option value="Análisis Predictivo">Análisis Predictivo</option>
                        <option value="Clasificación automática">Clasificación automática</option>
                        <option value="Visión Artificial">Visión Artificial</option>
                        <option value="Seguridad">Seguridad</option>
                    </select>
   </div>
</div>

Y para cumplir con la ley de protección de datos pongo una casilla de verificación de que se acepta la política de privacidad:
<div class="custom-control custom-checkbox pt-10">
                  <input type="checkbox" class="custom-control-input" id="customCheck1" required>
                  <label class="custom-control-label" for="customCheck1">Acepto la política de privacidad</label>
                  <br>
</div>

Añado una foto a la página y reglas css a main.css obteniendo como resultado:

En este caso hemos optado por ocultar la imagen en table y móvil. No aporta nada para el formulario de contacto y si lo ponemos arriba del formulario, habría que hacer scroll para acceder a éste, algo no conveniente si queremos que nos contacten. En el escritorio en cambio tiene sentido ya que quedaría el formulario como único elemento con demasiado espacio vacío a su alrededor.

Para ello añadimos:

@media only screen and (min-width: 768px) and (max-width: 991px) {
  .contact-section .contact-image {
    display: none;
  }
}

@media (max-width: 767px) {
  .contact-section .contact-image {
    display: none;
  }
}

Quedando en el móvil así:

Página de gracias

Esta página es muy sencilla, simplemente vamos a dar las gracias por el mensaje y vamos a incluir los datos que aparecen en la url. En la siguiente fase de la web, cuando utilicemos PHP ya estaremos en condiciones de almacenar los datos.

El código html añadido a la plantilla de página sería:

<!-- ========================= gracias-section start ========================= -->
<section id="gracias" class="gracias-section">
  <div class="container">
    <div class="row">
      <div class="col-lg-12">
        <div class="section-title mb-60 pt-50">
            <p>Muchas gracias por su mensaje. Antes de 24 horas laborables nos pondremos en contacto con usted.</p>
            <h5 class ="pt-20">Datos recibidos</h5>
            <p><strong>Nombre: </strong><a id="name">Nombre</a></p>
            <p><strong>Email: </strong><a id="email">Email</a></p>
            <p><strong>Móvil: </strong><a id="number">Móvil</a></p>
            <p><strong>Tema: </strong><a id="subject">Tema</a></p>
            <p><strong>Mensaje: </strong><a id="message">Mensaje</a></p>
        </div>
      </div>
    </div>
  </div>
<!-- ========================= gracias-section end ========================= -->

Los id, "name", "email", "number", "subject" y "messge" son los que nos permitirán mediante javascript ver los datos enviados.

En el javascript crearemos una función getQueryVariable para obtener el contenido de la url.

function getQueryVariable(variable) {
    var query = window.location.search.substring(1);
    var vars = query.split("&");
    for (var i=0; i < vars.length; i++) {
        var pair = vars[i].split("=");
        if (pair[0] == variable) {
            return pair[1];
        }
    }
    return " [ *** Dato no facilitado *** ]";
}

Con esta función obtendríamos caracteres como %40 en la url, por lo que debemos utilizar la función decodeURIComponent para decodificarlo en este caso a @. Para recuperar los espacios y que no aparezcan como + he creado la siguiente función:

function sustituyeMas(texto){
    var contenido=""
    for (var i = 0; i < texto.length; i ++){
       contenido += (texto.charAt(i) == "+") ? " " : texto.charAt(i);
     }//fin del for

    return contenido;
}

Por último vamos a sustituir el valor de los elementos que los vamos a obtener por su id, quedando así las llamadas:

document.getElementById("name").innerHTML= sustituyeMas(decodeURIComponent(getQueryVariable('name')));
document.getElementById("email").innerHTML= sustituyeMas(decodeURIComponent(getQueryVariable('email')));
document.getElementById("number").innerHTML= sustituyeMas(decodeURIComponent(getQueryVariable('number')));
document.getElementById("subject").innerHTML= sustituyeMas(decodeURIComponent(getQueryVariable('subject')));
document.getElementById("message").innerHTML= sustituyeMas(decodeURIComponent(getQueryVariable('message')));

El resultado final para la url:

gracias.html?name=José+María+Jiménez+Shaw&email=prueba%40gmail.com&number=123456789&subject=Análisis+Predictivo&message=Esta+es+una+prueba+de+mensaje

sería:

En el móvil se vería algo similar.

Quinto día: mejora de los contenido de la página principal

Ya nos estamos acercando al final de esta fase del proyecto. Antes de añadir alguna mejor en javascript, vamos a retomar la página principal donde quedaban pendientes por subir algunos contenidos.

Tras cambiar textos, fotos, eliminamos los botones que de momento no están operativos porque no tenemos páginas preparadas para ampliar información. Si más adelante se crearan los volvería a colocar. El único botón que mantengo es el que enlaza con el artículo del blog; pero lo cambio de color al #DB0EB7 que estoy utilizando en la página para destacar contenidos.

En la plantilla inicial había tres iconos Lineincons obtenidos a través del fichero LineIcons.2.0.css. Hago los siguientes cambios tras buscar iconos más apropiados para la web que estamos realizando:

  • lni-thought por lni-eraser
  • lni-ruler-pencil por lni-scholl-bench-alt
  • lni-bricks por lni-bar-chart

La goma me parece más adecuada para limpieza de datos que un pensamiento, un pupitre para entrenamiento que un lápiz y una regla, y un gráfico de barras para predicciones que unas cajas apiladas. Cuando ponemos el ratón sobre el icono, este cambia a su inverso, como podemos apreciar en la captura anterior.

Por último creamos las páginas correspondientes al aviso legal y la política de privacidad. Las enlazamos desde los pie de página de cada una de las páginas realizadas y la política de privacidad desde la página de contacto.

Sexto día: añadimos plugins jQuery

jQuery es una biblioteca multiplataforma de JavaScript y la usaremos para darle funcionalidad a la web.

El procedimiento para usarlo es añadir al final de las páginas donde queramos usar los plugin el siguiente script:

<script src="https://code.jquery.com/jquery-3.5.1.min.js"
        integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>

Debajo iremos poniendo las llamadas a los plugins en JavScript que usen jQuery.

Venom Button WhatsApp

No hay nada más frustrante para un futuro cliente el no poder contactar fácilmente con los que están detrás de una web. Si bien el que haya un formulario de contacto es un medio para dicho contacto, hoy en día la gente prefiere contactar por WhatsApp. Si queremos generar negocio con una web conviene tener un botón para que contacten con nosotros fácilmente.

Tras una búsqueda por internet al final me he decantado por Venon Button WhatsApp y aunque en teoría el proceso es fácil, le he dedicado tiempo hasta que lo he dejado funcionando. El problema principal ha sido que el icono de WhatsApp estaba por debajo de otros elementos y no lo veía.

El proceso para la instalación es el siguiente:

Copiar el archivo venom-button.min.css a. directorio /assets/css/ donde guardo el resto de los archivos css

  • Copiar el archivo venom-button.min.css al directorio /assets/css/ donde guardo el resto de los archivos css
  • Copiar el archivo venom-button.min.js al directorio /assets/css/ donde guardo el resto de los archivos js

  • Añadir el css en el <head> de la página

<link href="https://www.jqueryscript.net/css/jquerysctipttop.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="assets/css/venom-button.min.css">

  • Añadir el JavaScript al final de la página (antes de </body>), debajo del script de jquery

<script type=»text/javascript» src=»assets/js/venom-button.min.js»></script>

  • Añadir a la página un <div> para mediante css sustituir por la imagen de WhatsApp

<div id="myButton"></div>

  • Añadir al final de main.css el código para el botón de WhatsApp aparezca por encima de cualquier elemento

#myButton{ z-index: 99; }

 

  • Añadir a main.js la llamada a $(‘#myButton’).venomButton

Lo añadimos a window.onload para que se muestre el botón cuando la página se cargue.

window.onload = function () {
   window.setTimeout(fadeout, 500);

       $('#myButton').venomButton({
           phone: '+34XXXXXXXXX',
           popupMessage: 'Hola, ¿cómo puedo ayudarte?',
           message: "Hola José María, ",
           showPopup: true,
           position: "left",
           linkButton: true,
           showOnIE:  false,
           headerTitle: '¡Bienvenido!',
           headerColor: '#25d366',
           backgroundColor: '#25d366',
           autoOpenTimeout: 100000,
           buttonImage: '<img src="assets/img/whatsapp.svg" />'
       });
}

El resultado es el siguiente:

No voy a instalar el botón de WhatsApp en más páginas, ya que me interesa que lo use el que está navegando por la página principal como posible cliente de mis servicios.

jQuery Floating Social Share

En la página del artículo vamos a instalar jQuery Floating Social Share para que los lectores puedan compartillo en sus redes sociales.

Los pasos para la instalación son los siguientes:

  • Descomprimir el archivo
  • Copiar jquery.floating-social-share.min.css en el directorio assets/css/ y jquery.floating-social-share.min.css en assets/js/

  • Añadir en el <head> de aproximacion-verdadera-inteligencia-artificial.html el css

<link rel="stylesheet" type="text/css" href="assets/css/jquery.floating-social-share.min.css" />

  • Añadir antes de </body> el JavaScript de jQuery y del plugin

 <script type="text/javascript" src="https://code.jquery.com/jquery-latest.min.js"></script>
 <script type="text/javascript" src="assets/js/jquery.floating-social-share.min.js"></script>

  • Añadimos en main.js a window.onscroll, por lo que los iconos aparecerán cuando nos desplacemos hacia abajo

        $(".post-section").floatingSocialShare({
                place: "top-left", // alternatively content-left, content-right, top-right
                counter: false, // set to false for hiding the counters of buttons
                facebook_token: null, // To show Facebook share count, obtain a token, see: https://stackoverflow.com/questions/17197970/facebook-permanent-page-access-token/43570120#43570120
                buttons: [
                    "twitter", "facebook", "linkedin", "telegram", "whatsapp"
                ],
                title: document.title, // your title, default is current page's title
                url: window.location.href,  // your url, default is current page's url
                text: { // the title of tags
                    'default': 'share with ',
                    'facebook': 'share with facebook',
                    'twitter': 'tweet'
                },
                text_title_case: false, // if set true, then will convert share texts to title case like Share With G+
                description: $('meta[name="description"]').attr("content"), // your description, default is current page's description
                media: $('meta[property="og:image"]').attr("content"), // pinterest media
                target: true, // open share pages, such as Twitter and Facebook share pages, in a new tab
                popup: true, // open links in popup
                popup_width: 400, // the sharer popup width, default is 400px
                popup_height: 300 // the sharer popup height, default is 300px
            }

En buttons hemos seleccionado las redes sociales que queremos que aparezcan y en qué orden. En place elegimos dónde queremos que aparezcan.

  • En main.css añadimos z-index: 99 para que los iconos de compartir superpongan a cualquier elemento

.post-section {
position: relative;
z-index: 99;
}

Los iconos para compartir la página quedarían así

Séptimo día: retoques finales

Google Analytics

Vamos a empezar instalando Google Analytics. Damos de alta el dominio y obtenemos la propiedad de Google Analytics 4. Instalamos sus scripts en todas las páginas justo antes de </body>.

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-C8BLZS9ZN7"></script>
<script>
   window.dataLayer = window.dataLayer || [];
   function gtag(){dataLayer.push(arguments);}
   gtag('js', new Date());

   gtag('config', 'G-C8BLZS9ZN7');
</script>

Cookies

Para el consentimiento de las cookies usaremos el servicio que ofrece cookieboot que es gratuito hasta 100 páginas.

Nos dan 2 scripts, uno para colocarlo en la página de Política de Cookies que crearemos utilizando pagina.html y otro lo utilizaremos en todas las páginas por las que se pueda entrar en la web de forma directa (por ejemplo no sería necesario en la página gracias.html).

Para la página politica-cookies.html colocaremos el script directamente donde queramos que aparezca el código, en nuestro caso en el div de la clase «container». No funcionaría si lo colocáramos externamente en un fichero .js.

<div class="container">
        <br>
        <script id="CookieDeclaration" src="https://consent.cookiebot.com/dda723ad-7af6-4f66-9ddb-122f54a5f8a5/cd.js" type="text/javascript" async></script>
        <br>
</div>

Este código solamente funciona si lo ejecutamos en el dominio con el que nos hemos registrado. En local aparecería el mensaje:

La página en un servidor funciona correctamente:

El script de consentimiento ha de ser el primer script que ha de aparecer en una página. Solamente nos saldrá la primera vez que entremos en la web para que aceptemos las cookies.

 <!-- ========================= JS here ========================= -->
<script id="Cookiebot" src="https://consent.cookiebot.com/uc.js" data-cbid="dda723ad-7af6-4f66-9ddb-122f54a5f8a5" data-blockingmode="auto" type="text/javascript"></script>

Y solamente funcionará si tenemos la página subida al hosting porque hace una comprobación previa de si estamos en el dominio correcto. Quedaría así:

Problemas con el botón de WhasApp

Al instalar los el script en la página principal para el consentimiento de cookies ha generado un efecto indeseado. El icono de WhatsApp aparece dos veces.

Esto es debido a que instalamos $(‘#myButton’).venomButton() dentro de window.onload y el script lo vuelve a cargar una vez que aceptamos las cookies.

Para resolverlo, modificamos el código JavaScript añadiendo una variable que chequeará si es la primera vez o no que se carga window.onload. Si es la segunda vez no se ejecutará la creación de un botón de Whatsapp.

    let noPrimeraVez = false; // para evitar que el botón WhatsApp se ejecute dos veces
    
   window.onload = function () {

		window.setTimeout(fadeout, 500);

        // Botón de WhatsApp
        if (noPrimeraVez == false)
        {
            $('#myButton').venomButton({
                phone: '+34XXXXXXXXX',
                popupMessage: 'Hola, ¿cómo puedo ayudarte?',
                message: "Hola José María, ",
                showPopup: true,
                position: "left",
                linkButton: true,
                showOnIE:  false,
                headerTitle: '¡Bienvenido!',
                headerColor: '#25d366',
                backgroundColor: '#25d366',
                autoOpenTimeout: 100000,
                buttonImage: '<img src="assets/img/whatsapp.svg" />'
            });

            PrimeraVez = true;
        }

	}

Creo el archivo sitemap.xml y robots.txt

Un sitemap es un archivo XML que contiene una lista de todas las páginas de un sitio web que deseas que indexen los buscadores. El mío sería:

El robots.txt es un archivo que da instrucciones a los motores de búsquedas para que sepan que urls deben rastrear. El mío quedaría así:

Con sitemap.xml le estoy diciendo al buscador que páginas son importantes en la web y quiero que estén indexadas y con robots.txt le estoy indicando que cuando el buscador llegue a mi web no pierda el tiempo rastreando páginas que no son relevantes para la búsqueda.

Las páginas que aparecen en robots.txt con disallow no las rastrea el buscador; pero pueden estar indexadas. Para impedirlo debo añadir al html de dichas páginas en el <head> la siguiente metaetiqueta:

<meta name="robots" content="noindex">

Alta en Google Search Console

Google Search Console es un servicio gratuito de Google que ayuda a supervisar, mantener y solucionar los problemas que pueda tener tu web en los resultados de la Búsqueda de Google.

Tras darme de alta informo a Google Search Console de la url de sitemap.xml, lo que acelerará la indexación de la página en Google.

Divido el CSS en varios archivos

Tenemos un archivo main.css que contiene todo el css necesario para todas las páginas. Vamos a trocearlo en varias partes. Por un lado vamos a obtener un archivo que llamaremos common.css que contendrá el css común, el relativo al header y al footer. Este css será llamado desde todas las páginas.

Ahora vamos a crear un css específico para cada página:

  • index.css
  • contacto.css
  • gracias.css
  • post.css
  • legal.css (lo usamos en aviso-legal.html y en politica-privacidad.html)

De esta manera reducimos los tiempos de carga de la página al cargar en cada una solamente el css que necesita

Elimino carga de archivos JavaScript de las páginas que no lo necesitan

El siguiente JavaScript:

<script src="assets/js/count-up.min.js"></script>
<script src="assets/js/wow.min.js"></script>

sirve para animar los datos de Acerca de de la página principal. Por lo que no tiene sentido que se cargue en el resto de las páginas.

Cambio de formato de imágenes

Google clasifica las webs en rápidas, si su FCP (First Contentful Pain) es menor de 1 segundo, normales si su FCP está entre 1 y 2,5 segundos y lentas para un FCP mayor de 2,5 segundos. Según distintos usuarios los usuarios no tienen paciencia para esperar a que una web lenta cargue, por lo que es necesario optimizar tu web para que sea al menos normal aunque lo ideal es conseguir que sea rápida.

Uno de los factores que influyen en la velocidad de carga es el tamaño de las imágenes por lo que no debemos subirlas de un tamaño mayor del que vayamos a usarlas en la web. Además debemos buscar formatos que las compriman manteniendo la calidad de las mismas.

Una opción para mejorar la velocidad de carga es que las imágenes tengan el formato JPEG progresivo que muestra una versión de baja resolución de la imagen en el navegador Web mientras se descarga la imagen completa.

Otro formato con compresión creado por Google es el webP, proporciona un excelente compresión, con pérdida de información (como JPEG) y transparencia (como PNG).

Haciendo una prueba con Gimp para tranformar de PNG a JPEG progresivo con las dos imágenes con más peso de la web obtengo el siguiente resultado:

  • La foto del about que está en PNG si la transformamos a JPEG progresivo baja su peso de 117 KB a 24 KB
  • La foto del artículo que está en JPG si la transformamos a JPEG progresivo baja su peso de 42 KB a 33 KB

Probando ahora con Pixlr para cambiar el formato de las mismas imágenes a webP, obtengo el siguiente resultado:

  • La foto del about que está en PNG si la transformamos a webP baja su peso de 117 KB a 21 KB
  • La foto del artículo que está en JPG si la transformamos a webP baja su baja su peso de 42 KB a 31 KB

Los resultados muestran una ligera ventaja en tamaño del formato webP frente a a JPEG progresivo. A nivel visual ambos formatos son indistinguibles.

Finalmente opto por utilizar el formato webP ya que así puedo mantener la transparencia de las imágenes PNG. Las mejoras obtenidas en el resto de las fotos son las siguientes:

  • Con la transformación de png a webp, en los logos normal e inverso, pasamos de 20 KB y 23 KB a 10 KB y 14 KB respectivamente. Comprobamos antes de seguir que no hay diferencias visuales en los logos por lo que continuamos cambiando el formato en el resto de las imágenes de la web.
  • La foto principal de la portada pasa de 48 KB a 31KB
  • Las fotos de los servicios pasan de 14 KB, 22 KB, 27 KB, 28 KB, 22 KB y 18 KB a 8 KB, 14 KB, 24 KB, 21 KB, 14 KB y 14 KB respectivamente.
  • La foto blog de la portada pasa de 21 KB a 14 KB
  • La foto de cabecera para todas las páginas que no son la principal pasa de 3 KB y a 2 KB
  • La foto de la página de contacto pasa de 23 KB a 14 KB

A pesar de que el ahorro parecen de pocos KB, en muchos casos se reduce el tamaño de la imagen en un 60%. Hemos partido además de imágenes con tamaños optimizados, el ahorro en espacio desde la imagen original es de varios órdenes de magnitud, de MB a KB.

Resumen del trabajo realizado

Para crear la web estática elegimos una plantilla de Bootstrap5 para nuestra página principal que luego hemos ido adaptando a nuestras necesidades, cambiando colores, textos y secciones.

También tuvimos que realizar cambios en el CSS y en el html para corregir errores, tanto los detectados por PhpStorm como de SEO en la plantilla.

Además de la página principal hemos creado una página para un artículo, una página de contacto, una página de gracias más las páginas legales (aviso legal, política de privacidad y política de cookies).

En la página de contacto hemos creado un formulario donde solicitamos de forma obligatoria un email, pedimos nombre, teléfono y donde podemos seleccionar un servicio y dejar un mensaje. El formulario dispone de una casilla de verificación que se debe marcar para enviar el formulario que corresponde a la aceptación de la política de privacidad. Bootstrap5 proporciona clases CSS para el formato del formulario y código JavaScript para el control de errores en el lado del cliente.

Cuando se envía el formulario se carga la página de gracias con los datos introducidos en el formulario como parámetros de la url. Mediante un código JavaScript que he desarrollado recojo, dichos datos y los muestro en la página.

Utilizando un plugin de jQuery hemos añadido un botón de WhatsApp en la página principal para facilitar el contacto de los usuarios. También hemos usado otro plugin de jQuery para dar la opción de compartir la página del artículo en las redes sociales.

Dimos de alta la web en Google Analytics, en Google Search Console y en Cookiebot, para poder analizar las visitas, facilitar las búsquedas de Google y gestionar el consentimiento de cookies.

Reducimos el css y JavaScript que se carga en las páginas, eliminando lo que no es necesario.

Cambiamos el formato de las imágenes a webp para aumentar la compresión de las mismas.

El siguiente paso será recoger el contenido que se deje en el formulario de contacto y enviarlo por email. Para esto necesitaremos usar PHP por lo que será parte de la siguiente etapa de este proyecto.

Te invito a que visites el resultado obtenido hasta ahora, la web Aprendizaje Profundo, y que me des tu opinión en los comentarios.

Shares
Share This