Spin Text For SEO – A PHP Spinner

I recently had an SEO expert give us a few hours of his time to provide some suggestions to compliment our SEO strategy. One of the techniques that he introduced I was so impressed with (due to it’s utter simplicity) that I am kicking myself for not thinking of it before! Basically, if you have ‘doorway’ pages into your site (e.g. you have pages for ‘Cambridge Widgets’ and ‘Preston Widgets’ and alike) and want them to be dynamically generated, from the same content, but not to suffer horrible duplicate content penalties, you can use a ‘spinning’ function to generate contextually similar, different, content. The original concept is here, but I have enhanced it a bit to better suit my needs.

The original function had a few issues which made it unsuitable for my use, but a train journey home after our meeting provided me with ample time to enhance it for my needs. Basically I needed it to be:

  • either pseudo random or predicable (always the same on a per page basis) without including a block of code outside the function
  • able to include curly braces without spinning – just make the function require two braces, not one (i.e. {{spin|me}} )
  • able to use the same ‘spin block’ (i.e. {{phrase 1|phrase 2|phrase 3}}) multiple times, but treat each one differently
  • able to calculate the number of permutations that I was passing in (to ensure I was waaaay over the number of pages I was driving from one set of text)

None of these were difficult to add and I eventually ended up with two functions (the spin function and one to replace only the first instance of a string) for the job:

function spin($string, $seedPageName = true, $calculate = false, $openingConstruct = ‘{{‘, $closingConstruct = ‘}}’, $separator = ‘|’)
{
# Choose whether to return the string or the number of permutations
$return = ‘string’;
if($calculate)
{
$permutations = 1;
$return = ‘permutations’;
}
# If we have nothing to spin just exit (don’t use a regexp)
if(strpos($string, $openingConstruct) === false)
{
return $$return;
}
if(preg_match_all(‘!’.$openingConstruct.'(.*?)’.$closingConstruct.’!s’, $string, $matches))
{
# Optional, always show a particular combination on the page
if($seedPageName)
{
mt_srand(crc32($_SERVER[‘REQUEST_URI’]));
}
$find = array();
$replace = array();
foreach($matches[0] as $key => $match)
{
$choices = explode($separator, $matches[1][$key]);
if($calculate)
{
$permutations *= count($choices);
}
else
{
$find[] = $match;
$replace[] = $choices[mt_rand(0, count($choices) – 1)];
}
}
if(!$calculate)
{
# Ensure multiple instances of the same spinning combinations will spin differently
$string = str_replace_first($find, $replace, $string);
}
}
return $$return;
}
# Similar to str_replace, but only replaces the first instance of the needle
function str_replace_first($find, $replace, $string)
{
# Ensure we are dealing with arrays
if(!is_array($find))
{
$find = array($find);
}
if(!is_array($replace))
{
$replace = array($replace);
}
foreach($find as $key => $value)
{
if(($pos = mb_strpos($string, $value)) !== false)
{
# If we have no replacement make it empty
if(!isset($replace[$key]))
{
$replace[$key] = ”;
}
$string = mb_substr($string, 0, $pos).$replace[$key].mb_substr($string, $pos + mb_strlen($value));
}
}
return $string;
}

And an example:

$string = ‘{{The|A}} {{quick|speedy|fast}} {{brown|black|red}} {{fox|wolf}} {{jumped|bounded|hopped|skipped}} over the {{lazy|tired}} {{dog|hound}}’;
echo ‘<p><b>’.spin($string, false, true).'</b> permutations…</p><p>’;
for($i = 1; $i <= 5; $i++)
{
echo spin($string, false).'<br />’;
}
echo ‘</p>’;

Which produces:

576 permutations…

The speedy black wolf bounded over the lazy hound
A speedy brown fox skipped over the tired hound
The quick red wolf bounded over the lazy hound
The fast brown fox hopped over the tired dog
The speedy brown fox jumped over the tired dog

I’m sure that it isn’t perfect, but perhaps it will provide inspiration to someone else, like it did for me!

 

http://www.paul-norman.co.uk/2009/06/spin-text-for-seo/

Leave a comment