Skip to content

Posts tagged ‘seo’

21
Aug

Load Many Images in a Single Request (Optimization)

Some pages on GoToQuiz.com generate many requests to retrieve many thumbnail-sized images. Each image file is only 1 – 5 KB in size. I wanted to reduce the penalty associated with making numerous requests, so I came up with a way to combine these into a single request.

I needed a solution to retrieve an arbitrary number of images, which may vary with each pageview. I considered generating an image sprite on the fly, but this approach came with several problems:

  • Constantly invoking image functions on the server, adding more overhead
  • Image display would require using background-image and CSS manipulation
  • Image display would also depend on meta data about each image, to correctly set the necessary CSS values
  • Images may be different heights and widths, further complicating sprite generation

So instead, I went with returning the image data base64-encoded in a JSON format. It works like this. The HTML will have elements each holding the URI of the image as a data element rather than in <img src=”…”>.

<div class="gImg imgSwapHiPri" data-imgpath="/upic/2017/21/Mn8rrw.T1.jpg"></div>

In this case, it’s a certain kind of thumbnail styled with .gImg to have a specific height, width, and generic default background. The .imgSwapHiPri class is used to tag all elements to have their images swapped in.

And here’s the jquery plugin I wrote, to be called on pageload:

(function($, dataAttr) {

    $.lazyImage = function($swaps, alt) {
        $swaps = $($swaps);

        var thumbs = $swaps.map(function() { 
                return $(this).data(dataAttr);
             }).get();

        if (thumbs.length !== 0) {
            $.get('/img/image-set.json', {"paths[]": thumbs}, function(json) {
                $swaps.each(function(i, el) {
                    if (el.tagName === 'IMG')
                        el.src = json.base64[i];
                    else
                        el.innerHTML = '<img src="'+ json.base64[i] +'" alt="'+ (el.getAttribute('data-alt') || alt || '') +'">';
                });
            });
        }
    };
        
})(jQuery, 'imgpath');

Very simple. Invoked with $.lazyImage(‘.imgSwapHiPri’);. You can pass an optional alt attribute value, or optionally set a data-alt attribute per element. This script checks if the element to be swapped is an IMG tag; if so, set it’s src attribute. If not, set its innerHTML to an IMG tag. Either way, the image data is set to be the base64-encoded image returned by /img/image-set.json.

Let’s take a look at what’s happening in /img/image-set.json’s PHP code. I’ve got some framework boilerplate in the actual script, but the main bit is this:

const WEB_ROOT = '/path/to/public_html/';
$paths = $_POST['paths'];
$b64 = array();

//fill an array with the base64-encoded images        
foreach ($paths AS $path)
    $b64[] = base64EncodeImg($path);

header('Content-type: application/json');

echo '{"base64":';
echo json_encode($b64);
echo '}';

//function to convert image path to base64 data
function base64EncodeImg($path) {
    //first ensure the image path contains only legal characters
    if (preg_match('@^([-_/a-z0-9]+\.)+(png|jpg|gif|svg)$@i', $path)) {
        //absolute path to file
        $path =  WEB_ROOT . (strpos($path, '/') === 0 ? substr($path, 1) : $path);

        if (file_exists($path)) {
            $type = pathinfo($path, PATHINFO_EXTENSION);
            $data = file_get_contents($path);
            return 'data:image/' . strtolower($type) . ';base64,' . base64_encode($data);
        }
        else 
            return '';
    }
    else
        return '';
}

The data generated by the code above is a simple JSON file containing an array of base64-encoded images. Critically, it is generated in the same order as the elements in the HTML. This allows the jquery plugin to easily match base64 data with the appropriate element just by iterating over them.

And that’s really all there is to it. When the pageload event fires, the jquery plugin is called and makes the request for, say, a dozen images. The image data is returned in one JSON response–typically under 30KB in my case with JSON gzipping turned on (mod_deflate)–and it is fast.

BONUS:

If you have alternate high resolution versions of images for high DPI screens, this modified version of the above jquery plugin has your back.

(function($, dataAttr) {
 
    $.lazyImage = function($swaps, alt) {
        $swaps = $($swaps);

        var hdpi = window.devicePixelRatio || 1 > 1.3,
            thumbs = $swaps.map(function() { 
                var $this = $(this);
                return hdpi ? $this.data(dataAttr + 'H') || $this.data(dataAttr) : $this.data(dataAttr);
             }).get();

        if (thumbs.length !== 0) {
            $.get('/img/image-set.json', {"paths[]": thumbs}, function(json) {
                $swaps.each(function(i, el) {
                    if (el.tagName === 'IMG')
                        el.src = json.base64[i];
                    else
                        el.innerHTML = '<img src="'+ json.base64[i] +'" alt="'+ (el.getAttribute('data-alt') || alt || '') +'">';
                });
            });
        }
    };
        
})(jQuery, 'imgpath');

In this case, the plugin checks if the screen is high DPI and checks each element to see if there is a data attribute called “data-imgpath-h”. If so, it uses this instead of the value of “data-imgpath”. The value of data-imgpath-h is the path to the high resolution version of the image.

1
Mar

Best stats plugin for WordPress: ShortStat

unique hits to wordpress blogThis is just my opinion, based on what I was looking for, which is: a very simple WordPress blog plugin for gathering and reporting stats like unique and total hits, referrers, and search keywords. I wasn’t interested in a heavy-weight stats program. I already use Google Analytics, but for this blog I wanted a plugin to put exactly the stats I’m interested in on my WordPress dashboard.

ShortStat does exactly what I want.  It’s a simple and (as of this writing) actively-maintained WordPress stats plugin that provides a quick dashboard link, putting your stats a mere click away. Read moreRead more

17
Feb

Using word clouds for SEO keyword analysis

Wordle is an online tool that creates “word clouds” out of text.  Basically, you feed it some text and it generates an image of jumbled up words, with the size of each word determined by how frequently it is repeated.  One way to think about it is, Wordle gives you a rough idea of how a search engine spider sees your page.  This may be helpful in your SEO efforts.

For example, here is a word cloud of my blog post on geolocation. (click for larger size)

word cloud

Instantly, the main theme of the post jumps out, with words such as “geolocation”, “city”, “code” and “GeoIP” featuring prominently.  Then you also see secondary words, such as “region”, “PHP”, and “database”, adding additional context.  In SEO terms, the larger words are your keywords.  The font size represents your keyword density.

Another word cloud after the jump: Read moreRead more