Search indexes FINALLY updated

by alex 30. April 2013 18:30

About a month ago I mentioned that I was changing the titles in the sales site. It took about a month, but it is finally updated! This means I might rank better for the keywords I'm targeting.

Search results for "site:http://www.eisenhartsoftware.com"

Broadcasting your sitemap to search engines

by alex 30. April 2013 18:10

Day 89!

I just realized that I had the sitemap for the BuildKeeper.NET blog configured incorrectly with Google. D'oh! I was using the RSS feed instead of the dynamic sitemap! After fixing this problem, my submitted-pages count jumped up!

I don't think this mistake caused terrible problems because my blog shows up in Google results when searching for my post titles and keywords. But it means that my blog would have been a step or two behind in scanning, because new blog posts could only be detected if the blog root was reindedex first.

A few months ago I manually registered a static sitemap for the sales site and the dynamic sitemap (although incorrectly) with Google Webmaster Tools. This means Google has my sitemaps, but Bing and Yahoo don't. To broadcast your sitemaps to all search engines, add them to your robots.txt file. Here's a snippet with mine:

sitemap: http://www.eisenhartsoftware.com/sitemap.xml
sitemap: http://www.eisenhartsoftware.com/blog/sitemap.axd

 

Early results on exploratory signup website No Dice Required

by alex 8. April 2013 22:31

It's day 67 of the experiment. I mentioned last week that one of my old projects, No Dice Required, recently had an unexpected surge in traffic and signups. I spent a few days last week redesigning the website in ASP.NET MVC 4 and writing new copy and user tracking code.

The new website is a coming-soon page with a beta signup. The entire site consists of maybe a dozen pages: home page (with sign up control), sign up page, sign up complete page, HTTP error pages, and a this-site-has-been-redesigned page for the pages of the old site. Additionally, there are many dynamically generated landing pages.

Home page

The old home page was poor for a few reasons. There were less than 20 words available before login and there wasn't any meta data included in the headers: together, these make it hard for search engines to know anything about the site.

The old page also didn't sell the site in any way. Why does it exist? Why should the visitor care? I'm still not particularly good at writing copy that converts, but I feel like I'm improving.

The new homepage has much more text, images, and formatting variations: these should make a visitor more interested in reading the content of the webpage.

The coins at the bottom spin, and if the visitor clicks on them then a coin-pickup sound is played and the coin counter in the top menu increases. The number of collected coins is persisted in a cookie.

I pushed this to the internet a little less than a week ago. So far there are 2 signups for the beta and it has been seen by 89 unique visitors. Most visitors haven't realized that the coins were clickable. This might be because they lack imagination and I imply that they are clickable. Implying on the internet is bad for conversion! I should have come out and said that they were clickable or collectible or something a bit less subtle.

There's quite a bit of custom user tracking going on; I will write about the details of what I'm doing. The landing pages are done, except that I still need to work out the creation of dynamic sitemaps. The trouble here is that I can't easily route a single file to a controller action without also routing all files through the ASP.NET pipeline as well; doing that would be a performance nightmare.

Creating dynamic data-driven landing pages in ASP.NET MVC

by alex 8. April 2013 19:26

Creating dynamic landing pages

I mentioned in the last post that No Dice Required was updated. The real experiment with this site is that I'm playing with scaling out SEO efforts by drastically increasing the number of landing pages.

A landing page is the first page of your website that a visitor lands on. A certain amount of visitors to nodicerequired.com will be looking for "language learning tools", but another group will be looking for "Japanese food words." Ideally, the visitor should land on the home page for the first phrase but the 2nd phrase, "Japanese food words", has no place on the homepage. That's where landing pages come in.

Landing pages are kind of like search fodder to give you more indexes in Google. There are two goals: one is to grab search phrases which are related to your problem domain but not necessarily related to your product, and the second is to then route visitors into your website from those phrases. Above all else, landing pages should resolve some need the visitor has.

It would be easy to create a dozen landing pages by hand, but this has scalability problems; hand-crafting a dozen similar pages isn't what you or I should be spending our on. As a programmer, this problem has an easy programming solution!

First off, you should remember that there isn't anything particularly unique about a landing page, other than that it generally has many crosslinks to other content on your site (and maybe to other landing pages); however the rest of your site generally won't have links to landing pages.

The rest of this post is techy and related to creating landing pages in ASP.NET MVC 4. If that isn't your cup of tea, then you should probably move on to the next article now =)

Defining your data structures

You need to consider the data that you'll need to populate a page. For No Dice, I planned to have each landing page be a list of translated vocabulary words, and it will include links to other lists, and the lists are grouped by categories.

I have POCO objects to support these goals. The POCO objects may look a little wonky, but I'm using them directly with Entity Framework to build my database via Code First, so I can deal with the weird virtual properties.

public class Word
{
    public int ID { get; set; }

    public DateTime DateCreated { get; set; }

    public int UserID { get; set; }

    [StringLength(256)]
    public String Text { get; set; }

    [StringLength(10)]
    public String Language { get; set; }

    public int? WordListID { get; set; }
    public WordList WordList { get; set; }
}

public class WordList
{
    public int ID { get; set; }

    public DateTime DateCreated { get; set; }

    public int UserID { get; set; }

    public String Name { get; set; }

    public virtual IList<WordListCategory> WordListCategory { get; set; }

    public virtual IList<Word> Words { get; set; }
}

public class WordListCategory
{
    public int ID { get; set; }

    public DateTime DateCreated { get; set; }

    public int UserID { get; set; }

    public String Name { get; set; }

    public virtual IList<WordList> WordLists { get; set; }
}

That's pretty simple. There's a one to many relationship between WordList and Word, and a many to many between WordList and WordListCategory. Or, in other words, every Word is in one WordList; every WordList has many Words and many WordListCategorys.

The data model I'm using isn't exactly like this, but it's similar enough for this discussion.

I don't want every WordList to be a landing page, so I also have a Page object:

public class Page
{
    public int ID { get; set; }
    public DateTime DateCreated { get; set; }

    [StringLength(256)]
    public String Name { get; set; }

    public String ViewName { get; set; }
    public String ViewMasterName { get; set; }

    [StringLength(256)]
    public virtual String Stub { get; set; }

    public int WordListID { get; set; }
    public WordList WordList { get; set; }

}

For every landing page that I want, I create a Page object and configure it to use a WordList, give it a stub and a name, and it's good to go.

You might also notice that I added a ViewName and ViewMasterName property. This allows me to configure which .cshtml file will be used to render the landing page, in addition to a Master Page or layout, so that every page doesn't necessarily have to have the same look and feel as the others or the rest of the site.

Persisting the objects

You'll need some place to persist all these objects, probably XML files or a database. Personally, it's quickest for me to drop them into an Entity Framework DbContext and use SQL Server.

public class DiceContext : DbContext
{
    public DbSet<Word> Words { get; set; }
    public DbSet<WordList> WordLists { get; set; }
    public DbSet<WordListCategory> WordListCategories { get; set; }

    public DbSet<Page> Pages { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Word>()
            .HasOptional(p => p.WordList)
            .WithMany(d => d.Words)
            .HasForeignKey(p => p.WordListID)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Page>()
            .HasRequired(p => p.WordList)
            .WithMany()
            .HasForeignKey(p => p.WordListID)
            .WillCascadeOnDelete(false);
    }
}

Landing page Controller

Create a new LandingPageController class, which will handle page requests.

Here's mine:

public class LandingPagesController : BaseController
{
    public ActionResult Index(string language1, string language2, string stub)
    {
        Page p = null;
        // [...]
        return View(page.ViewName, page.ViewMasterName); 
    }
}

I need to know the name, ID, or stub of the page to be rendered. I decided to use a stub instead of the page ID because stubs are more friendly to search engines and users. I also need to know which language the visitor knows and which language they want to study, language1 and language2. From these three data points, I can find a Page, which indicates a WordList. I can find the appropriate words using language1 and language2.

Routing URLs to your Controller

I've talked about routing in a few other posts. You want to make sure that your URLs look good. By that, I mean they should be shallow and keyword-rich. Having your keywords in the URL makes your page look more useful to search engines.

Create your new routes in the Register_Routes method (this might be in global.aspx.cs or RouteConfig.cs).

My route will interpret all 3-segmented URLs as a landing page: the first value is language1 (the visitor's native language), the 2nd is language2 (the visitor's study language), and the third value is the stub of the page to be displayed.

I will probably have to make some revisions to this routing structure if I get enough interest to make me revive this project.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Landing Pages",
        url: "{language1}/{language2}/{stub}",
        defaults: new { controller = "LandingPages", action = "Index" }
    );

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

After this, I can load URLs like http://www.example.com/english/japanese/food and it will be routed to the LandingPageController, with the parameters properly filled in.

Finally, the easy part: create a view and go crazy in the ways you normally would to create and populate a view. Mine looked like this in the end:

Dynamic Sitemap.xml files for bots to detect the pages

You might be asking yourself, "If my homepage doesn't link to any pages that eventually link to the landing pages, how will they ever show up in search results?" Good question.

Right now, they never will. We need to create a dynamic sitemap file and submit it to our search engines of choice so that they know about the landing pages and can index them properly.

This post has gone on long enough, so I'll cover this topic later tonight or tomorrow.

If you run into any issues or have any questions, feel free to share them in the comments below!

Build Keeper.NET logo drafts

by alex 28. March 2013 01:50

Tree logos

My first idea is that since Build Keeper is used to cross reference different versions of software releases, it could be represented by a tree. And what better way to illustrate a programmer's tree than with Visio? =)

That idea gave rise to these two images. Some feedback on the first image was that it didn't invoke the image of a tree in the viewer's mind. This doesn't necessarily make it a bad logo, but it misses the mark so I tried adding a few smaller green leaves. I'm not totally in love with either of these images, but I still like the original idea.

Cloud logo

For a brief moment I considered a cloud logo, with the bubbles on the standard cloud logo being nodes in a small dependency graph. I don't know what I was thinking and this was quickly abandoned.

Castle logos

The second idea, probably a bit more obvious, is centered around the "keep" portion of Build Keeper: castles, towers, and such.

2D Iconic castles

I tried some quick drafts of simplified 2D castles but I wasn't particularly fond of anything that was happening here. The first is very Cisco.

3D Rendered castles

A castle tower or turret is kind of interesting and I thought I might be able to get an interesting design with simplified colors. I fired up my 3D program of choice and built a (very) simple turret. Two directional lights cast high-contrasting colors at either side.

Using a standard up and aim perspective camera, looking up at a shallow angle, I rendered it with high-contrast colors and then again with two colors from the product site. I kinda liked it, but it felt a little boring, so I tried cutting a hole in the middle of the tower, to make room for an icon or something. Barf. But it was fun because who does boolean operations on polygonal solids these days? =)

All cameras are not created equal and the next experiment used an orthogonal camera. Ignore the black parallelograms on the bottom - that's the underside of the turret and it'll be stripped off later.

I liked that well enough to scratch a bit.

Using Gimp, I created a bottom edge (this same look could probably have been achieved with a perspective camera with tweaked out settings to make the vanishing points shoot far off... probably something to do with ISO settings [j-playing at the end there]).

Anyway.

The brand name also makes an appearance here. The contrast between the blue-side and "Build" is nice, but it requires the tower to be tall and the text is quite wide, so the silhouette looks strange - bulk to the left and wide and thin to the right. It's almost key-shaped. But I feel like I could be on to something with this shape. 

I tried shortening the turret a bit, but I think it went a little too far in the 2nd image - it looks squashed and the 3D-ness of it starts to break down.

 

Vectorizing the raster - inking

Everything to this point has been low-quality, rasterized bitmaps and they were a bit fuzzy in places. I imported the latest version (the shortened tower with the brand) into Inkscape and traced all the edges. This process involves drawing math-powered lines on top of the bitmap and then filling it in.

These shots in are:

  1. The traced source image.
  2. A taller turret with deeper "teeth". And I also somehow swapped the colors. That wasn't intentional =)
  3. Two tests of how it would look on the product site and in the product itself; the product will use a transparent version to let the menu header shine through.

 

Finally, here's what it would look like in the product itself and on the sales site:

I think I like this logo. It can easily be 1-bit, which makes it cheap to be printed. The colors can be varied to fit the medium and the message.

If two colors are used (like the orange and blue of the product site) I may remove the black outlines.

What do you think?

Edit: The smallest icons - in the last two samples - gets a bit blurred at the top, while the middle is a wasteland of color. I could see trashing the middle "tooth" and have only 2 per edge around the top. That might turn out to be funny looking.

Tags:

Advertising

About the author

Something about the author

Month List