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 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; }

    public String Text { get; set; }

    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; }

    public String Name { get; set; }

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

    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)
            .HasOptional(p => p.WordList)
            .WithMany(d => d.Words)
            .HasForeignKey(p => p.WordListID)

            .HasRequired(p => p.WordList)
            .HasForeignKey(p => p.WordListID)

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)

        name: "Landing Pages",
        url: "{language1}/{language2}/{stub}",
        defaults: new { controller = "LandingPages", action = "Index" }

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

After this, I can load URLs like 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!

10 Productivity tips for startups to stay focused and on track

by alex 28. March 2013 18:50

As of today, I've been working for myself for 56 days. In those 56 days, I've had amazing results and learned a whole lot. But I've also had a lot of guilt and missed expectations, largely due to focus and motivation. Here are some of my personal tips to keep you on track when you have to self-manage.

1. Wake up and get started

When you work from home it's far too easy to hit snooze "just a few times." Identify when your productive hours are, and make sure you are awake and ready to go when that time comes. When you wake up, get started. Don't laze about; don't play games online, watch "just one" episode of The Daily Show on Hulu before getting started.

Instead, get dressed. Put on your shoes and step outside. You don't even have to put on clean clothes or brush your teeth. Don't feel pressured to go for a jog around the block. Take 10 deep breaths and hug the sun. Get out of bed and get moving. If you are still tired after all of that then you can take a nap.

You have to push yourself.

2. Stay off Facebook

Facebook is fun. Facebook is boring. Facebook is distracting, upsetting, angering, and endearing. Unless your business requires you to be on Facebook for the purposes of advertising or researching, avoid it. Facebook will eat your time in 15 minute chunks and you'll ask yourself where the day went. Facebook has it now, and she'll never let it go.

This goes for Twitter and your other social networking sites too.

3. Don't F5 your email

Did you just push a new software release? Post something exciting on Twitter to let your community know? Wonder if your customer survey results are in?

Stay out of your email. Waiting for information and feedback is a bit like looking forward to Santa's arrival. You know what, Santa will get there whether you are playing video games with your friends (I mean, reading a book and tutorial neighborhood kids) or bugging your mom about it.

I don't know where that metaphor was trying to go. Anyway, your information, if it will arrive, will arrive. Checking your email between every task switch doesn't buy you much and it will steal your time or distract you from what you should be doing.

Unless you're waiting for an email from the President saying "Do not press the button!", do not stalk your inbox.

4. Focus on one task at a time

Multitasking is dead.

Staying focused on completing one task is much easier and faster than trying to do two at once. I think this is double true for anything creative. This isn't to say that you shouldn't listen to music or that you can't talk to your coworkers or roommate, but you shouldn't be designing a logo while trying to do your taxes.

If a customer call comes in, stop what you are doing (if it's appropriate), deal with the customer's request and then get back to work.

If you're working on a new logo, stop fretting over the code that you don't know how to write. Don't think about website color schemes while writing your copy. Don't tweak and play with the CSS in your media player when you're cutting audio.

Staying focused on one task will make the work go faster and with better results in the end.

5. Don't stress out

It isn't good for anyone, especially you and your friends and family. Take a breath. If you're getting frustrated or depressed, step away from the issue. Switch to a new task. Or lock your computer and go outside. This doubles as exercise, which is all around good for you because you can eat more bacon later.

That was a joke. Don't stress out.

6. Don't gaze aimlessly into your monitor 

If you find that you have stopped working and are now looking at your desktop wallpaper or reading random garbage on the internet: stop. Get up, walk away, do 10 pushups, wash the dishes, fold laundry, walk the dog, clean your room, prep your dinner, dance around, call your mom.

You have things you need to do and reading another Reddit article is not it. You do not need to change you wallpaper again. Stop trying to find the perfect profile picture.

7. Avoid games during work hours

Games are good, games are great. You might be creating games, and that makes you cool. But don't play unrelated games during your work hours. It is all together too easy to play for longer than you planned.

I like games too, but schedule game time after your work is done for the day. It doesn't necessarily have to be after your tasks are completed, but make game time after work time is over. Don't play games and call it work time. Don't play games and have guilt because you should be working. If you should be working, then do it.

8. Don't over-eat

Over eating leads to over sleeping. If you get tired after eating a meal then you probably ate too much. Try reducing the size of your meals and eating smaller meals more often throughout the day. It will keep you alert, avoid the mental fuzziness of Thanksgiving and it is also healthier for you. Don't make me find a citation for that, mister, because I know they are out there and I will if anyone questions it.

Avoiding over-eating will keep your work time at its max efficiency.

9. Don't over-caffeinate

Ah, caffeine. Let's take a moment. . . .

Coffee can make the mind sharp and it can snap you into the mood to get stuff done and accomplish the world! And if you have enough coffee you might not care that "accomplish the world" doesn't really make any sense. But if you have too much caffeine you'll become jittery, anxious and easily distracted.

Find your magic sweet-spot number of coffee cups or tea mugs and stay in that neighborhood. Too much coffee hurts your productivity and your health.

10. Make a task list

Every morning, make a list of what you need to do and what you can reasonably accomplish today. It will help you focus your effort and attack your tasks in the correct priority.

This will lead to a feeling of accomplishment - you get to check things off the list and larger projects can be completed more easily with a focused, targetted effort.

When you complete a task, you don't have to mentally regroup and shift back to a high-level to survey the field - just choose the next task on the list.

No muss no fuss.



About the author

Something about the author

Month List