Alex Pooley's Blog

Hello there, my name is Alex Pooley and I'm a freelance web developer residing in Perth, Western Australia. My passion is in the development of web sites that solve everyday problems. Here's a gallery of some of my notable work. If you need a web site designer or developer, contact me with further details. Lastly, you can read more about me.

Keyword Research With Keyword Explode

February 27th, 2007


keyword research

I haven’t posted to my blog for a while because I’ve been in the lab working all hours to finish my latest product. I’ve just released a new product for the search engine marketing crowd. Keyword Explode is a desktop application that will build a list of base keywords so quickly and so comprehensive that you will literally blindside your competition.

For those who are unaware, there are two sides to the search engine optimization equation. There are the searchers that send out queries to search engines, and there are publishers that provide what searchers are looking for. The job of a search engine is to connect these two groups as efficiently as possible. The more accurately a web page can tailor it’s content, back links, and adverts around search terms, the better the page will rank in the search engines for those particular search terms.

The typical strategy is to create a base set of keywords that broadly defines what content/search terms a site is targeting, and then to use the base keyword list to create more specific terms that pages, links, ads will target. So, say you wanted to start a blog about horses. Your base keyword list may be something like:

  • horse
  • donkey
  • pony

If you could, you would target these keywords directly in your content/links/ads but they are way too competitive. Therefore, it’s necessary to target something we are more likely to compete with. To do this, we create more specific terms using modifiers and the base keywords above. Modifiers we may use include:

  • brown
  • American
  • evil

Then you permute the modifiers with the base keywords so you get:

  • brown horse
  • American horse
  • evil horse
  • brown donkey
  • American donkey
  • evil donkey
  • brown pony
  • American pony
  • evil pony

Another option instead of adding modifiers to the base keyword list is to use search mining services. These services mine what search terms users search with, and can return more specific search terms for whatever keywords you have. Say you ask for more searches that include the term “horse”. The mining service may return a bunch of results and one of them might be the query “American brown horse” with an estimated 1,500 searches over the last 30 days.

By creating more specific keywords we have narrowed the amount of other publishers we have to compete with. The problem is that the process I’ve just gone through is pretty much the process everyone goes through. So now instead of competing against 100 people with “horse”, we’re targeting 80 of those 100 by aiming for “brown horse”.

To gain an edge, extensive keyword research is performed in the hope of finding keywords that other people haven’t thought of. There’s a few problems with this:

  1. It’s very time consuming
  2. There are still other people that will perform the same research you do. This includes reading the same top 10 Google results that you read.
  3. Because the English language is finite, there is a finite set of keywords. Yet, you never know how many more unknown words there are to find. Imagine researching for an extra half day for nothing because you already had an exhaustive list of keywords.

The trick in keyword research is to find the most base keywords possible, because all your other efforts derive from the base keyword list. Adding just one extra base keyword can result in exponentially more content, links, and ads. The bonus with lots of base keywords, is that the more you find, the less likely your competition will have all of them.

Keyword Explode solves these problems through it’s understanding of words and word relationships. With Keyword Explode, you can very quickly build a comprehensive list of base keywords that you can use to build content, links, and ads. All you need to do is think of some seed words for your niche, to use the previous example above we could simply use “horse”. Then you iterate through a process of expanding your current list of keywords, and culling what you don’t want. It’s essentially a three button process that will only take you a few minutes. You can watch a demo of the keyword research tool.

Keyword Explode is much more than a fancy thesaurus. A thesaurus only understands similar words, Keyword Explode knows similar words too, but it also understands that a beagle is a dog, a tire is part of a car, and that a house contains a toilet. You simply will not find anything else like this on the market. There are some services that return keywords your competition are using, but what good is it using the same keywords our competition are using? That’s exactly what we are trying to minimize!

I have more information about keyword research and information on related stuff like latent semantic indexing and the long tail over at the Keyword Explode product page. Check out those links and you will see that Keyword Explode is the easiest, and most comprehensive keyword generation tool around.

30% affiliations are available, sign up here. For a limited time only, and at my discretion, I’m offering SEO/SEM bloggers/web sites with an Alexa under 50,000 a free copy of Keyword Explode. No strings attached. Please use the contact form and include the URL of your blog/site with your message. Don’t worry, your details won’t be distributed to others, etc etc.


seo software tool

Long Live Internet95!

February 7th, 2007

I’m subscribed to a few mailing lists. These lists I’m a member of are the Internet equivalent of infomercials. You know the ones with the overly enthusiastic presenter with the over the top marketing strategy… “I’m going to suck up this cup of rice with my 1500 Watt cyclonic vacuum cleaner. Look at how easy it is!” I bet you roll your eyes when you see that sort of crap right? The mailing lists are a bit more intellectual but still in the same vein. The reason you see this sort of stuff is because it works. Sad, but true.

One of the lists was plugging a recent promotion - Day Job Killer. As you can already tell, the marketing is a bit over the top. But, there’s nothing over the top about this…

Day Job Killer @Alexa

Day Job Killer pulled in as many max page views in 2 weeks, as TechCrunch has built up over about 18 months. Apparently DJK sold 5,000 copies at $77 each in the first day. Not a bad result.

This is the result of old school marketing, Internet 1995 style. In contrast, Web2.0 is fun, and technically exciting. The problem with Web2.0 is that the emphasis is on the technology, and not on the business.

Here’s a negative article from a developer who has read DJK.

Here’s more reviews from people with questionable credibility linking to DJK with an affiliate ID. You could only affiliate with DJK if you had purchased the book.

Guilty, As Charged
Day Job Killer What’s All The Fuss About?
Day Job Killer is now LIVE! Act fast…

Is DJK the real deal? I don’t know.

Iterating Multi-Dimension Permutations

February 6th, 2007

Ever needed to iterate a multi-dimensional array? This is an easy problem if you know the size of each dimension, otherwise it’s a real bitch. For example, this is easy: “Iterate all permutations of A where A is a set {X, Y, Z}, and X: {1, 2, 3}, Y: {4, 5, 6}, Z: {7, 8, 9}”, but this is hard: “Iterate all permutations of A where A is a set {X, Y, Z}, and X: {1, 2, 3, …, n1}, Y: {4, 5, 6, …, n2}, Z: {7, 8, 9, …, n3}”. That’s only two dimensions too, imagine going to more - youch! These problems come up most often in scientific applications, but you also find derivatives in resource allocation, scheduling, and probably other places I can’t think of right now. Below is some Java code (complete with unit tests!) that I wrote for a recent project that will allow you to iterate all permutations of a multi-dimensional collection of unknown size.

Here’s the source. The unit tests are first so you can see what this thing is mean to do. Note that this source can theoretically work with more than two dimensions, but I only needed two so that’s all I’ve tested for.

/*
 * ChainTest.java
 * JUnit based test
 *
 * Created on February 6, 2007, 6:36 AM
 */

package phabian.util;

import junit.framework.*;
import java.util.Collection;
import java.util.Iterator;
import java.util.ArrayList;

/**
 *
 * @author alex
 */
public class ChainTest extends TestCase {
  ArrayList<Collection> iterable = new ArrayList<Collection>();

  public ChainTest(String testName) {
    super(testName);
  }

  protected void setUp() throws Exception {
    ArrayList<String> alpha = new ArrayList<String>();
    alpha.add("a");
    alpha.add("b");
    alpha.add("c");
    alpha.add("d");
    ArrayList<String> alpha2 = new ArrayList<String>();
    alpha2.add("x");
    alpha2.add("y");
    alpha2.add("z");
    ArrayList<Integer> num = new ArrayList<Integer>();
    num.add(1);
    num.add(2);
    num.add(3);
    ArrayList<Integer> num2 = new ArrayList<Integer>();
    num2.add(7);
    num2.add(8);
    num2.add(9);

    iterable.add(alpha);
    iterable.add(num);
    iterable.add(alpha2);
    iterable.add(num2);
  }

  protected void tearDown() throws Exception {
  }

  /**
   * Test of getValue method, of class phabian.util.Chain.
   */
  public void testGetValue() {
    Chain instance = new Chain(iterable, null);

    instance.next();
    instance.next();
    instance.next();
    instance.next();
    Collection value = instance.getValue();

    Collection<Object> expResult = new ArrayList<Object>();
    expResult.add("a");
    expResult.add(1);
    expResult.add("y");
    expResult.add(7);
    Collection result = instance.getValue();
    assertEquals(expResult, result);
  }

  /**
   * Test of hasNext method, of class phabian.util.Chain.
   */
  public void testHasNext() {
    Chain instance = new Chain(iterable, null);

    int combinations = 0;
    while (instance.hasNext()) {
      instance.next();
      combinations++;
    }

    assertEquals(108, combinations);
  }

  /**
   * Test of next method, of class phabian.util.Chain.
   */
  public void testNext() {
    Chain instance = new Chain(iterable, null);

    // Go next a few times.
    instance.next();
    instance.next();
    instance.next();
    Collection value = instance.next();

    // Check value returned is correct.
    Collection<Object> expResult = new ArrayList<Object>();
    expResult.add("a");
    expResult.add(1);
    expResult.add("y");
    expResult.add(7);
    Collection result = instance.getValue();
    assertEquals(expResult, result);

    // Go next one more time.
    instance.next();
    value = instance.getValue();

    expResult = new ArrayList<Object>();
    expResult.add("a");
    expResult.add(1);
    expResult.add("y");
    expResult.add(8);
    result = instance.getValue();
    assertEquals(expResult, result);
  }

}

Here’s the source. I had to remove the class comment because it was messing with the syntax highlighter, so here it is below instead of in the code…

/*
 * Chain.java
 *
 * Created on February 5, 2007, 8:06 PM
 * The basic idea is to create a Chain from a Collection.
 * Each Chain has a left and right, in the same way a doubly linked list has.
 * Next() on the parent Chain passes the Next() call down to the leaf Chain.
 * When a Chain overflows (hasNext() == false) then an overflow event is called
 * on the parent of the overflowing Chain and the parent Chain increments to
 * compensate for the overflow. This increment can also create an overflow.
 * The iteration of the Chain (and it's siblings) is complete when all Chains
 * return hasNext() == false.
 *
 */

package phabian.util;

import java.util.Collection;
import java.util.Iterator;
import java.util.ArrayList;

/**
 *
 * @author alex
 */
public class Chain implements Iterator {

  /** An iterator for Chain's that house other chains.
   * This prevents Chain from iterating over subordinates chains.
   */
  private class ContainerIterator implements Iterator {
    public boolean hasNext() {
      return false;
    }

    public Object next() {
      return new Object();
    }

    public void remove() {
      throw new UnsupportedOperationException();
    }
  }

  private Collection collection;
  private Iterator iterator;
  private Chain left;
  private Chain right;

  // This Chain contains other chains, so it's classed as a container.
  // The value of a container is the current value of each collection contained.
  private boolean container = false;

  // The current value of the iterator.
  private Object value;

  public Chain(Collection collection, Chain left) {
    this.collection = collection;
    // Only iterate over this collection if we are not housing further collections.
    if (!collection.isEmpty() &#038;&#038;
        !(collection.toArray()[0] instanceof Collection) ) {
      this.iterator = collection.iterator();
    } else {
      this.iterator = new ContainerIterator();
    }
    this.left = left;
    if (left != null) {
      left.link(this);
    }

    left = this;
    for (Object o : collection) {
      if (o instanceof Collection) {
        Chain previous = new Chain((Collection)o, left);
        left = previous;
      }
    }
  }

  public void link(Chain right) {
    this.right = right;
  }

  public Collection<Object> getValue() {
    ArrayList<Object> value = new ArrayList<Object>();
    if ( ! (this.iterator instanceof ContainerIterator)) {
      value.add(this.value);
    }
    if (right != null) {
      value.addAll(right.getValue());
    }
    return value;
  }

  public Iterator iterator() {
    return this;
  }

  /** Our subordinate chain overflowed, so we need to increment too.
   */
  public void overflowEvent(Chain right) {
    next(false);
  }

  public boolean hasNext() {
    boolean hasNext = iterator.hasNext();
    if (right != null) {
      hasNext = hasNext || right.hasNext();
    }
    return hasNext;
  }

  public Collection next() {
    return next(true);
  }

  /** Increment the subordinate chain, or ourselves if we were directed
   * to not pass it on.
   */
  private Collection next(boolean passItOn) {
    passItOn = passItOn &#038;&#038; (right != null);
    if (passItOn) {
      // Initialize our value to make it look like we did something.
      if (this.value == null) {
        this.value = iterator.next();
      }
      // Pass it on.
      right.next(true);
    } else {
      if ( ! iterator.hasNext()) {
        if (this.left != null) {
          this.left.overflowEvent(this);
        }
        iterator = collection.iterator();
      }
      this.value = iterator.next();
    }

    return getValue();
  }

  public void remove() {
    throw new UnsupportedOperationException();
  }
}

You can think of the code as a business. On his way to golf, the CEO commands the CTO to do stuff. Before the CTO leaves to join the CEO for a round of golf, the CTO instructs mid-level management to get stuff done. mid-level management have lots of coffee to drink so they instruct their project manager to get stuff done. The project manager is too busy day trading to do anything else, so he tells his team leader to get stuff done. The team leader is swamped with other work so he tells his overly enthusiastic team leader wanna-be to get stuff done.

After some time, the wanna-be team leader gets it done, and tells the team leader, who tells his project manager, who tells mid-level management, who in turns notifies the CTO via mobile phone, who tells the CEO over a beer at the 19th hole.

And that, is how life the code above works.