Posted on Leave a comment

Google Ghosts Trap

A fan model of a Ghost Trap as featured in the 1984 Ghostbusters film

The image kindly made available at GB fans forum

The Story continues …

This is episode 2 of our Google education effort. Have you read episode 1,  Global Ghosts Afterlife? Therein we claimed and explained that our site essentially didn’t have 404 not found errors. To get the SEO right we are using Rank Math SEO, and with the advent of the Global Ghosts, it was time to turn on a module for which we thought we had no use, the 404 monitor.

Parapsychology and the Image Proxy

How do ghosts multiply? Surely we had laid the global ghosts and the google ghosts revealed in the Google Search Console by redirection to the afterlife? So our 404 monitor should be clean apart from the haphazard? But, Oh dear, no! So many entries and with common characteristics. So let’s look at this one ,,,

URIwp-content/imagescaler/ad3e154bee03f2b5acf54109eafa19cb.jpg
User-AgentFirefox 11.0 | Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko Firefox/11.0 (via ggpht.com GoogleImageProxy)

Parapsychology as a science

Things we noticed and investigated:

  • many of the references are to folder wp-content and the file extension is jpg, so these are images.
  • the user agent refers to (via ggpht.com GoogleImageProxy). What’s that?
  • can we actually return the image from the Internet Archive? (see episode 1).

Extraterrestrial: Google Phone Home

So the User Agent says: (via ggpht.com GoogleImageProxy) and if you Google search “ggpht.com GoogleImageProxy” one of the results at the time of writing is Dealing with false opens in Gmail  It seems you would have to be an email marketing expert to make much sense of the findings in that article.  But one thing is clear, this is the published Google Image Proxy. BUT, sometimes, the image proxy is looking in the wrong place for the image and receiving a 404 not found response.

Looking in the right place, here is the image you would see based on the URI and using a little bit of work with the WaybackMachine.

Cover of The Girl with the Dragon Tattoo by Stieg Larsson
Cover of The Girl with the Dragon Tattoo by Stieg Larsson

What we intend people to see for the time being, is this:-

A fan model of a Ghost Trap as featured in the 1984 Ghostbusters film
A fan model of a Ghost Trap as featured in the 1984 Ghostbusters film

In other words, a direction to this post which gives guidance as to where you might find the original image of the cover of The Girl with the Dragon Tattoo by Stieg Larsson.

Past Lives and the Paranormal

So we know that authors-books had a past life and the image of the cover of The Girl with the Dragon Tattoo by Stieg Larsson is an artifact of that past life. These observations emerge in the context of our difficulties with Google search, where we’ve gone from hero to zero, we believe and intend to prove, through no fault of ours (we’re still on page 1 in Bing search and DuckDuckGo, etc) And while Google features large in our observations because of the image proxy and wide adoption of Gmail, this is in fact another global problem. So authors-books would like to suggest a global solution.

The Global Ghost Code

Wikipedia has a list of HTTP status codes. The 4xx rage are client errors. Some people have suggested in cases like that above, the site should return 410, sometimes described as content deleted. But that’s not true. On the current incarnation of the website it never existed.

Would love to have come up with a clever suggestion for the code, as in 451 Unavailable for Legal Reasons, a reference to the novel Fahrenheit 451. Ideas please. But in the meantime, what about:

452 Property of a Previous Owner of the Domain Name

This request probably relates to a page or image from a website established by a previous owner of the domain name. It has never been available on the website of the present owner of the domain name. The page or image may be available at the Internet Archive on the WaybackMachine.

452 – a solution for generations to come

Alphabet, please get behind this idea. When Google Image Proxy or any other system receives a 452 response there’s constructive action to be taken. Perhaps automatically trying the Internet Archive? Whatever, the world has been given a more meaningful response.

Much more to come …

This is the end of episode 2 of our Google Education series.  So much more to say, so episodes 3, 4, … coming. And we know we’re doing our SEO well because we’re on top of page 1 in Bing, DuckDuckGo, etc. with searches where we’re nowhere in the Google results!

The Previous and Next Episode

Update 2nd October 2025.
Hurray, we’re now found in Google searches. We changed nothing, but Google Search has caught up.
The previous episode Global Ghosts Afterlife published 16th October 2024.
The next episode Google Books Blind Alley published 18th October 2025.

Posted on Leave a comment

Global Ghosts Afterlife

ECTO 1 in full flight in pursuit of Google Ghosts afterlife

Credit: Photo by Winston Chen on Unsplash

The Story so far

The advice for some time had been, that to achieve our goal, we needed the right brand. As a micro startup, to set things in motion, we’d gone with our business name Data Stream World and we took the domain name datastream.world. Yes that’s a new top-level domain (TLD .world). And we said the brand was Author Direct Bookshop, but, it never did seem right.

Then when Facebook become Meta, Google become Alphabet and Twitter become X, we wondered why can’t Data Stream World become Author’s Books? We were delighted to find that the domain name authors-books.com was available. Wow! An actual .com that’s completely the brand. New logo, move the site to the new domain name and we’re away. Or so we thought.

With our old domain name, if you searched in Google for a book title on our site we were always number 1 or 2 in the search results. Yes, we’d got the SEO right using Rank Math. Then why with the new domain name and an otherwise identical site are we nowhere? Literally nowhere! This post is just one part of the story of our effort to find the answer.

Google Ghosts

Our site doesn’t have 404s. Yes, well if you key the URL ‘authors-books.com/nonsense’ you will get a 404 response. That’s a real 404. But Google Search Console should not be getting 404 responses. It never did with the original domain name of datastream.world. And we regularly run a link checker. So, what’s going on?

Why are we receiving emails from Google Search Console telling us there are reasons pages are not being indexed? Really didn’t happen before. Better take a look. Horror!

There’s this bunch of URLs (see image below captioned ‘Google Ghosts Cellar URLs labelled vintage authors-books.com’) that have never been on our site. We’ve never heard of them!

And into the bargain the URLs are HTTP. Our sites, datastream.world and authors-books.com have always been HTTPS. We’re talking about current professional websites after all.

Google Ghosts Cellar URLs labelled vintage authors-books.com
Google Ghosts Cellar URLs labelled vintage authors-books.com

Internet Archive

Ah! So perhaps this domain name belonged to someone else before? But, why on earth has Google Search Console associated that data with our Google account? After all, we’ve had to jump through hoops proving we own the domain.

Now experience tells us, we’re seldom alone with a problem. So, we go ahead with a (yes) Google search “404 previous owner URL”. And there they all are, people experiencing the same issue. At least one of the entries refers to the Wayback Machine.

So, we pop one of the URL’s into the Internet Archive and there it is.

AUTHORS-BOOKS.COM from the Wayback Machine
AUTHORS-BOOKS.COM from the Wayback Machine

Now some of the “experts” advising worried site owners give advice that Google Search Console has a very busy bot and it may not be that speedy in forgetting old memories and getting up to date. Heavens above! This capture was made only once in 2010CE. Apparently, the site became unreachable not long after.

Current XML Sitemap

Our site has an excellent XML site map generated by Rank Math. We don’t think we ever explicitly submitted to Google Search Console a site map with our original domain name datastream.world. Perhaps, Google Search Console found it, or Rank Math submitted it, we’re not sure, but the end result was top rankings for the titles on our site.

However, some of the “expert” advice talked about submitting a sitemap to Google Search Console, so we looked to do that. Unbelievable, there was a site map that never was on our site, submitted over ten years ago with all these non-existent HTTP URLs! By what misguided mechanism did it become associated with our site?

We instructed Google Search Console to drop this ghost, hoping things would improve. But no. It seems these ghost URLs are very difficult to lay. How ironic that one of the titles was “Dark Life by Kat Falls”. Time for ghost busting! So here we are, we now have redirections from those URLs to this page.

Global Ghosts and Google Ghosts

Global Ghosts are references to no longer existing pages. The page might not exist for a variety of reasons. One of these reasons is that the domain name ownership is not renewed and has reverted to an available name with the domain registrar. That’s an artefact of the domain name system.

Google Ghosts as found in the Google Search Console look like cobwebs that need to be swept away. Is there not an opportunity when the proof of ownership of the domain name takes place to ask whether any data held by Google Search Console is still relevant to the website of the new domain owner? Then, at that time, Google Search Console has a chance to sweep the cellar clean if that’s what’s desirable.

Backlinks

In the hope of mutual benefit and the possible continuing power of backlinks we’ll happily list your site here if you too have suffered from the afterlife of Google Ghosts. Please send an email subject “Google Ghosts Afterlife backlink” to webmaster@authors-books.com. Please include the URL where we can view your link to this post. Also a few words you’d like to go with our link to you and the URL you’d like us to reference.

The Next Episode

This is the end of episode 1 of our Google Education series.  Episode 2 ‘Google Ghosts Trap‘ published March 2025.

Posted on Leave a comment

Toggle WordPress Background Image for Readability


Why and How We Toggle the Background

For reasons related to the origin of our site we want to keep our background image although for readability it is less than ideal. So the question was, how do we enable the user to effortlessly hide the background image if they wish to improve the contrast of the page?

As our site uses WooCommerce, for small mobile screens we wanted to have our ‘Contrast’ button in the handheld footer menu.

While the button would say ‘Contrast’, we thought a, not to be missed, tooltip was necessary. Also a tooltip that would, in some way, cope with the absence of hover on touch screens was desirable.

Then it seemed that once the background image was hidden, the new state should apply to all newly opened tabs. This was achieved through the use of a cookie. Indeed, the background image state would apply consistently in the browser until the cookie expired after a day.

How we implemented each of the above goals is described in the following sections.

There’s quite a lot of JavaScript code to follow in this. If you’d like to see the completed code this can be done using the Chrome Developer Tools. Look at the ‘Sources’ tab and find the file ‘https://authors-books.com/wp-content/uploads/siteground-optimizer-assets/custom-js.min.js’. This is a minified file, however, there is a pretty-print icon ‘{ }’ in the footer of the code window that allows you to see the formatted code. Update 4 May 2021. To look at the particular file you need to be logged in, but no problem, just register and when you’ve finished, there’s a ‘Delete My Account’ option in the Dashboard. We’ll forget all about you!

Steps for a Floating ‘Contrast’ Button

  1. Guided by one of many posts on the topic of a floating button, we added the following to the style.css file in our child theme.
    #contrast_button {
          position: fixed;
          z-index: 99999;
          right: 20px;
          top: 100px;
    }
    For the button to be mouse sensitive we found we needed a large z-index. The value of 99999 is arbitrary and effective. (Our effort to find the highest z-index in use in the stacking context was disapointingly fruitless.)

    We also copied header.php to our child theme and included, as a new <div> after #content, the following:
    <div id="contrast_button" class="a_contrast">
          <a id="a_contrast" href="javascript:void(0);"
               title="Toggle background image.">Contrast</a>
    </div>

    We don’t want the anchor click to take us anywhere, so the href we’ve used is explained in “Is an empty href valid?“.

  2. However, so far the anchor does not look like a button. So we added this style.css in our child theme:

    /* make the link look like a button */
    #contrast_button{
          border: 1px solid black;
          border-radius: 5px;
          padding: 0px 3px;
          background-color: #E3E3E3;
    }

    #contrast_button:hover{
          background-color: #E0FFFF;
    }

  3. When we click the button we want to hide the background image. An inspection of page source or the article How To Properly Add Background Images To Your WordPress Site tells us that we need to remove the css for the class custom-background and replace it with other css that we’ve called custom-contrast. So we added this css to our child theme style.css:
    /* Toggled values to replace custom-background */
    .custom-contrast{
          background-image:none;
          background-color: #E3E3E3;
    }
    Then, following the up-voted code in Changing background color in wordpress with a button so that these values toggle when we click the button, we added the following to our custom.js file (we’re using the theme-customisations plugin):
    jQuery(function($){
          $("#contrast_button").on("click", function(e){
               e.preventDefault();
               $('body').toggleClass(
                    'custom-background custom-contrast');
          });
    });

    To allow us to use the $ shortcut we have followed Using ‘$’ instead of ‘jQuery’ in WordPress and also the recommended jQuery syntax.

And that’s all that’s necessary for the floating button.

Handheld Footer Bar ‘Contrast’ Button

  1. Guided by Customize links in the handheld footer bar we added the following to our functions.php:
    /*
    * Add a link in the handheld footer bar
    */
    add_filter( 'storefront_handheld_footer_bar_links',
         'add_contrast_link' );
    function add_contrast_link( $links ) {
         $new_links = array(
               'contrast' => array(
                    'priority' => 10,
                    'callback' => 'contrast_link',
               ),
         );
         $links = array_merge( $links, $new_links );
         return $links;
    }
    function contrast_link() {
         echo '<a id="contrast_bar_button"
              href="javascript:void(0);"
              title="Tap to toggle background image.">'
                   . __( 'Contrast' ) . '</a>';
    }
    This is enough to add the link in the footer bar, but we do not yet have an icon.  So, additionally we need to add to style.css:
    .storefront-handheld-footer-bar ul li.contrast > a:before {
          content: "f042";
    }

  2. For the footer bar button to do the same action as the contrast button, we just need to add its selector to the line:
    $("#contrast_button").on("click",function(e){
    to become:
    $("#contrast_button, #contrast_bar_button").on("click", function(e){

  3. And lastly, we needed to turn off the ‘Contrast’ button in the page body, so we added this to style.css:
    /* don't display the contrust button on handheld */
    @media only screen and (max-width:768px){
          #a_contrast, .a_contrast {
               display: none !important;
          }
    }

And that’s all that’s necessary for the footer bar button.

Adding a Big Tooltip to the ‘Contrast’ Button

  1. For the tooltip we followed the post Responsive and Mobile-Friendly Tooltip.  So firstly we added the attribute rel="tooltip" to our anchor elements (id’s a_contrast and contrast_bar_button) above.

    Then, we wanted the tooltip:

    1. to automatically disappear after 3 seconds.
    2. to show itself on page load, so attention is drawn to the button.
  2. So we included the CSS as shown in the post in style.css, except for small variations as shown here:
    #tooltip
    {
          text-align: center;
          color: #fff;
          background: #0000FF;
          position: absolute;
          z-index: 99999;
          padding: 15px;
          border-radius: 5px;
    }
    Here we’ve chosen a different background colour, we needed to increase the z-index and we choose rounded corners.
  3. We included the JavaScript largely as shown, but with the following changes for 1a and 1b above and since we already have document ready handling, then c below:
    1.  We added, at the end of the init_tooltip function, a timeout, thus:
      window.setTimeout(remove_tooltip, 3000);
        
    2. The changes for the on page load tooltip display are fivefold:
      1. we named the function bound to the variable targets using a function expression, thus:
        var show_tip = function()
          
      2. So now we have (noting that .bind is, sort of, deprecated), to keep the original functionality:
        targets.on( 'mouseenter', show_tip);
          
      3. Then we added after the above line of code:
        show_tip();
        in order to show the tooltip on page load, however, there is a problem, because the object this is the window object and not the button clicked.
      4. So how to select the button?  Well the buttons are held in the variable targets and in our case only one is visible, either the floating button or the footer bar button.  So which is visible?  Guided by How to check an element is visible or not using jQuery this is how we found out:
        var vis;
        $(targets).each(function (index, element){
              if ($(element).is(":visible")){
                   vis = element;
                   return false;
              };
        });
        So now we know which button element is visible and thus the button we should tooltip when this is the window object.  
      5. This is how we test if this is the window object, so accordingly we evaluate:
        this != null && this === this.window
        Hence we replaced:
        target  = $(this);
        with:
        target = $(
             (this != null && this === this.window)? vis : this
        );
         
    3. We removed the construct:
      $( function() { < // code we keep >  });
      since we already have a document ready construct:
      jQuery( function($) {  // Our toggleClass code  });
      so we included all our code within this later construct.

And that’s all that’s needed for the footer bar ‘contrast’ button.

Using a Cookie to Know the ‘Contrast’ State

  1. Knowing nothing of the subject, we first read How to Set, Get, and Delete WordPress Cookies (like a Pro).  We also read the PHP documentation on setcookie, noting the protocol restrictions regarding HTTP headers.
  2. Our cookie was generally to have a value of ‘low’ or ‘high’ corresponding to the contrast states of, background image showing, and no background image, respectively.  However, we introduced an initial state of ‘init’ which allowed us to show our tooltip for longer when the cookie was created.
  3. Update 22 May 2020.  With the buzz around Chrome’s cookie SameSite policy rollback in the COVID-19 pandemic, we decided now was the time to get SameSite as right as possible.   Our current PHP version is 7.3 and is relevant to our solution as discussed.  Getting it right was not easy as there are suggestions which did not work for us.  On reading Secure better your website with SameSite cookies we used the header function to set the cookie where formerly we had used the setcookie function.  So to create our cookie we added the following to theme functions.php:
    /*
    * Contrast cookie
    */

    function set_contrast_cookie() {
          // Check if cookie is already set
          if(!isset($_COOKIE['contrast_state'])) {
               // Set the cookie, expires in 1 day
               $expire = date('D, d M Y H:i:s', time() + 60*60*24); // one day from now
               header("Set-cookie: contrast_state=init; expires=$expire; path=/; SameSite=Lax");
          }
    }
    add_action('init', 'set_contrast_cookie');

  4. Once the cookie has been created, all our other cookie handling can be done by the browser with JavaScript.

    How should cookies be handled JavaScript?  We found How do i set/unset a cookie with jQuery which pointed us to js-cookie.

  5. Update 4 May 2021.  Previously, we did not need to load js-cookie as that was being loaded by WooCommerce.   but then we hit a snag when we implemented Perfmatters for performance reasons.  With version 1.6.9 of Perfmatters there were ‘Multiple improvements to WooCommerce disable scripts …’, so js-cookie was no longer being loaded on most of our pages. Thus we needed to load it when necessary.

    The fact that js-cookie wasn’t being loaded showed up on the console as ‘Cookie’ being undefined.  So our approach was to trap this condition with try and catch statements.  But now, how does one dynamically load the required script? We came to Dynamically load JS inside JS [duplicate] and way down with only 8 up votes read about  extending jquery.getScript to have the loaded script cached.  What a nice idea, so we went for that.

  6. To remove the background image if the cookie value is ‘high’, we need to act as if the ‘contrast’ button had been clicked.  So we added the following to custom.js:
    var contrast;
    // Page load set contrast high if necessary
    contrast = Cookies.get("contrast_state");
    if (contrast == 'high') {
         $('body').toggleClass('custom-background custom-contrast');
    }
  7. Now we needed to set the cookie when the ‘contrast’ button is clicked, so we added to custom.js in the function for the contrast button .on(‘click’:
    contrast = Cookies.get("contrast_state");
    Cookies.set('contrast_state',
         (contrast == 'low') ? 'high' : 'low',
         {expires: 1, path: '/', sameSite: 'lax'});

  8. We decided that we only wanted the tooltip to show without focus being on the ‘contrast’ button on the occasion when the cookie was created.  We thought that for it to appear on every page load might be irritating.  So we modified the show_tip(); statement to be:
    contrast = Cookies.get("contrast_state");
    if (contrast == 'init') {
         show_tip();
         Cookies.set('contrast_state', 'low',
              {expires: 1, path: '/', sameSite: 'lax'});
    }
  9. As mentioned above, we wanted the tooltip to show for longer on the initial page load when the cookie is created.  It’s now the case that the page load show_tip() is only done when the cookie value is ‘init’, that is only once before the cookie expires.  So we made some changes to the custom.js code.  In place of :
    var show_tip = function()
    {
         target = $((this != null && this === this.window)? vis : this);
    we now have:
    var show_for;
    var is_window;
    var show_tip = function()
    {
          is_window = (this != null && this === this.window);
          show_for = is_window ? 6000 : 3000;
          target = $(is_window ? vis : this);

And that’s all that’s needed for the cookie to know the contrast state.

Just a reminder, if you want to see all the JavaScript code, we explain how in the last paragraph of the first section ‘Why and How …’.