A simple Ajax + SEO solution? - ajax

on my site ive got a search box in center with google, when you search for something it displays all threads that matched the search criteria.
so these threads are all ajaxad in, but when you click on a thread it will go to the thread content with usual href link and the page will refresh.
now i have to let google find these threadlinks that link to every thread in the usual way, so if i put a 'show all threads'-link in my first page on the upper right corner that shows every thread in my site, does it solve the SEO part?
google is able to index them all, but the users will just use the ajax search box?
i've read that "as long as google can find all your contents from the first page (index.php) its fine". so this will be a good solution?

One of the downsides of AJAX is that it breaks a fundamental aspect of the net: that anyone visiting a given URL will get the same page view. This means bookmarking doesn't work right (or at all) for you and link sharing doesn't work right. It also means that bots (even very smart bots) may miss whole sections of your site.
One way to approach this is to make sure that all of your content is reachable via non-AJAX means. Graceful degradation is an important design concept, but it can be difficult to implement after the fact. My rule is to make the site work correctly without any JS magic, and then make it snazzier if JS is enabled. This is also good from an accessibility point of view since many people with handicaps can't benefit from (or are actually further disadvantaged by) AJAX and other JS wizardry.

This will work - up to a point - and you'd be better off putting the links on a different page. You can trust that your users will go with the path of least resistance. If your search works better than your listing, you'll be fine there.
Regarding Google, what you described sounds a lot like a sitemap. That'll work OK, but consider breaking it up into multiple pages if you exceed around 150 links (that's about the time the searchbot gives up). The page should also be something else than index.php, and then just provide a link to it on the home page. A lot of news sites categorize by day or week, but you could also use alphabetical or other. Use whatever system works best for your site.

Turn off javascript on your site. Can you navigate to the threads in some fashion? If so, you can assume Google can as well.
I have to assume that your site isn't solely dependant on search to find threads. There should be some sort of traditional category-based way to get to the forums. If so, that should be all Google needs.
Worse case? Yes, a single link to some sort of index of all posts should work as well.

Here is the complete web sample with Php, Apache, Ajax, history.js (support bookmark and back forward), and SEO support without hash (#) or query (?): http://solusiprogram.com/ajax-seo-with-back-forward-support/ .
The live demo is the website itself. Just try it with javascript turn on or off (to comply SEO).
Then here are the content of that link:
Replace all "yourdomain.com" mentioned below with yours
Put all the files mentioned below to your Apache Document Root
Download jquery-1.11.1.min.js
Download browserstate-history.js-1.8-20-gd213d8c.tar.gz then put
these their 3 files to your document root:
scripts/compressed/history.js
scripts/compressed/history.adapter.jquery.js
scripts/bundled/html4+html5/jquery.history.js
Create .htaccess
#if server returns error, remove this line as your hosting server already handles it
Options +SymLinksIfOwnerMatch
RewriteEngine On
RewriteBase /
#these 3 parts below avoiding duplicate contents that SEO doesn't like
#enforce non-www-uri (you can modify it if you want www-uri instead)
RewriteCond %{HTTP_HOST} ^www.yourdomain\.com$ [NC]
RewriteRule ^(.*)$ http://yourdomain.com/$1 [L,R=301]
#remove trailing index.html or index.php
RewriteCond %{THE_REQUEST} /index\.(html|php)\ HTTP/
RewriteRule ^(.*)index\.(html|php)$ http://%{HTTP_HOST}/$1 [L,R=301]
#enforce a trailing-slash
RewriteRule ^([^.]*[^/])$ http://%{HTTP_HOST}/$1/ [L,R=301]
#set your home page as the default page
Rewriterule ^$ http://%{HTTP_HOST}/home/ [L,R=301]
#to achieves SEO friendly without querystring uri
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Rewriterule ^([^?]*)/?$ /index.php?page=$1 [NC,L,QSA]
Create index.php
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php
$base_uri = "http://yourdomain.com/";
$menus[] = array( 'href'=>'home' , 'title'=>'Home Page' , 'display_text'=>'Home' );
$menus[] = array( 'href'=>'page1', 'title'=>'Page 1' , 'display_text'=>'Page 1' );
$menus[] = array( 'href'=>'page2', 'title'=>'Page 2' , 'display_text'=>'Page 2' );
$page_query = trim( $_GET['page'], '/' );
$page = 'home'; $title = 'Home Page'; //the default page to display
$menu_display = '';
foreach( $menus as $menu ) {
$menu_display .= '<li>' .$menu['display_text']. '</li>';
if( $menu['href'] == $page_query ) { //set page to display based on url query
$page = $page_query;
$title = $menu['title'];
}
}
echo '<title>' .$title. '</title>'; //php set page title for the first load of this index.php then History will replace it when user clicks a menu or back/forward browser button
?>
<script src="http://yourdomain.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://yourdomain.com/jquery.history.js"></script>
<script type="text/javascript">
//<![CDATA[
jQuery(document).ready(function () {
if( document.location.protocol === 'file:' ) alert( 'The HTML5 History API (and thus History.js) do not work on files, please upload it to a server.' );
var last_url = "";
var History = window.History;
//intercept the menu click event
$('li>a').click(function () {
$(this).onclick = undefined; //to prevent default anchor event >> thanks to http://stackoverflow.com/users/690854/thecodeparadox
var data = {}; data.putYour = "data here if you need to";
//push the data, url & title to History and then History.Adapter will load the url
History.pushState( data, $(this).attr('title'), $(this).attr('href') );
return false;
});
//History.adapter triggered by pushState() above or by back/forward browser button
History.Adapter.bind( window,'statechange',function() {
var State = History.getState();
var data = State.data; //all the data you passed on pushState() above is accessable here now, then you can do whatever you need
var url = State.url;
url = url.replace( /\/$/,'' ); //remove trailing slash
if( url==last_url ) return; //prevent ajax from loading the same last_url
last_url = url;
if( !( /.html$/i.test(url) ) ) url=url+'.html'; //make sure it ends with '.html'
//alert( "ajax will load page: '" + url + "'");
$("#ajax_target").load(url);
});
});
//]]>
</script>
<style type="text/css">
body { margin:2em; }
#menu { border: 3px solid #DDD; }
ul {
margin:1em;
background:#DDD;
}
li {
list-style-type: none;
background:white;
padding:5px 13px;
}
#ajax_target {
text-align: center;
vertical-align: middle;
padding:3em;
border: 3px solid #DDD;
}
</style>
</head>
<body>
<h1>AJAX SEO by solusiprogram.com</h1>
<h3>- support SEO uri without hash (#) or query (?)</h3>
<h3>- can run normally without javascript to comply SEO</h3>
<h3>- support Browser History Feature (Back/Forward Buttons)</h3>
<h3>- the uri and Page's Title changed as content changed</h3>
<h3>- support Html4 and Html5 Browser</h3>
<div id="menu">
<ul>
<?php echo $menu_display; ?>
</ul>
</div>
<div id="ajax_target">
<?php require( $page . '.html' ); ?> <!-- php fill ajax_target for the first load of this index.php then History.Adapter will replace it when user clicks a menu or back/forward browser button -->
</div>
</body>
</html>
Create home.html
This is Home Page
Create page1.html
This is Page 1
Create page2.html
This is Page 2
Create sitemap.xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://yourdomain.com/home/</loc>
<changefreq>daily</changefreq>
</url>
<url>
<loc>http://yourdomain.com/page1/</loc>
<changefreq>daily</changefreq>
</url>
<url>
<loc>http://yourdomain.com/page2/</loc>
<changefreq>daily</changefreq>
</url>
</urlset>
Create robots.txt
User-agent: *
Disallow:
Sitemap: http://yourdomain.com/sitemap.xml
Now you can try "http[:]//yourdomain.com/" with javascript turn on or off (to comply SEO).

Related

Laravel index route issue when using for a subsection in another fw (external public dir)

I'm using a Laravel app with an external public directory, e.g. root/Laravel, and root/html/public.
I need this app to load from a require on a php file (root/html/this-section.php) that already has another framework loading it, hence that other fw has its own head, and body tag. This app will load between the header and footer of that file.
When I set up the routes, i notice that both of the following routes work, but i get different results.
Route::get('/', 'HomeController#index');
Route::get('/this-section', 'HomeController#index');
# this also works as a substitute for above, still same issue though
Route::get('//', 'HomeController#index');
These are the same pages, the controller has the same code, I would expect that the pages load the same. Whats happening is the main index site.com/ is loading correctly, but the latter is loading without the html <head> and <body> tags which exist on this-section.php. So essentially, the latter is not loading the parent page, its only loading what it sees on the blade templates.
I suspect maybe either need to add a rewrite to the .htaccess to cover this, or set up a custom redirect or return of a view or response in the controller (I need help here with suggestions) where I can then make a second method, e.g. thisSectionIndex() and return that suggestion.
At first I had things working with overriding the public_path() to the correct path this-section however that backfired when i made the sub routes
e.g. when using the following route setup
Route::get('/', 'HomeController#index');
Route::get('/feature', 'SectionController#feature');
It caused the feature route to be 500 or 404, I think it couldn't find the files, so I realized I needed to unfortunately add in the /this-section portion to the route ,which opened a can of worms pretty much.
Route::get('/', 'HomeController#index');
Route::get('/this-section', 'HomeController#index');
Route::get('/this-section/feature', 'SectionController#feature');
ON a side note, some fallout for this which I found a temporary work-around for already, was {{assets()}} broke. I had assets() overridden to not have to use the this-section/ portion, e.g. like this {{assets(/this-section/css/styles.css)}}. The temp worksround was to unfortunately have to manually add the paths and forego using {{assets()}} altogether in the blade templates until i figure that part out, because no path is working for them now.
Some background info:
Im overriding the public path like this
#Laravel\app\SectionApplication
class SectionApplication extends \Illuminate\Foundation\Application
{
public function publicPath()
{
$newBasePath = $this->basePath . DIRECTORY_SEPARATOR . '..' .
DIRECTORY_SEPARATOR . 'html/this-section';
return $newBasePath;
}
}
#Laravel/bootstrap/app.php
// $app = new Illuminate\Foundation\Application(
// realpath(__DIR__.'/../')
// );
$app = new App\SectionApplication(
realpath(__DIR__.'/../')
);
Here is the pertinent(adjusted) parts of the laravel bootstrapper index (html/this-section/index.php)
function public_path($path = '')
{
return realpath(__DIR__);
}
//adjust your relative laravel framework path here
$laravelRelPath = '../../Laravel';
//override the blade {{asset()}} helper
function asset($path, $secure = null)
{
$newPubPath = 'this-section/'; //relative from html where the index.php will be
return app('url')->asset($newPubPath . $path, $secure);
}
.htaccess is located outside of Laravel, and in html/
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
#Rewritebase /this-section/
#RewriteRule ^(.*)$ this-section/$1 [L]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>
With the help of this topic
and this topic I found a working solution. Adjustments are needed When your loading in the application. You want to bootstrap it from the same path as the file loads the bootstrap, then override the .htaccess for that particular path only.
move laravels bootstrap file html/this-section/index.php file up one directory, next to the file html/this-section.php, and rename it to html/this-section-laravel-boostrap.php
adjust the path for laravel on html/this-section-laravel-boostrap.php by removing one directory ../
e.g. from $laravelRelPath = '../../Laravel'; to $laravelRelPath = '../Laravel';
add the following code to htlm/this-section.php (the file loads the bootstrap)
if (strpos($_SERVER['REQUEST_URI'],'this-section') !== false) {
require_once('this-section-laravel-bootstrap.php');
}
add the following to the .htaccess to snag the uri
#Rewritebase /
RewriteRule ^this-section/?$ / [L,NC]
The only route needed for this-section
Route::get('/this-section', 'HomeController#index')
In your blade templates, call your assets like this so they load on every sub sections url, e.g. for css
<link rel="stylesheet" href="/this-section/css/styles.css">
The application will now bootstrap, and always use the outer contents from the parent file that loads it. See below for an example parent test file(html/this-section.php) for this.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Parent Application</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
</head>
<body>
<header>
<nav>
<ul>
<li>menu</li>
</ul>
</nav>
</header>
<?php
<--! laravel sandwich -->
if (strpos($_SERVER['REQUEST_URI'],'this-section') !== false) {
require_once('this-section-laravel-bootstrap.php');
}
?>
<footer>
<p>Copyright <?php echo date('Y'); ?> - All rights reserved.</p>
</footer> -->
</body>
</html>
Bonus
assets are now loading correctly, you probably dont need step 5.
{{asset('css/vendors.css')}}

.htaccess, how can I remove pattern from url?

I would like to clean my urls from this:
https://example.com/track&id=180
to:
https://example.com/track/180
My code is as follow:
My .htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^welcome/([^/]+)/?$ index.php?a=welcome&filter=$1 [NC,QSA,L]
RewriteRule ^track/([^/]+)/?$ index.php?a=track&filter=$1 [NC,QSA,L]
RewriteRule ^(([^/]+)+)(/([^/]{0,32})(/.+)?)?$ index.php?a=$1&q=$3 [L,QSA]
But if I use the 2nd example (the url without &id=) via Ajax it returns "undefined".
I tried the Ajax call with this link button
Click Here
I supposed it's undefined because in my requests I get the id parameter in PHP as $_GET['id'];.
So my question is: why it doesn't work on Ajax?
Here is my functions.js
$(function() {
$("body").on("click", "a[rel='loadpage']", function(e) {
// Get the link location that was clicked
startLoadingBar();
pageurl = $(this).attr('href');
// Replace the path of the url from index to the path with raw content
var custom = pageurl;
var custom = custom.replace(baseUrl+'/track', 'page.php?a=track');
var custom = custom.replace(baseUrl+'/', 'page.php?a=welcome');
// Request the page
$.ajax({url:custom,success: function(data) {
// Show the content
$('#content').html(data);
// Stop the loading bar
stopLoadingBar();
// Scroll the document at the top of the page
$(document).scrollTop(0);
// Reload functions
selectExplore();
reload();
}});
// Store the url to the last page accessed
if(pageurl != window.location){
window.history.pushState({path:pageurl}, '', pageurl);
}
return false;
});
});
.htaccess isn't my forte, so any help would be much appreciated.
Thanks in advance.
You can use this JS code to send your AJAX call:
var custom = pageurl.replace(baseUrl+'/track/', '/page.php?a=track&id=');
// Request the page
$.ajax({url:custom,success: function(data) {
// ...
}

Magento Nopin for entire site

I would like to add pinterest's nopin code to my site, inside the <head>.
I am using a custom theme and navigated to: app/design/frontend/default/THEME NAME/template/page/html/head.phtml
I also tried: app/design/frontend/base/default/template/page/html/head.phtml
I pasted the nopin code provided by Pinterest:
<meta name="pinterest" content="nopin" description="Sorry, we do not allow pinning of our copyrighted materials" />
No joy! Is there a location that I can post this or do I need to protect each image another way?
If you want to cover the entire site, the tag must be placed in
\app\design\frontend\default\theme_name\template\page\html\head.phtml
assuming Current Package Name is "default".
Flush the cache and reindex all the data
Tested on my dev site and is showing the message: "Sorry, we do not allow pinning of our copyrighted materials"
Also check your pinterest code. I use this one:
<a href="//www.pinterest.com/pin/create/button/" data-pin-do="buttonPin" data-pin-config="beside" >
<img src="//assets.pinterest.com/images/pidgets/pinit_fg_en_rect_white_20.png" /></a>
<script type="text/javascript">
(function(d){
var f = d.getElementsByTagName('SCRIPT')[0], p = d.createElement('SCRIPT');
p.type = 'text/javascript';
p.async = true;
p.src = '//assets.pinterest.com/js/pinit.js';
f.parentNode.insertBefore(p, f);
}(document));
</script>
Hope this helps

RewriteRule Form Get Request

When i submit my form this is my url:
index.php?pagina=search&terms=soccer
I want to change it to:
/pagina/search/terms/soccer
what I have so far doesn't work
#searchRewriteRules
RewriteCond %{QUERY_STRING} ^terms=([a-zA-Z0-9]+)$
RewriteRule ^index.php$ /pagina/search/terms/%1? [R=301]
Could somebody help me
Your query string is pagina=search&terms=soccer. You need to match that completely. Please note that if you are doing a POST request you loose the POST body on the redirect. Besides that you need to translate the pretty url back to the normal url, and prevent an infinite redirect from happening.
RewriteCond %{THE_REQUEST} ^(GET|POST)\ /index\.php?pagina=search&terms=([a-zA-Z0-9]+)\ HTTP
RewriteRule ^ /pagina/search/terms/%2? [R=301,L]
RewriteRule ^pagina/search/terms/(.*)$ /index.php?pagina=search&terms=$1 [L]
it's working with jquery.
I have created a new page called rewritesearch.php and inserted into my main page where the form is.
rewritesearch.php
// Base Url
$url = BASE_URL;
echo <<<EOT
<script>
$(document).ready(function() {
$('#submit').click(function() {
// get the terms value
var terms = $('.search').val();
goUrl = '{$url}pagina/search/terms/'+terms+'/';
window.location = goUrl;
return false; // Prevent the default button behaviour
});
$('#search_form').submit( function() {
return false; // May be necessary to prevent the default form behaviour
});
});
</script>
EOT;

Printing pdf from iframe not working in mozilla

I want to print pdf inside an iframe. It works perfectly in chrome, but in mozilla, it's not working at all. do you guys have any solution for this?
<iframe id="pdftoprint" style="display:none; position:absolute;" src="sample.pdf" type="application/pdf"></iframe>
<div class="buttonimage"><img src="print.png" onclick="print_elem('pdftoprint')"></div>
function print_elem(elem_name)
{
var elem = document.getElementById(elem_name);
elem.contentWindow.focus();
elem.contentWindow.print();
}
The problem is that Firefox will not let you access the element if the URL of the page does not start with www. Try adding this script to the top of your page:
<script type="text/javascript">
if ( location.host.toLowerCase().substring(0,3) != "www" )
{
location.href = location.href.replace( /\/\//, "//www." );
}
</script>
This will redirect the user to a the same URL but adds www. to the start of it. Hope this helps, it worked for me.

Resources