Haciendo del Desarrollo y la Arquitectura Web, ciencia y pasión.

Google Api PageSpeed & Symfony

En esta entrada os voy a hablar del uso de Apis de Google. Google tiene infinidad de servicios disponibles para ayudarnos en nuestros desarrollos, Google Webmasters, Google AnaliticsMapas, History location, etc . La api que vamos a usar es PageSpeed, un servicio que ofrece Google para poder averiguar el pagerank de una web. Para hacerlo más interesante crearemos un servicio dentro del contenedor de servicios de una aplicación Symfony y lo llamaremos desde nuestro controlador. Este servicio nos da una serie de datos, como velocidad, recursos, infracciones, errores. Aquí teneis la dirección del servicio para ver que ofrece https://developers.google.com/ speed/pagespeed/insights/ Si entramos y revisamos esta misma web, veamos lo que nos dice:

resultado_pagespeed_dg_web

 

No esta mal del todo: un 90/100, alguna cosa a revisar, muy interesante. Por curiosidad lanzamos al mismo Google y nos da un 97/100.

Empezaremos por definir nuestro servicio en el archivo de configuracion services.yml.

 

parameters:
#    parameter_name: value
     pageRank.class: daniel\D1Bundle\Services\CurlService


services:
    my_api_call:
        class:        "%pageRank.class%"
        arguments:    [url]

Excelente, ya tenemos nuestro servicio configurado, al que hemos llamado my_api_call, que invocará a la clase definida en el parametro pageRank.class con valor CurlService, declarado dentro de mi bundle. Muy bien, ahora nos vamos a la carpeta de servicios dentro del bundle donde éstos se alojaran:



namespace daniel\D1Bundle\Services;

class CurlService {

    public function __construct() {

    }

    public function pageSpeedReport($url) {


        $ch = curl_init();

        $key = "********AQUI VA LA KEY DE GOOGLE*********";
        $apiUrl = "https://www.googleapis.com/pagespeedonline/v2/runPagespeed?url=$url&strategy=desktop&key=$key";
        $optArray = array(
            CURLOPT_URL => $apiUrl,
            CURLOPT_RETURNTRANSFER => true
        );

        curl_setopt_array($ch, $optArray);

	// execute request and get response
        $result = curl_exec($ch);

        return $result;
    }

}

El servicio en cuestion es trivial, previamente hay que solicitar una key, a google para invocar el serivicio. Esto es lo habitual en la Apis de Google, pides una key que te identifica y a la cual esta asociada los privilegios de uso. Si por ejemplo fuera de Google maps, es gratutia hasta un cierto numero de peticiones, 25000 por dia creo, a partir de este numero ya hay que pasar caja. establecemos las opciones de Curl, ejecutamos con exec y retornamos. Siguiente paso: creamos nuestro controller. Como de costumbre nuestro metodo extiende de Controller:

    /**
     * @Route("/pageSpeed", name="pagespeedform")
     * @Template()
     */
    public function PageSpeedAction(Request $request) {

        $url = $request->get('url');

        if ($url) {
            $curl = $this->container->get("my_api_call");
            $result = $curl->pageSpeedReport($url);
            $resultArray = json_decode($result);


            $score = $resultArray->ruleGroups->SPEED->score;
            $title = $resultArray->title;
            $numberResources = $resultArray->pageStats->numberResources;
            $imageResponseBytes = $resultArray->pageStats->imageResponseBytes;


            $rules = $resultArray->formattedResults->ruleResults;
            $rulesValues = array();
            foreach ($rules as $key => $value) {
                $rulesValues[] = array('nameRule' => $key,
                    ' ruleMesssage' => $value->ruleImpact > 10 ? 
                        $this->parseMessage($value->urlBlocks[0]->header->format, $value->urlBlocks[0]->header->args) :
                    '', 'ruleImpact' => $value->ruleImpact);
            }
            return $this->render('danielD1Bundle:PageSpeed:pages.html.twig', array('report' => true,
                        'score' => $score, 'title' => $title,
                        'numberResources' => $numberResources,
                        'imageResponseBytes' => $imageResponseBytes,
                        'rulesvalues' => $rulesValues,
                        'url' => $url
            ));
        } else {
            return $this->render('danielD1Bundle:PageSpeed:pages.html.twig', array('report' => false));
        }
    }

    private function parseMessage($message, $params) {
        foreach ($params as $param) {
            $message = str_replace("{{" . $param->key . "}}", $param->value, $message);
        }
        return $message;
    }

Básicamente invocamos el servicio de nombre my_api_call, decodificamos la salida de pageSpeedReport y lo mandamos a la vista. De todos los parametros obtenidos, uno especialmente, Ruleimpact, nos indica el impacto sobre el rendimiento de nuestra web, de tal manera que si supera en 10, entramos en éste y lo revisamos con mas detalle.

Por ultimo la vista, un formulario y la lista con los resultados de PageSpeed. Para que tenga un aspecto más elegante añadimos la css de Bootstrap:

{% extends '::frontend.html.twig' %}
{% block title %}PageSpeed test{% endblock %}
{% block body %}
{% for flashMessage in app.session.flashbag.get('mensaje') %}
<span class="alert-success">
{{ flashMessage }}
<hr />
</span>
{% endfor %} <div class="form">
<h2>Page Speed test Api</h2>

<form class="form-horizontal" role="form" method="post" action="{{path('pagespeedform')}}">
<div class="form-group">
<label for="inputUrl3" class="col-sm-2 control-label">Url</label>
<div class="col-sm-10">
<input type="url" name="url" class="form-control" id="inputUrl3" placeholder="{{(url!='')?url:'Introduzca su Url'}}" />
</div>
</div> lt;div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Analizar</button>
</div>
</div>
</form>
</div>

{% if report %}
<div class="report">

<h2>Report</h2>
<ul>
<li> Score: {{score}} </li>
<li> Title: {{title}} </li>
<li> NumberResources: {{numberResources}} </li>
<li> ImageResponseBytes: {{imageResponseBytes}} </li>
<li> rules:
<ul>
{%for rule in rulesvalues%}
<li>{{rule.nameRule}}:
<ul><li>ruleImpact:{{rule.ruleImpact}} </li>
{% if rule.ruleMesssage%} <li>Message: {{rule.ruleMesssage}} </li>
{%endif%}
</ul>
</li>
{%endfor%}
</ul>
</li>
</ul>
</div>


{%endif%}
{% endblock %}

 

Y el resultado final es este: 

resultado_pagespeed_dgimeno