SEO Image Names in NOPCommerce

Image file names in NopCommerce have historically been not very attractive, to either humans or google-like creatures. The image file format for Nop has historically been:

site.url/images/thumbs/00000123_70.jpg

which would be the image with id 123, and dimensions of 70 along the largest size.

slightly off topic – the “single size” parameter of Nop has been a problem, since some images may be very wide or very tall… so once both sides are smashed down to 70, it may be only 10 pixels in the other dimension… making for some ugly pics. An early mod I added to nop is to allow specifying a max size rectangle, so the image can be sized to fit a rectangle instead of a square. This then looked like:

site.url/images/thumbs/00000123_70_300.jpg

Also even more off-topic – Nop currently doesnt handle non-progressive jpeg’s correctly, as it is searching for a mime type of pjpeg. If you upload a jpeg image that is not progressive, the mime type will be jpeg instead of pjpeg, and nop will wind up setting the file name extension to .jpeg instead of jpg. Not a big problem, but just add the jpeg handler to the switch statements in pictureservice.cs and it will keep all your images named with a consistent .jpg extension.

This then let me have pictures in my product listings which filled the width out to 70, but if they are tall, they can grow to a max of 300 pix before it starts getting resized. Used correctly, this makes much nicer looking product images listings.

Fast forward to version 2.3 which now includes SEO image file name support. The format for these file names now looks like:

site.url/images/thumbs/00000123_my_products_name_70.jpg

Then adding my dual dimensions mods back to it:

site.url/images/thumbs/00000123_my_products_name_70_300.jpg

It’s a definite improvement in file name friendliness, but we can do better right?

The ID portion is padded out with zeros in order to allow easy deletion of all thumbs when the admin desires, as it does a delete of {id}*.{ext} pattern. Since the ID number might be repeated somewhere else in the URL, the zeros reduce this possibility quite a bit. However, if we assume the thumbs folder will always contain {id}_{seo name}_{size}.{ext}, we can just change the delete pattern to be {id}_*.{ext} and it should work without the zero padding. So now my url looks like:

site.url/images/thumbs/123_my_products_name_70_300.jpg

One more thing I decided to do for my thumb images is to chane the folder they are put in. Many of the images used from this folder are quite large anyway, so the name “thumbs” (for thumbnails) doesnt really apply anyway. Make this change in the PictureService.cs file. I made  a global var with the path info so I could change all the paths to use this var and allow modifying it in the future more easily. I went with just /img for the thumbs folder, so now I’m down to:

site.url/img/123_my_products_name_70_300.jpg

Also, it is still considered to be better to use hyphens in urls than underscores (it’s controversial, but in general this is the case) so let’s also change this while we’re at it:

site.url/img/123-my-products-name-70-300.jpg

I left all the old already-generated images in the original thumbs folder, so links won’t break to them. I’m planning to create redirection rules for each file to point the old file name to the new one, so we can tell google and others to start using the new images. This will take a bit of effort so I’m leaving it for another day at the moment.

Ok, Let’s do even one better. Since we are using the seo name in the file name now, why do we need the ID portion at all? Well we do need it for the delete operation mentioned above, but we could add a delete operation which instead searches for the SEO file names and deletes them instead.  So as far as I can tell, we no longer need the ID in the file name at all. (Note I havent implemented this thumbs deletion code yet, so my site is running a bit in manual admin mode for now…). Now our images are:

site.url/img/my-products-name-70-300.jpg

This creates a problem though – currently (version 2.3) we can’t change the SEO file name for each image, they are just set to the product name automatically. If we manually change the file names in the database, this works. These can be changed in the “Picture” table in your database, just edit the SEOFileName column data. Again, running in manual mode for now, but I’m hoping version 2.4 will include the ability to change the seo file name per image. Also, this might not work if you store your original files in the file system – Im using “store in database” mode on mine.

The remaining enhancements we could do is try to trim or even remove the size info on the end of the file name. a few options we could use for this would be:

-use pre-defined sizes in the database, and append the id for these defined sizes to the URL- so if we define a size of 70×300, we could get an ID number of 3 for this- so our image would be:

site.url/img/my-products-name-3.jpg

-a variation of this is to allow a friendly name for the file size to be included with the defined size – so 70×300 could be our “Small” or “SM” size, so the url becomes:

site.url/img/my-products-name-SM.jpg

Optimally this would still support the old size-in-the-url for backward compatibility, or for those occasional images you need a special size for as a one-off.

I’ll likely go ahead and implement this full feature before redeploying because I don’t want to go through another upgrade later that requires redirecting file names yet again- best to do this as infrequently as possible.

 

Future Enhancements

I assume Nop will get image edting capabilites does the road, allowing cropping/zooming and other filters per-image and perhaps per-size etc, so these features will likely require further mods to the URL’s used by the images. Oh and watermarks would be nice too.

Another possible mod would be to put images in virtual folders under their product names. This would require the picture service to manage a tree of subdirectories in the image folder, but would allow urls to look something like

site.url/my-product-name/productname-front-view.jpg

In theory this could be semantically superior to the earlier versions as it associates the product image more closely with the actual product… but we would also need some enhancements to the product url’s themselves before this would make sense- we would need to move product detail pages to use shorter urls like site.url/product-name, instead of the current site.url/p/123/product-name… Next project perhaps.

Another nice feature would be support for cdn’s. In the case of a simple subdomain cdn, the store could support hosting the image files under a different subdomain such as:

cdn.site.url/my-product-name-image.jpg

Or continue with the semantic subfolder as above-

cdn.site.url/my-product-name/productname-front-view.jpg

If the cdn is offsite (ie, not hosted on the same server), the implementation becomes a bit trickier.

 

Open URL using LinkLabel

In Winforms, you have a LinkLabel control – which one might be interested in using to open a browser with a url (perhaps?).

One way to accomplish this is to add the LinkClicked event handler, and have it execute this:

System.Diagnostics.Process.Start(http://www.amazify.com/);  //Put your own URL in there

WPF uses a different control and method of handling links, I’ll add that content here once I go find it again.

 

 

Auto-Update .Net applications

Adding auto-updating features to a .net application always seems to be far more complex than it should be. Since this is something that many or even most apps will want as a feature, it seems there would be more or better solutions out there.

If you are using WPF, you can use ClickOnce – but this has a number of restrictions to it. Built-in to visual studio.

The Auto-Update Application Block is another option, but is apparently heavy weight and easily become burdensome for many projects.

WyUpdate – open source from WyDay.com – I need to look into this one furtheer. see http://wyday.com/wyupdate/

(this is a stub- more to come)

TSDB Time Series Database

Recently did some research on Data Historians, which are effectively just time series databases. Time series databases is the name of genre of databases which are optimized for storing large quantities of data as it is catured over time- think of sensors taking readings every second, or even many times per second. A data historian is typically used in facilities like process plants to store this large quantity of data in a reliable, yet efficient way. Due to the large quantity of values, the storage has to be optimized to prevent exploding database sizes. This is accomplished in a number of ways, often a combination of them. Since long series of readings will often have very similar or same values, the server can take advantage of these small deltas to store less data. Often plain old compression technology is used in conjunction with these other methods.

Since historically a data historian has been a very expensive specialized asset, I was curious if the open source world had tried to tackle this one. I found a couple TSDB’s out there, but the most mature one I found as at http://opentsdb.net – which appears to be used by the StumbleUpon website. Interesting stuff.

 

 

nopcommerce 2.0 fresh install sql script

With one of our NopCommerce ecommerce websites, we recently ran into an issue with upgrading – in short, if you want to upgrade from a pre-2.0 site to the latest (2.1 as of now) version, you would need to install 2.0 first, let it create a new database, run the 1.9 to 2.0 migration sql script, and *then* upgrade to 2.1. Since we still had a 1.7 site, and had developed a new version in 2.1, we wanted to skip the whole installation of 2.0 step. So, we ran a 2.0 version on a local machine, let it install a fresh db to a new database, and scripted this out to a new script. We can now run this script to create a fresh 2.0 db if needed.

If you have need of this script, you can download it here: nopcommerce 2.0 new database script.

(this is for sql 2008 r2, it might work on your non 2k8r2 db, but no guarantees).

schema.org with nopcommerce

We’re deploying the latest nopcommerce 2.1 on some of our ecommerce sites very soon. This version (well, version 2.0) was a major overhaul of the nopcommerce project to port it over to mvc3 and razor… so migrating our old sites over turned into a lot of work, but work (I hope) that will be worthwhile since the ASP.Net MVC framework is so… well, we’re big fans.

While messing around with porting the sites, I decided to dabble with adding some schema.org tags to the project. Right now it’s pretty proprietary to our own sites, but I’m planning to look into whether this can be created as an add-on for nopcommerce.

If you are unfamiliar with schema.org, it’s the latest greatest incarnation of microdata/rich snippets/whatever you call it… which just means, you add information mixed into your html pages which let’s third parties be able to extract meaning from the content of your page, beyound just a bunch of html. So, when we add this to a nopcommerce site, we can add markup inside the page to show what a “product” is… which means tagging the name, description, price, and so forth. The tags are a great mix of simplicity with usability, as it seems like all the most common things you can think of on the web are encompassed in the definition. And even if they aren’t, you can request an extension be added to the schema. Not too shabby. Have a look at http://www.schema.org for more info.

268435456

268435456 is a big number. I ran across it while researching some google maps stuff, and the author of an article said it was half the earth’s diameter, in pixels, when google maps is zoomed to level 21. OK…

For some reason, I wondered if that was kindof a common knowledge thing or not, so i googled that number. I found the referenced article, but then also found a bunch of references to some default memory size limitation set in PHP. Strange.

That is one really big number to have occurred in two distinct places like this. Which makes me wonder if it has any other significance. Actually, i bet it’s a power of 2.

Sure enough, it is 28 bits of data, or rather 2 ^ 28 = 268435456

Welp, not such a huge mystery now I guess.

NOPCommerce Themes and Theming

NopCommerce 2.0 is now fully ASP.Net MVC3 using razor etc. Pretty nice stuff. This makes porting a site from earlier version a bit of a challenge, if it has a lot of customization. Actually if you only made customizations via CSS modifications, then it is actualy very easy to port over (I’ll make another post covering this), but changes to any of the aspx files will require porting these over to the new razor .cshtml format.

When doing this porting though, a nice new feature in 2.0 makes this job easier-  the ability to “overload” a view inside your theme. This basically means that a custom pluggable theme can change the page structures. Previously, the themes really only had power to change things via stylesheets, so you could change colors and formatting, but doing deeper modifications to pages requred opening the source code in visual studio and hacking on the .aspx pages.

To take advantage of this feature, just add your overloaded (or even completely new) .cshtml files inside the /themes/{your theme}/Views folder. This folder should mimic your normal views folder, ie it should use a /Shared folder for shared views, /Home for the home etc.

Now you can hack on the structure of your site without having to change the original .cshtml file.. if you mess things up, just delete (or rename) your theme view and the original view will be picked up and used.

 

NopCommerce 2.00 is released- time to upgrade

The long-awaited 2.0 release of NopCommerce was released today. It’s going to be a lot of work, but we will be porting our primary nop project, Deadlywind.com, to the new framework as soon as we can. We’ve been holding off on a lot of improvements to the site/store knowing that this major update was coming out soon (and even held off on doing some new ecomm projects for this same reason).

The new version has been fully migrated to MVC 3, so we’ll get all the benefit of Razor, clean URL’s, and easier theming and modifications through the new plugin framework. Really looking forward to the new features, but not super excited about porting it all over. I’ll likely update this post, or add another one with all our findings/gotchas/howtos for this. 

Simplest MVC Controller routing

I’ve ported a number of websites from old static (or nearly so) pages over to more recent .net mvc technology, just for the benefit of being able to use templates and manage/automate a few things better than having to edit individual html files. Yes, Im a fan of Orchard CMS but some of these sites just arent worth the effort of trying to port to Orchard, or at least not for now. Creating a custom theme just for one site just wouldnt be worth the effort.

When doing these kinds of sites, you could use a single “Home” controller for all your pages, and add a controller method for each page. With 20+ pages, you would add a method and a single View for each page you port over… kinda burdensome for a simple site.

So, what I’ll often do is just simplify the Index() method on the controller so it can show the requested view, whatever it may be. You can implement this as follows (yes I’ll add code formatting to this eventually…)-

in HomeController, we add a parameter to the Index() method so we can pass in the name of the view.

public ActionResult Index(string view) {
   return View(view);
}

In Global.asax, we change the default routing to use:

routes.MapRoute(“Default”,
   “{view}/{id}”, // URL with parameters
   new { controller = “Home”, action = “Index”, view=”Index”, id = UrlParameter.Optional } // Parameter defaults
);

Now, the default controller “Home” calls Index by default, and passes in the first parameter as the view name. We simply load the view with that name and display it. Note that this route can mess you up fast if you try to do anything fancier, but it’s a good way to simplify a really simple site that is basically a collection of views… perfect for porting over our old pages from and old static site.

64bit Oracle Instant Client Performance

I’ve made a post on StackOverflow – http://stackoverflow.com/questions/6718890/oracle-datareader-in-net-way-too-slow-over-network/6747497#6747497  about a weird performance issue Ive encountered with the 64 bit version of the Oracle Instant Client 11g. I’ve tested on other machines with a 32 bit client (though not instant) and it is much faster, around 10 times the speed, when using a simple datareader to fetch table records. The details are in that post, but I’ll just say that the performance was bad enough with this client that I had to seek an alternative to use for my project… and it wasn’t very pretty.

I’d be really curious to hear an explanation for this- plain ol bug, or is the supersized 64 bits causing the client to do extra work and killing the performance? Or is it just the instance client is always like this? The one thing I havent tried yet is using the 32 bit version of the instant client on the same machine and see if it improves things. I have a feeling it will…

Google Black Bar

Google apparently decided to change the menu bar across the top of the page to black. I don’t really care, but I will admit it looks really out of place. Apparently a lot of others agree- and some really have strangely strong opinions about it, which can’t be a healthy sign… but anyway.

So who wants to build a firefox plugin to revert this menu back and make all these weirdos happy again?

Oh and why am I writing about something this dumb? Im just curious if I can rank for the phrase Google Black Bar. And that’s why I just said it again right there 😉

 

Google Microphone in Chrome spooks me out

Loaded Chrome browser earlier and was greeted with a little microphone icon in google’s search box. Click it, and sure enough, you can talk to google and it will recognize what you say and do a search for it.

Cool stuff, but what is spooky about this is- the browser never asked me if I wanted to allow the app to use my mic. So, technically, google could turn on my microphone and listen to me any time it wants? What are the security parameters around this thing?

Click Mic icon. Say “Google, are you listening to me?”

15 bean soup recipe

1 bag “15 bean soup” mix

cook according to directions, but use these ingredients instead:

-replace half the water (and optionally all the pork) with pork stock

-replace canned tomatoes with a few shots of Huy-Fong SriRacha sauce (or try tabasco)

-add a whole lime instead of a lemon

-throw in a whole chopped union (instead of just 1 cup)

-Add chili pepper and garlic as instructed, and the contents of the little mix pack

 

This stuff feeds 14 people (or two bachelors) and costs like a buck. And tastes GREAT.