HTML5 pushstate and SEO link

安稳与你 提交于 2019-12-20 15:36:55

问题


I try to implement pushstate history on my website in order to load content from a single.php page inside a index.php container.

My website have two main page : index.php and single.php .

On the index.php there are links that call pushstate script:

<a class="phplink" href="/Formlabs-3D-printer" title="Formlabs 3D printer">Post 12</a> 
<a class="phplink" href="/Minimal-Bumper-for-iPhone-5" title="Minimal Bumper for iPhone 5">Post 11</a>

On my single.php page I use isset get method to dynamically load content that correspond to clicked link on index.php:

<?php
if (isset($_GET["page"])) { 
//I do some stuff in order to echo content
?>

In my .htaccess file I rewrite the url link (that the reason that in index.php link are cleans):

Options +FollowSymLinks
RewriteEngine on
RewriteRule /([a-zA-Z0-9\-]+)$ /index.php 
RewriteRule /([a-zA-Z0-9\-]+)$ /single.php?page=$1 [L]

And here my pushstate script:

$.ajaxSetup({cache:false});
$(".phplink").click(function(){
    var $post_link = $(this);
    load_content($post_link.attr('title'),$post_link.attr('href'));
    return false;
}); 

window.onpopstate = function(event) {
    if (event.state) {
        load_content(event.state.title, window.location.pathname, true);
    } else {
        var stateObj = {
        title: document.title,
        url: window.location.pathname,
        };
    url = window.location.pathname;
    load_content(url,url);
    }
}  

function load_content(title,url,skipHistory) {
    $.get(url,function (data) {
        document.title = title;
        var stateObj = {
            title: title,
            url: url
            };
        if (!skipHistory) {
            if (typeof window.history.pushState == 'function') {
                window.history.pushState(stateObj,title,url);
            }
        }
        if(url.substring(1) != '') {
            $("#ajaxify_container").html("loading...");
            $("#ajaxify_container").load('single.php?page='+url.substring(1)+' #container-2');  
        } 
        else {
            $("#ajaxify_container").html('');   
        }
    });
}

My pushstate script works to load content on link click (on .phplink click). It works also for back/forward button.

1st PROBLEM : When I refresh the browser (with an pushstate link in the url) it works on google chrome (load content from single.php to index.php container) but no in IE10 (nothing is loaded, it stay on index.php page).

2nd PROBLEM : If I disable javascript to see what's happen for googlebot (for SEO). I can't load/reach the single.php page, it always stay on index.php. So single.php page can't be crawled by search engine (I suppose, but I'm not sure about this) . This behaviour is normal because I set in my .htaccess file, that "all this links" will be redirect to index.php .

I do this trick because without it pushstate loads single.php page when I refresh. And I don't want this behaviour. I want when I refresh it just load content from single.php into index.php container.

So my main problem (problem 2) is: I don't know how to write my script or my links in my php page in order to load content in my index.php file when I click, I refresh and I back/forward.

In normal behavior of pushstate, does on browser refresh, onpopstate can load content from a page into a container of an other page (load content from single.php into a container of index.php) ?

I hope that someone can help me and explain how it works. I have some difficulty to understand how it work with links.

Sorry for my English, I'm French...


回答1:


I found a way to make it works great!

I made a script that use pushstate for HTML5 web browser with an hashbang fallback in HTML4 web browser (it works since IE8)

To fix the refresh browser problem (without using rewrite rules in .htaccess), I added a little script on the head of the single.php page in order to redirect (only if you are javascript enable) to index.php while getting the pathname of the window.

single.php script (in the head, at the top of the head!):

self.name= window.location.pathname;
window.location.replace(".");

Script for pushstate and hashbang fallback:

if(self.name){
    refreshdocumenttitle = document.title;
    refrestitle = self.name;
    refreshurl = self.name; 
    if (typeof(window.history.pushState) == 'function') {
        refrestitle = self.name.substring(1).replace(/-/g," ");
        refreshurl = self.name.replace("#!", "");
    }else {
        window.location.hash = '#!' + refreshurl.substring(1);
    }
    load_content(refrestitle, refreshurl);
}

$(document).on('click','.link', function(){
     link= $(this);
     if (!link.hasClass('current')) {
        $(".link").removeClass('current');
        link.addClass('current');
        $post_link = link;
        load_content($post_link.attr('title'),$post_link.attr('href'));
        return false;
    }
        return false;
}); 

window.onpopstate = function(event) {   
    $(".link").removeClass('current');
    url = window.location.hash;
    if (url != '') {    
            title = url.substring(2).replace(/-/g," ");
            url = "/" + url.replace("#!", "");
            load_content(title,url);
    }
    if (event.state) {
        load_content(event.state.title, window.location.pathname, true);
    } else {
        if (!self.name) {

            if (typeof refrestitle !== 'undefined') {
                pathname = window.location.pathname;
                    if (pathname == "/") {
                        document.title = refreshdocumenttitle;
                    }
            }           
            var stateObj = {
                title: document.title,
                url: window.location.pathname,
                };
            window.history.replaceState(stateObj,document.title,window.location.pathname);
            load_content(document.title, window.location.pathname, true);
        }       
    }   
    self.name= '';
}

$(window).on('hashchange', function() {
    if (typeof(window.history.pushState) !== 'function') {
        var hash = "/" + location.hash.replace("#!", "");
        if(window.location.hash) {
            load_content(hash.substring(1).replace(/-/g," "), hash);
        } else {
            load_content("", "")
        }
    self.name= '';
    }   
})
$(window).trigger('hashchange');

function load_content(title,url,skipHistory) {
    $.get(url,function (data) {
        document.title = title;
        var stateObj = {
            title: title,
            url: url
        };
        if (!skipHistory) {
            if (typeof(window.history.pushState) == 'function') {
                window.history.pushState(stateObj,title.replace(/-/g," "),url);
            }else {
                if( url != "") {
                    window.location.hash = '#!' + url.substring(1);
                }
            }
        }
        if(  window.location.hash != "" ||  window.location.pathname != "/" ) {
            $("#ajaxify_container").html("loading...");
            $("#ajaxify_container").load('single.php?page='+url.substring(1)+' #container-2');      
        } 
        else {
            $("#ajaxify_container").html("");       
        }
    });
}

In this script, I check on load if the pathname have an hashbang or if it's just a normal path. If the browser can support pushstate, I change hashbang to normal pathname. If the browser don't support pushstate and if pathname have a normal pathname I add an hashbang.

Then, for HTML5 history I use onpopstate and for HTML4 I use hashchange to support back, prev button and refresh browser (because of my script in the head of the single.php page).

If javascript is disabled or if the browser can't handle hashbang or pushstate, the single page can be loaded normally and all necessary informations are displayed like a normal page.

So everything works with or without javascript. It's SEO friendly!! Googlebot crawled all my links with the right content of each dynamic single.php page!



来源:https://stackoverflow.com/questions/16658895/html5-pushstate-and-seo-link

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!