Facebook Pixel implementation: some references.

Implementation

Implementation – Facebook Pixel

Cookie consent and GDPR

If you plan to serve European Union you will need to implement GDPR.

General Data Protection Regulation (GDPR) | Facebook for Business

Which means you will need to ask for user consent before tracking their activity on your website that involves personal data. Fortunately Facebook offers an API to pause Pixel from firing and fires once consent is granted:

fbq('consent', 'revoke');
fbq('consent', 'grant');

General Data Protection Regulation – Facebook Pixel

You can also use a tag manager for that purpose.

Tracking Events

Facebook Pixel API offers a wide range of standard events to track.

Examples:

fbq('track', 'Purchase', {currency: "USD", value: 30.00});
fbq('track', 'AddToCart', {currency: "USD", value: 30.00});
fbq('track', 'PageView');

You will find the complete list of standard event here Reference – Facebook Pixel.

Custom Events

fbq('trackCustom', 'ShareDiscount', {promotion: 'share_discount_10%'});

Conversion Tracking – Facebook Pixel

Parameters and Object properties

In the examples above you may have notice that some code got additional information beside the event name.

{currency: "USD", value: 30.00}
{promotion: 'share_discount_10%'}

Those are optional parameters written as JSON-formatted objects and allow to include additional information to your events.

We have seen value parameters and promotion but you might want to add the category where the event took place

{content_category: "name_of_category"}

You can just as easily create custom parameters.

{custom_parameters: "some_value"}

or even more complex objects:

{contents: [
      {
        id: '301',
        quantity: 1
      },
      {
        id: '401',
        quantity: 2
      }]}

You will find more information on the link above where parameters are treated, plus you have some example above.

Migrating a static site to WordPress CMS

In this article we will consider that you have already finalize your site on WordPress on a development server, backed up your production site and that you are ready to do the transfer. We will simply mention that once you have finalized you site on the development site don’t forget to redirect your page through .htaccess.

Redirections

Your .htaccess will look like that:

<IfModule mod_rewrite.c>
RewriteEngine On

</IfModule>

# BEGIN WordPress
# Rivit, jotka ovat "BEGIN WordPress" ja "END WordPress" välissä on luotu dynaamisesti ja niitä tulee muokata vain WordPressin filttereillä. Kaikki manuaaliset muutokset riveihin tullaan yliajamaan.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /

#My redirect

RewriteRule ^some_url.html$ https://www.example.com/some/new_url/ [L,R=301,NC]

#End redirect

RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress
#BEGIN CUSTOM

Note that the simple 301 redirect:

 Redirect 301 /oldpage.html http://www.yoursite.com/newpage.html Redirect 301 /oldpage2.html http://www.yoursite.com/folder/

as described here, won’t work as is in the WordPress .htaccess, hence the use of the previous method. Not that the URL being redirected does not use the domain name.

If you have to redirect files and folders that are hosted in a subdomain, make sure to modify the .htaccess accordingly in the affected directory.

We also recommend that you redirect your image to not lose any image traffic.

Moving WordPress

WordPress.org has a good documentation about moving wordpress:

In our case study, the paragraph about changing domain name and URLs is particularly of interest to us.

One thing that is not explicitly mentioned is that the column guid in the wp_posts column in the database won’t change and still refer to your development server. To solve this you might think of running an SQL command to update the gui to your new domain name:

UPDATE wp_posts SET guid = REPLACE(guid, "old[DOT]com",  "new[DOT]com");

but this operation is not recommended due to data serialization issue. I tested one of the recommended plugin in the article (better search replace) and it worked well.

Uninstall problematic plugins before migration

Note that some plugins might cause issue during the migration because they have hardcoded your previous domain (the development one). In that case you might want to uninstall them before migration. Some plugins doesn’t do proper garbage management and you might need to do some manual cleaning.

In my case, I had to uninstall Wordfence and manually clean the database and some files and folders. You will find all required information on Wordfence site. There is an advance uninstall option that is suppose to do that for you, but I was not aware of it at the time. It seems to be a separate plugin:

YITH WooCommerce Wishlist caused also issue by requiring a file that was not there (and also missing in the dev site but without causing issue). So you can also just uninstall it before backing up for migration and reinstall it once migration is complete. In my case I commented out the incriminated line which allow me to access the dashboard and updated the plugin, which solved the issue.

Minimizing down time

If your site have a large amount of pictures and you want to minimize downtime, we recommend that you upload your picture before hand on the production site ahead of the migration.

If you have followed the moving WordPress tutorial, you have done a backup of your development site and its database, changed the URLs in wp settings – general, which leads to a 404, backup your dev site and its database after the change you can upload the following folder to your production site, without interrupting production: wp-admin, wp-content, wp-includes.

Make sure you have php version compatible with wordpress on your production site.

Create a database to upload the database of your dev site (the one you did after changing the domain in the settings). Note the user name, use password, database name and host as you will need it later.

Finalize migration

Once you have finished transferring your pictures and the WordPress folders and imported your database table in the production database, you are ready to finalize the migration. Delete the folders related to the previous version of your site and upload all the WordPress files that lies at the root of your dev site.

robots.txt

Check that your site is discoverable in WP Reading Settings and double check the robots.txt and do your redirect as indicated at the beginning of the article.

Google search console

Make sure to update your site map URL in case it differs from the version prior to migration.

Analytics

And finally add your analytics tracking code to your new site.

Profit.

Set a dedicated 404 page in .htaccess

In the redirect section of your .htaccess file just add the following line:

ErrorDocument 404 https://example.com/404/

Replace the url by the actual url of your dedicated 404 page as you would do for any other redirect.

Now all what’s left to do is to create the page in your CMS back end (or code one in html if you are running a static site).

Find unsused code in your javascript and css files. Optimizing your lighthouse scores part 2

To find out what part of your CSS or JavaScript is not used, you will need to enable the coverage tab in the Chrome Developper Tool. For that you will need to run a command in the command window. The command window can be enabled in the right hand “three dot” menu of the Chrome Developper Tool.

Type coverage and press enter. The coverage tab will now be available in the bottom window of your Google Developper Tool.

Reload the page to start the diagnostic.

You will see listed your files, their type, size and amount of unused code as well as a graphical representation of the proportion of unused code compare to the total size of the file. By clicking one of the file it’s content will be displayed in the code window of the source tab and you’ll see that the beginning of the line of unused code will be highlighted in red. Now it will be your job to refactor the script so that only necessary CSS and js are loaded for any given page …ideally, as this is no easy task.

Additional reading: https://developers.google.com/web/tools/chrome-devtools/coverage

Optimizing for Core Web Vitals . Part 1

During the course of the year 2020, Google has announced that Core Web Vitals will be come a ranking factors. Google makes, such announcement when the company wants webmasters to prepare their website for the changes to come.

Core Web Vitals is a selection of metrics that help characterize the user experience on a page: how fast does it render? how fast is it interactive? Does the content of the page jump around when new element are loaded?

In technical terms thats gives:

Largest Contentful Paint (LCP): measures loading performance. To provide a good user experience, LCP should occur within 2.5 seconds of when the page first starts loading.

First Input Delay (FID): measures interactivity. To provide a good user experience, pages should have a FID of less than 100 milliseconds.

Cumulative Layout Shift (CLS): measures visual stability. To provide a good user experience, pages should maintain a CLS of less than 0.1.

https://web.dev/vitals/

You can find the Core Web Vitals for a page by using tools such as https://developers.google.com/speed/pagespeed/insights/ but they are also available in Google Search Console and other Google products.

As the opportunities for improvement will vary greatly from one website to another. I will develop here the one I encounter during my own optimization process, and hopefuly it will be useful to others. Let’s analyze some opportunities:

Preload keys requests:

Preloading a font to be loaded ahead of time so that when it is needed, it is already available.

https://web.dev/codelab-preload-web-fonts/

https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content

Preloading content is also useful to help prevent blocking resource.

When preloading the font, Google Page Speed returns an error message that the font is not used:

Warnings: A preload <link> was found for “https://www.example.com/templates/horme_3/fonts/glyphicons-halflings-regular.woff” but was not used by the browser. Check that you are using the `crossorigin` attribute properly.

https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content#Cross-origin_fetches

So preloading a font will look like:

<link rel="preload" href="https://fonts.googleapis.com/css?family=Michroma|Roboto" as="font" crossorigin >
<link rel="preload" href="/some/script.js" as = "script" />
<link rel="preload" type="text/css" href="/some/style.css" as="style" />

preload html specification

In the same vein, you can also preconnect to external resource to gain on loading time:

<link rel="preconnect" href="https://stackpath.bootstrapcdn.com" >

Cumulative Layout Shift (CLS)

The most common causes of a poor CLS are:

  • Images without dimensions
  • Ads, embeds, and iframes without dimensions
  • Dynamically injected content
  • Web Fonts causing FOIT/FOUT
  • Actions waiting for a network response before updating DOM

https://web.dev/optimize-cls/

The first suggestion apply to my case as I don’t declare any width and height in the picture element. I got used to the flexibility of responsive image (calculated according the size of the screen) and didn’t move on to the srcset method where the different image size available are listed with specification regading the screen size it should be displayed at. This method requires to carefully plan break and the various size available to fit the different screen size. Example:

< i mg srcset="elva-fairy-480w.jpg 480w,
             elva-fairy-800w.jpg 800w"
     sizes="(max-width: 600px) 480px,
            800px"
     src="elva-fairy-800w.jpg"
     alt="Elva dressed as a fairy">
The code above did not work as desired (the image loaded on mobile screen size was still the largest one.
The following code works as intended:

<picture> 
<source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg"> 
<source media="(min-width: 800px)" srcset="elva-800w.jpg"> 
<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva"> 
</picture>

In the article about optimizing cls cited earlier, it is specified that you need to give the image aspect ratio (actually width and height) so that the browser can calculate the size on the screen as soon at it received the css relative width, for example:

width:100%

implementing min-height for the images class solved the issue of layout shifting. The text still overlay pictures that have a height larger than the min-height but it’s due to a javascript (matchHeight.js) in my template which role is to set all div from a row to the same height. This needs to be replaced with css that performs the same action.

Avoid displaying empty font:

adding

font-display:swap;

to the @font-face in the bootstrap css glyphicon font delaration solved the issue. It tells the browser to use a build-in font to render the text while the proper font is loaded.

https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display

Display pictures at the proper size

To display picture properly on high-dpi screen I use to display compressed jpeg at half their actual width. This rendered well on iPhone screen even though the quality was a bit lower on desktop compared to the same compression but at the actual size.

The issue with this method is that it requires that the browser resize the picture to the screen size and it might consume more badwidth than serving the picture at the actual screen size, although with this method you can serve picture twice the size but lighter than the actual size one because they are more compressed.

There might be an alternative that would save the computer the calulation cost and that would be to use picture at 100% their screen size but saved with higher dpi so that they look good on high-dpi screen as well.

We need to control that high-dpi picture are looking good on retina display and the like, but also that the CMS, when generating thumbnails, will also create high-dpi thumbnails.

Security

Link with target="_blank" are unsecured without rel="noopener" or rel="noreferrer". Read more:

https://web.dev/external-anchors-use-rel-noopener/

And on wether or not you should use target="_blank" at all :

Best practice:

Links do not have a discernible name

if your link doesn’t have text or a picture with an alt-tag, you can use arial-label=”link description” for people using assistive technology.

Next step: remove unused CSS and javascript!

Writing content

In case you have no idea about the content a page should have but you have to write it anyway, because you client absolutly want it or because there is an obvious use for such a landing page but you have no inspiration on the content, I present you with a methodology to write a text about a given topic whithout prior knowledge:

Take the few first search result pages and use it as inspiration for the page structure and content. Once you have an overview of the different elements that needs to feature on the page. You will have a better idea on how to layout the page.

With the example gathered from to pages you can now write a text that presents your topic/product/category correctly, using appropriate keyword and satisfying customer expectation and ansewering customer intent.

Even if the pages you use for inspiration or as source were ranking well they might be overooking important keyword or not be fully satisfying for the customer. So don’t hesitate to take further step in order to write better text using a more engaging layout.

Consult your analytic to find for user query using the target keyword(s) to check if customer have recurring question or associate your keyword with specific adjectives or query.

Remove base for category permalink in woocommerce

TLDNR: Not advisable

I have this idea that longer URI path, or deeper “file hierarchy” would have a negative SEO impact. But recently John Mueller made a statement that URI length did not have any negative SEO impact. The most important thing is that your important page are easily accessible to the search engine, and probably to your customer too.

In this article, Search Engine Journal speaks about length and recommend to keep it short but it’s an extrapolation on what J. Mueller said regarding URI longer than 1000 characters may not be a good practice (which is different from: “the shorter, the better”).

https://www.searchenginejournal.com/googles-john-mueller-recommends-keeping-urls-under-1000-characters/318739/#:~:text=Google’s%20John%20Mueller%20recently%20stated,under%201%2C000%20characters%20in%20length.&text=With%20that%20said%2C%20it’s%20generally,than%20they%20need%20to%20be.

In a more recent tweet, John was clear about that point:

https://www.seroundtable.com/google-url-length-seo-28952.html

Given that woocommerce does not recommend to remove the product-category base from the permalinks and that there is no clear SEO SEO advantage to it, then there is no reason to implement this feature.

If anything you can implement the option to have the product category included in your product permalink for SEO purpose. Having the product category in your URL might help google identify which category your product belong to and helped it rank for those keywords.

Formatting results from Google Search Console API

Issue: using python, google search console API csv lines starts all with the following string

 b'\xef\xbb\xbf2019-04-20'

Solution:

The \xef\xbb\xbf is the BOM. It came here because I was actually encoding the result in utf-8-sig instead of utf-8. Just make sure to properly encode the returned strings in utf-8 and this won’t bother you.

So after this correction we are left with the following:

 b'2019-04-20'

This indicates that the date (which is the key) is actually of type bytes and not of type string.

To solve this just make sure to decode the bytes to string with the following code:

key.decode('utf-8')

Sources of keywords

Google Search Console

It gives you queries for which Google Search returned your site as a result

Google Ad Keyword ideas

Primarily meant to find ideas for your Google Ad campaigns, it is a good source of keyword ideas for your SEO. In addition you can evaluate the value of the keyword thanks to volume forecast, recommended minimum biding and competition evaluation.

Latent Semantic Analysis

If the two sources of keyword above are based on user query (the most important) we can also extract valuable keywords from the site already online. Latent semantic analysis allow to find the most statistically significant keyword in a group of pages compared to a larger set of document which is suppose to be representative of the frequence of the words in the language.

Quality of the results yielded by this method depends greatly on the dataset and on the quality of the content for the specific topic you want to analyse. Topic with poor description and little written content (and no SEO effort ) are likely to yield poor results.

Evaluating the quality of the result of the LSA and optimizing the process to extract the maximum information will require some adjustement: is lemmatization a good idea for n-grams? Doesn’t it make results more difficult to analyze? Lemmatization was suppose to strengthen the presence of a given word by aggregating all its different forms in its unic lemma.

A possibility to evaluate the quality of the subset for the topic is to check how much words from the two first lists (after lemmmatization if necessary) are present in the documents. If little are found, it tends to indicate that this field is not optimized toward user query and possibly that little attention is given to the content, or that the content and the user queries for this topic are “disconnected” and that we have a good opportunity to fill the gap.