NOP people and learning Ruby

Some people can’t just sit and do nothing, I know that cause I’m one of them… I call these people: *NOP people. Even a ride on the elevator is just enough time to check emails and tweeter, and that’s also why I always need a side project. Last year I committed to PHP and MySQL (LAMP), even though I read some awful things about it, I decided to learn some PHP because there are so many CMSs built with LAMP:WordPress, Drupal, Joomla… and carts as well: Magento, Zen cart, Open cart

For year 2013 I decided to learn Ruby and Ruby on Rails. For those of you who don’t know the difference, it’s simple:

Ruby – scripting language that has many cool features such as dynamic typing (also known as “duck typing”)

Ruby on Rails – web framework for Ruby that provides many libraries that’ll make your life much easier. RoR, like Ruby, is provided free and is open source.

I have to admit that until the end of February I thought that Python will be the winner but then I ran into Rubymonk and it just caught me. In parallel to Rubymonk, I re-solved about 30 challenges in codeeval – because of the first rule of programming: you can’t learn a new language just by reading!

When I started coding in Ruby, I was looking for a good IDE for Mac and after some Googling work I decided on Sublime Text Editor. It takes a little time getting used to it, but when you learn shortcuts like command+R – jump to another function, or, command + P – to browse between files, and the very convenient tab completion (ife, tab for if-else-end for example) and many other shortcuts which you can browse yourself by typing command + shift + P. God bless sublimeText!

I didn’t take any of the in from Try Ruby but I bet that they’re good, and I can say that because I took a few classes in Rails for Zombies and it was fun! I would definitely check out the other classes in codeschool.

On my next NOP of course..

______________________________________________________________________________.

*NOP – In computer science, NOP or NOOP (short for No Operation) is an assembly language instruction, sequence of computer programming language statements, or computer protocol command that effectively does nothing at all. (from wiki)

Advertisements
NOP people and learning Ruby

Patent troll Uniloc takes a hit

A few months ago I wrote a post about intellectual property telling the story of a small company called Laminar Research which might be forced to shut-down due to a lawsuit they’re facing.

Well, I was glad to read this morning that the same patent-troll, Uniloc, got their claim against Rackspace dismissed by a chief judge Leonard Davis which based his ruling on U.S. Supreme Court case law that prohibits the patenting of mathematical algorithms. This is the first reported instance in which, an early motion to dismiss finding a patent invalid because it claimed unpatentable subject matter, is granted.

Rackspace, even though being way bigger than Laminar research, still needed Red Hat support which provided Rackspace’s defense. Laminar research were not that fortunate. Just a thought.

Patent troll Uniloc takes a hit

Using API to create single-click order experience

On the previous posts we went over the different options of online payment processing and then dived a bit deeper into a discussion about how user-experience effects the conversion and how can we improve both by using an API.

The last two examples showed how to use an API in order to create a shopper entity on Bluesnap servers and then use it with a token (which was generate by the API as well) in order to “log the shopper into” a buy page, meaning, redirect the shopper to a buy-page where all his information (except the billing information) is pre-filled. The reason we couldn’t pre-fill the billing info is due to regulations forced on us by the credit-card companies: a merchant which is not PCI compliant, should not hold billing information records of his/her customers. It sounds like this restriction sucks, but it’s actually very good since it forces us to protect our clients data!

That said, we still want to provide the best customer experience to our shoppers, and by using an API we can do just that. The last post gave us the “taste” of what can be achieved and now we’ll see the “real thing”: after a shopper already placed an order and bought one of our products, we may offer the customer a promo-code for future purchase or an upgrade for a reduced price etc. Even though we don’t have the shopper’s billing information the processor (Bluesnap) does – and we’ll take advantage of it to create a single-click order experience.

Since we created the shopper entity we have a “shopper-id” (unique identifier for a shopper – supplied by the processor) which we can use to place future orders:

<?php
/*
 * Written By: Ben Hultin & Nir Alfasi (alfasin)
 * Nov. 2012
 * 
 * This code is used to call an API (RESTful) service of Bluesnap that places an order on Bluesnaps' backend.
 * We chose using CURL to place the API request in this demo, but we urge anyone who implements an API client 
 * to work with a RESTful API client framework in order to have a full support of all the properties of REST, such as: 
 * set HTTP method, get return-code, read/write headers, full XML support etc.
 * 
 * The API manual is available under "Developer Toolbox" section: 
 * http://www.bluesnap.com/helpcenter/Static/default.htm?bluesnap_web_services.htm
 * 
 */

//here we define $credentials = $username . ":" . $password;
include_once('../credentials.php'); 



/**
 * Retrieve data from input fields
*/ 
$shopperId = $_REQUEST['shopper-id'];   		
$cardLastFour = $_REQUEST['card-last-four-digits'];     		 
$cardType = $_REQUEST['card-type'];
$skuId = $_REQUEST['sku-id'];
$amount = $_REQUEST['amount'];
$currency = $_REQUEST['currency'];
  

/**
 * Assemble the XML string with variables instantiated above
*/  
$xmlToSend = '<order xmlns="http://ws.plimus.com">
 <soft-descriptor></soft-descriptor>
   <ordering-shopper>
    <credit-card>
                  <card-last-four-digits>'.$cardLastFour.'</card-last-four-digits>
                  <card-type>'.$cardType.'</card-type>
    </credit-card>
    <shopper-id>'.$shopperId.'</shopper-id>
            <web-info>
                <ip>'.$ipAddress.'</ip>         
                <remote-host>bzq-219-121-253.static.bezeqint.net.reinventhosting.com</remote-host>
                <user-agent>Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; GTB6.3; .NET CLR 2.0.50727)</user-agent>
                <accept-language>en-us</accept-language>
            </web-info>
   </ordering-shopper>
   <cart>
      <cart-item>
         <sku>
            <sku-id>'.$skuId.'</sku-id>
         </sku>
         <quantity>1</quantity>
        </cart-item>
   </cart>
   <expected-total-price>
      <amount>'.$amount.'</amount>
      <currency>'.$currency.'</currency>
   </expected-total-price>
</order>';
        
        
/**
 * Initialize handle and set options
*/
$url = 'https://sandbox.plimus.com/services/2/orders/';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_HTTPHEADER, Array("Content-Type: application/xml"));
curl_setopt($ch, CURLOPT_USERPWD, "$credentials");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlToSend);	
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);


/**
 * Execute Curl call and display XML response
*/
$response = curl_exec($ch);
curl_close($ch);

echo show_xml($response);
?>

By clicking on the following link you’ll place a (single-click) order in Bluesnap’s sandbox using the API code displayed above.

Using API to create single-click order experience

Improving Customer-Experience and Conversion with API

Important: all the links and the code-examples that are embedded in this post, link toPlimus service in  Bluesnap’s sandbox – so feel free to play with it – all the credit-card charges are not real!

On the previous post , we talked a bit about the different options of online payment-processing and now it’s time to talk about the “how”.

One of the nightmares of every marketer is abandoned carts, in this post we’ll see how you can use an eCommerce API in order to create a better shopper experience and as a result to improve the conversion rate.

There are so many theories that deal with customization of a Buy-Page , lists of Do’s andDon’ts  and so on and so forth . People like to think that there’s some secret formula that once applied – conversion will rocket high.

The truth is that there are many different truths that apply to different types of businesses, for example, if your online store sells SSL-certificates or Anti-virus software (or any other protection-software like firewalls) you really should have a ’Hacker Safe’ logo or something alike – your buyers WILL look for it on their checkout page and if it won’t be there – it will be a little suspicious…

There are products for which you’d better customize a single-checkout page process (letting the customer enter his personal details and credit-card information on the same page), such a single checkout page usually works fine for low-price items, but if your product includes shipping, for example, then a two-pages checkout will work better in most of the cases.

Like I said – there’s no “secret trick” and if you want to confirm that you did a good job, A/B testing should be applied (if you can’t measure it – you can’t prove that it works!).

Still, there are a few “universal truths” that can be applied to your store, and this is what we’re going to deal with in this post, so roll your sleeves up and let’s get to work!

If your website support user-registration, making the shopper enter ALL his personal information AGAIN in the checkout page is not a very nice user experience to say the least. That’s exactly why we should use the create-shopper API call . An example of how it works can be viewed here . As you can see, the PHP code is pretty simple and short (if you remove the comments you’ll see that it’s about 60 lines of code):

<?php

/*
 * Written By: Ben Hultin & Nir Alfasi (alfasin)
 * Nov. 2012
 * 
 * This code is used to call an API (RESTful) service of Bluesnap that creates a shopper entity on Bluesnaps' backend.
 * The shopper-entity can be used, later-on, for one-click purchases, to automate charges, to retrieve orders history and more.
 * We chose using CURL to place the API request in this demo, but we urge anyone who implements an API client 
 * to work with a RESTful API client framework in order to have a full support of all the properties of REST, such as: 
 * set HTTP method, get return-code, read/write headers, full XML support etc.
 * 
 * Documentation on "create shopper" service can be found here: 
 * http://home.plimus.com/DocumentationCenter/Static/Plimus%20Web%20Services_create_shopper.htm
 * 
 * The API manual is available under "BuyAnyware" section: 
 * http://home.plimus.com/DocumentationCenter/Static/default.htm
 * 
 * This code example is also available from: 
 * https://alfasin.com/api/create_shopper.html
 *
 * and if you want to see it "in action": 
 * https://alfasin.com/create_shopper.php
 * 
 */
    

    // In the response of "create-shopper" API call we'll receive the 
    // newly created shopper-id which we should extract from the Location header. 
    // An example for such header: 
    // 
    // ...
    // Location: https://sandbox.plimus.com/services/2/shoppers/19372564
    // ...
    function get_shopper_from_header($ch, $string) {
        global $shopper_id;       
        //looking for the "Location" header - but since it's case insensitive...
        if(strpos($string, "ocation") > -1){ 
            $tokens = explode("/", $string);
            //the shopper-id will always be the last token
            $shopper_id = trim($tokens[count($tokens)-1]); 
        }  
        return strlen($string);
    }

   // TODO: Change the following URL to our rackspace machine
   // An example of how to call this PHP code:
   // https://alfasin.com/blog/code/create_shopper.php?firstName=bob&lastName=Smith&email=bob.Smith@gmail.com&address1=123 Main Street&address2=Apt K-9&city=Parkville&state=TN&country=us&phone=411-555-1212&zipcode=37027

   // read the request parameters and handle special chars 
   $firstName = htmlspecialchars($_REQUEST['firstName']);     	 
   $lastName  = htmlspecialchars($_REQUEST['lastName']);     		 
   $email     = htmlspecialchars($_REQUEST['email']);                    
   $address1  = htmlspecialchars($_REQUEST['address1']);
   $address2  = htmlspecialchars($_REQUEST['address2']);
   $city      = htmlspecialchars($_REQUEST['city']);
   $state     = htmlspecialchars($_REQUEST['state']);
   $country   = htmlspecialchars($_REQUEST['country']);
   $zipCode   = htmlspecialchars($_REQUEST['zipcode']);
   $phone     = htmlspecialchars($_REQUEST['phone']);
      
   // EXAMPLE INPUT
   // -------------
 $firstName = 'Bob';   		 
 $lastName = 'Smith';     		 
 $email = "bob.smith@plimus.com";      
 $address1 = "123 Main Street";
 $address2 = "Apt K-9";
 $city = "Parkville";
 $state = "TN";
 $country = "us";
 $zipCode = "37027";
 $phone = "411-555-1212";
   

   // In the following XML (which will be embedded in the BODY of the HTTP request) 
   // the <web-info> element supposed to hold customers' information (IP, browser type etc) 
    $xmlToSend = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>
    <shopper xmlns=\"http://ws.plimus.com\">
          <shopper-info>
                <shopper-contact-info>
                      <first-name>". $firstName ."</first-name>
                      <last-name>". $lastName ."</last-name>
                      <email>". $email ."</email>
                      <address1>". $address1 ."</address1>
                      <city>". $city ."</city>
                      <zip>". $zipCode ."</zip>
                      <country>". $country ."</country>
                      <state>". $state ."</state>
                      <phone>". $phone ."</phone>
                </shopper-contact-info>
                <locale>en</locale>
          </shopper-info>          
          <web-info> 
                <ip>62.219.121.253</ip>
                <remote-host>bzq-219-121-253.static.bezeqint.net.reinventhosting.com</remote-host>
                <user-agent>Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; GTB6.3; .NET CLR 2.0.50727</user-agent>
                <accept-language>en-us</accept-language>
          </web-info>
    </shopper>";

    // Set values for the POST HEADERS:
    // The URL sets the REST resource which is being called 
    $service = 'https://sandbox.plimus.com/services/2/shoppers';
    // for the sandbox testing account TODO: include this parameter from another file and remove explicit credentials from the code
    $credentials = 'XXX:YYY'; 
    $contentType = array('Content-type: application/xml');
    
    // Initialize handle and set options
    $ch = curl_init();
    // more info about setopt options can be found here: http://www.php.net/manual/en/function.curl-setopt.php
    curl_setopt($ch, CURLOPT_URL, $service); 
    curl_setopt($ch, CURLOPT_USERPWD, $credentials); // authentication (credentials) string encoded in base-64 
    
    curl_setopt($ch, CURLOPT_HEADER, true);          // include the headers in the output
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  // don't output the response to screen (default behavior)
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlToSend);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $contentType);    
    curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'get_shopper_from_header');
    
    // The following switches are needed only when running in development-mode on localhost
    //    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);  // follow redirects recursively 
    //    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // default value is "2": "check the existence of a common name and also verify that it matches the hostname provided" - we need to turn it off
    //    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // "stop cURL from verifying the peer's certificate"
    
    // For debugging purposes - we can ask the remote server to include all the request-headers in the response
    //    curl_setopt($ch, CURLINFO_HEADER_OUT, true);
    

    // Execute the request and example code to time the transaction
    $response = curl_exec($ch);           
    // if a shopper was successfully created we should receive "201 created" response code
    // and the shopper-id will be extracted into $shopper_id by get_shopper_from_header() which will iterate the response headers
     
    // Check for errors
    if ( curl_errno($ch) ) {
        echo 'HTTP error code: ' . curl_errno($ch) . '<br>error-message: "' . curl_error($ch) . '"';
        return;
    } 

    // SUCCESS
    if (is_numeric($shopper_id)) {
	echo '<br>
              A new shopper entity was created on our servers with shopper-id: '
              . $shopper_id .
              '<br><br>';
    }
    // FAIL
    else {
        echo '<br><br>
              <font color="red"><b>Something went wrong!</b></font>
              <br>
              Server reponse:
              <br><br>
              <pre style="display: block; font-family: monospace; white-space: pre; margin: 1em 0px;">'
              . $response .
              '</pre><br>';
    }
?>

This code is using what we call  authentication-token auto-login API call . If we scroll back a bit and click again on the “create-shopper” demo, we can see that in the response we receive a shopper-id. This ID can be used in order to generate an authentication token which in return can be used to auto-login the shopper into one of the buy-pages (step-1 and step-2) or into the shopper control-panel.

On the next post we’ll implement a real single-click purchase process after which I’ll explain the PCI-compliance issue involved and lay-out how can we work around it (in a legit way of course!) until then, you can enjoy the Harlem shake in the bitwise version

Improving Customer-Experience and Conversion with API

Online Payment Processing

ecom

I started writing a post that demonstrates how a vendor can use API calls in order to create a better shopping experience and help convert shoppers into buyers. But after a few lines I figured that there is a basic terminology and motivation that might be obvious to me (since I worked in the eCommerce industry for the last 6 years) but not necessarily to the readers… So I decided to write a “pre-post” that will provide an overview about online payment-processing  – and only then I’ll move on to implementing API calls and suggestions to improve your conversion rate.

There are many developers out there that build cool software, apps, plugins etc – but have no idea how to sell it. Some of them just open a Paypal/Google wallet/Authorize.NET account, implement their API/HTTP-redirect and think that they’ve done the best thing possible. Well, think again!

Let’s start with some

Definitions & Terminology

Payment Gateway” or “Payment Processor” – In order to simplify things, we’ll treat the two as the same: a company or a third party in which the merchant (developer) opens a merchant-account and which processes transactions by moving the money from the customer’s issuing bank to the merchants’ bank.

Motivation

There are two major problems with Paypal/G-Wallet/Authorize.NET:

1. You, the developer, need to take care (implement) all the possible scenarios:  success, and possible failure reasons (display the proper error), calculate the currency conversion rates, hedge the amount in case the currency-rates change dramatically and the customer asks for a refund (or alternatively, lose money…) and that’s only part of the list of issues that should be handled.

2. Localization: there are so many potential-customers in other parts of the world that won’t buy since your buy-page is not translated to their language and the payment options you offer are not popular in their countries. For example, in the Netherlands (where you process in Euros) there’s a payment method that most of US residents probably never heard of, called iDEAL.

If you’re a good programmer, you’ll probably work hard and solve most of the critical issues in #1, but the issues in #2 are not solvable unless you do one of the following:

  • use the services of a professional online payment processor (such as Bluesnap or DR)
  • implement a full eCommerce solution…

Of course that there are many other reasons to go with a professional online payment processing solution, and maybe the most important of which is having a fail-over mechanism, for example, if you tried to process a credit-card with Authorize.NET and Wells-Fargo returned a generic error, you can try processing the same transaction with a different gateway instead of loosing business.

Why shouldn’t I use Authorize.NET ?

You may decide to use Authorize.NET, but then you’ll loose market segments such as:

  • Businesses in countries which don’t favor credit-card transactions
  • B2B – which normaly use PO (purchase orders), check or wire transactions
  • Local customers that feel more secure using their Paypal accounts, checks or other payment options

So, When SHOULD a developer use Paypal or Authorize.NET ?

To my opinion only if you do micro-payments, or, if you belong to a small segment of businesses that process mainly local transactions in USD and target customers that use only credit-cards.

Why do I say “almost never” ?

Business owners prefer using Paypal or Authorize.NET because of the low commission-rates (around 3%) comparing to a full payment processing solution which charges somewhere between 5-15% (depends on the transaction amount). But, if we do the math, one deal that you loose because you couldn’t support the payment-method/fail-over mechanism – could “cover” a commission rate difference of another 10-15 transactions!

What I like the most about using a professional payment processing solution is that you can setup an account and start selling in less than five minutes. Want to see for yourself ? Just open an account on Bluesnap sanbox (it’s free!) and follow the go-guide to setup a product: all you have to do is choose a name, short description and a price. After a product was created – automatically the platform creates a contract/SKU – which is the *real* thing that we’ll sell. A good example to understand the difference between a Product and a Contract is to think about a product as “Microsoft Office” and the contract as “Student version” or “Home edition”. You can see that the product is an abstract entity (like a Class) while the contract is the Object or a product Instance if you will.

product-setup-300x171

product setup 1st step

product-setup-2-300x192

product setup 2nd step

Once a contract was created – you can go to the contract’ “General” settings-page (there are many configurable options – but we’ll ignore it for now), copy the “Buy-link” and paste it into your browser

contract-setup-300x157

contract setup page

it will take you to your newly sandbox buy-page. If you want to place an order – you can use a generic “Visa” credit-card: 4111-1111-1111-1111 (you can enter any 3-digits in the “Security Code” field) and place an order. An example for such a buy-page: https://sandbox.plimus.com/jsp/buynow.jsp?contractId=1711978

After you’ve gone through that – you’re ready to take the “advanced class” and start playing with the API – on which I’ll write the next post.

Disclaimer
I work for Bluesnap – an online payment-processing company, but with that said, I am not one of the owners and currently I don’t hold any shares/options!

Online Payment Processing

Blog renovation

In this world of technology using wordpres for blogging seems to be the right choice, I mean, in the last couple of months I noticed that I kept postponing writing stuff in my blog due to the overhead of maintaining my own simple html blog. So I finally took the time to install & configure WP and boy, that wasn’t simple…

I think that for non-developers it would be a quite tedious task if not impossible. For example, in order to fix a bug (the “continue reading” feature didn’t work) I had to go to different forums until I finally found out that I need to change code in /wp-content/themes/<my template>/content.php

And that was only one of the tweaks I had to do. If I would start listing all the problems I had, then the most important ones will be:

  • folder permissions problem – prevents you from upload media and plugins to your server (to fix you have to run chown and chmod from linux prompt!)
  • fix .htaccess (because of the same permissions issue) manually in order to add WP additional lines
  • manually set favicon.ico turned out to be a real pain too (edit /wp-content/themes/<my template>/header.php)
  • manually change /wp-content/themes/<my template>/footer.php to NOT display “Proudly powered by…”

But on the bright side:

  • It’s so nice to easily install (after you got over the permissions-issue) plugins like:Sociable and All in One SEO Pack
  • The speed is very good even though I didn’t install a cache-plugin just yet (this is also the place to recommend the CDN services of cloudflare (I use their free package)
  • easy to choose, install and configure a template (but then again, if you’re very meticulous and want to move a certain line one millimeter to the right – get ready to dive into tons of php & css code…)
  • you get to have comments “out of the box”
  • and much more (tags, categories, menus, tons of free plugins etc)

So by all means, if you’re using another CMS for blogging purpose (I had my experience with Joomla, Drupal and Magento store – but I got to admit that I didn’t try blogger) you should re-consider your choice.

I’ll wrap up with the following cute joke:
A programmer tells his friend that yesterday he almost got busted when his wife asked him which one he loves more: her or his computer.
Friend: So, what did you reply ?
Programmer: I said I love her more
Friend: good choice! so, why do you say you almost got busted?
Programmer: cause luckily, she didn’t ask me about my laptop…

Blog renovation

SEO Made Simple – book summary and review

seo

A good friend of mine runs his own company. He always paid 3rd parties to handle his SEO but, as a developer, he felt he should put the effort into learning, at least the basics, so that he could understand if the money he’s spending on these services has a good ROI. So a few days ago he came to me all enthusiastic about this great SEO book. I love learning new stuff, and today, whatever your business is – you have a website, so SEO becomes more and more important. Now, I already read plenty of stuff about search engine optimization (there’s tons of free stuff on the web), but I never really read anything that was structured in a methodical way, well organized and that goes over all the different subjects – I couldn’t resist borrowing (and soon after’ ordering) it!

Relatively, it’s a short book (about 130 pages) but it summaries all the basic principles of SEO, it provides all the “DO’s” and “DON’Ts”. I was already a few pages into the book when a thought came into my mind: why not create a short summary of this book, and add my own “take” during the process. Now you might think, if I already got the summary – why should I buy the book ? well – you really don’t have too (I’m not getting paid any commission :D ), but, bare this in mind and it’s true for any good technical book – you can’t read it once (let along summary) and grasp it, you’ll find yourself going back to the book, again and again, looking up things you read but don’t remember exactly to the small details. And besides, I believe that if someone took the time and effort to write a book, and the outcome is good – he should be rewarded!

After this long intro, let’s get down to business, here it goes:

Meta Tags

TITLE

Keyword/phrases – up to 7 words, can be two phrases separated by “|”

DESCRIPTION

Use your keywords twice (not more!) – do not stuff keywords – it has to be a good description (seems natural) for click-through rate

KEYWORDS

Less important. Do not repeat the same keyword consecutively (i.e. marketing, marketing resources,…) avoid stuffing!

ROBOTS

<meta name=”robots” content=”all”> encourages crawlers to crawl ALL the pages in your website

URLs

FORMATTING

Content first, clean code (http://validator.w3.org), no JS no flash no styling – extract all non-SEO relevant data to external files), heading tags (1-3 is enough), title, alt tags, favicon, proper keywords placement, internal linking (using navigation menus and anchor text) and sitemap.xml. If your site loads fast (pagespeed/YSlow!) – You’ll get extra points with Google, same goes for schema.org

CONTENT FIRST

The location of the content should be “above” the links, if possible, always think about the order in which crawlers scan the page.
A good example to “content first” will be:

1 Header – logo etc.
2 3 Content
4 Menu/links

 

PROPER KEYWORD PLACEMENT

Place your keywords in:

  • meta-tags
  • title
  • headers
  • first 25 words of the page
  • last 25 words of the page
  • bold font (at least once)
  • italic or underline font (at least once)
  • in the footer/ copyright section
  • define the content of your site in general terms
  • identify keywords related to the topic
  • use google keyword tool
  • select 10-30 keywords based on:
    • at least 3000 monthly searches
    • less than 50,000 monthly searches
    • eliminate unnatural phrases
    • commercial intent – conversion of a keyword in the range of (0,1)
    • KEI (keyword effectiveness index) – calculated by the formula [number of monthly searches/number of competing sites] where number of competing sites is the number of results that returns from Google. Rule of thumb: this should be less than 3M.
    • Most important: research the competition!
      • Use wordtracker (free trial)
      • Use FF plugin: SEO quake
      • More relevant tools in the link in the header
      • Find top ranking sites for these keywords and check their SEO (on-page, alexa etc.) look for:
        • Website URL
        • Google PR (don’t compete with sites that have PR6 or more)
        • Number of backlinks – no rule of thumb here
        • Keyword in meta-tags, headers, title, first and last 25 words, bold, italic and underline
        • Use NO MORE than 2-3 keywords per page

Keywords development

 

Off-Page SEO

  • The most important: about 85% of the weight of PR (vs. 15% on-page)
  • Directory & search engines submissions
  • It’s not the number of the backlinks – it’s the quality (PR)
  • It’s not only the quality but also the relevancy of these sites (backlinks)
  • Link types: one-way (best), reciprocal (link exchange/swap/partners), three-way (also good)
  • Build “partner page” with reciprocal links – not more than 100 (link farm). Place a link to this page from your home-page
  • Use “title” in href as well as good anchor text (can be two phrases separate by “|”), rel=”dofollow” and target=”_blank”
  • Link building using articles (1-2 per week)
  • Publish the article on your website first
  • Submit to article directories using spinner (about 25 directories per week)
  • Keep publishing moderately – otherwise google might consider it as SPAM
  • Directory submission: DMOZ, submit only to directories that review manually, reciprocal-links are good as long as the link to your site has higher PR than yours. Use directory submission software – do not SPAM.
  • Register your blog with directories: DMOZGoogleTechnorati.
  • Design your blog for SEO using on-page optimization techniques
  • Add RSS feed (needs to be updated regularly)
  • Update sitemap.xml (needs to be updated regularly)
  • Write weekly posts and submit to ping-o-matic
  • Enter your keywords in the “Name” field
  • Use real email address
  • Use complete URL
  • DO NOT post links in the comment
  • Write a good comment: relevant and at least 3 sentences long.
  • Google: “high PR do follow blogs” to find blogs for comments
  • Follow blogs with high PR so you can comment there from time to time – never comment more than once on the same post
  • Update new content at sites like: deliciousreddit and Digg
  • Add social buttons to your blog, you can use services like AddThis
  • Usually cost money – but it can be done in affordable ways
  • Create content which will be interesting and NEW enough to get picked up by News-sites:
    • Create a poll. A recommended way to do this is in your blog! 100 voters will be enough for first-time, usually 250 voters is a good threshold
    • Use services like surveyMonkey (~$20)
    • Press release distribution services usually cost in the range of $1-250
    • You can use a press release each time you add a new feature to your site
    • PRWeb – good but a bit pricey, PR-Inside and Free press release are more affordable for beginners
    • Find press release which already rank high for your desired keywords
    • Find forums related to your niche with high PR and “live” activity
    • Important: does the forum allows “do follow” links in the signature?
    • Many signatures allow up to 3 links – using 2 is enough
    • Some forums require you posting 10 comments before allowing you to use a signature
    • Use your keywords in the signature wisely
    • If you want to start promoting new keywords and you change your signature – it might affect old comments!
    • Posts/Comments should be relevant, meaningful and valuable
    • The goal is ~10 forums which you’ll regularly post/comment
    • It requires a lot of work! Consider outsourcing it only after you’ve posted at least the first round!

Blogging

  • Register your blog with directories: DMOZGoogleTechnorati.
  • Design your blog for SEO using on-page optimization techniques
  • Add RSS feed (needs to be updated regularly)
  • Update sitemap.xml (needs to be updated regularly)
  • Write weekly posts and submit to ping-o-matic

Blog commenting

  • Enter your keywords in the “Name” field
  • Use real email address
  • Use complete URL
  • DO NOT post links in the comment
  • Write a good comment: relevant and at least 3 sentences long.
  • Google: “high PR do follow blogs” to find blogs for comments
  • Follow blogs with high PR so you can comment there from time to time – never comment more than once on the same post

Social bookmarks

  • Update new content at sites like: deliciousreddit and Digg
  • Add social buttons to your blog, you can use services like AddThis

Press Releases

  • Usually cost money – but it can be done in affordable ways
  • Create content which will be interesting and NEW enough to get picked up by News-sites:
    • Create a poll. A recommended way to do this is in your blog! 100 voters will be enough for first-time, usually 250 voters is a good threshold
    • Use services like surveyMonkey (~$20)
  • Press release distribution services usually cost in the range of $1-250
  • You can use a press release each time you add a new feature to your site
  • PRWeb – good but a bit pricey, PR-Inside and Free press release are more affordable for beginners
  • Find press release which already rank high for your desired keywords

Forum Marketing

  • Find forums related to your niche with high PR and “live” activity
  • Important: does the forum allows “do follow” links in the signature?
  • Many signatures allow up to 3 links – using 2 is enough
  • Some forums require you posting 10 comments before allowing you to use a signature
  • Use your keywords in the signature wisely
  • If you want to start promoting new keywords and you change your signature – it might affect old comments!
  • Posts/Comments should be relevant, meaningful and valuable
  • The goal is ~10 forums which you’ll regularly post/comment
  • It requires a lot of work! Consider outsourcing it only after you’ve posted at least the first round!

Authority links: profile sites

Site in which you create a profile and can use it to comment, mainly forums, wikies, communities and such. There are services like Angela’s links that provide you with monthly high-PR profile sites [alfasin: I’m not sure how good this website is!].

SOCIAL MEDIA SITES

This part deserves a dedicated book, SEO Made Simple doesn’t say much about it, but it does provide rules of thumb: in every major social network (Facebook, Tweeter, Pinterest, Instagram etc.) – create a profile and as part of your profile link back to your website.

Facebook – you can create and promote a fan-page

Tweeter – use tags and lists (hash tags #) to link back and promote your content

YouTube – create a monthly video to promote you site, you can create a dedicated channel, in the beginning of the video description link back to your website and use your keywords

Google places – open an account and keep updating on a monthly basis with pictures and new content

Important:

Beware of fully automated tools! Consider outsourcing specific tasks instead. Recommended sites for outsource: odeskelance and upwardsseo, there are other famous outsource sites like: gurugetafreelancer and 99designs.

 

 


What can I say, Michael Fleischner did a wonderful job!
Now back to programming (to be continued…)

SEO Made Simple – book summary and review