Conchango Blogs Minimize
blogs.conchango.com

blogs.conchango.com

  1. 2008: The Death of the High Street?

    Well it was very close… and there are a few towns and small cities that will never be the same as the vicious cycle continues on the high street and shopping malls up and down the country.

    As lots and units become vacant, especially larger ones such left by Woolworths, MFI, Adams, Zavvi etc… and no one to fill them -  the landlords will try and up their rents, rates and other such utilities to ensure that they, as businesses keep turning over. In turn some of the retailers that may have just scrapped through Xmas – and lest face it with the discounting that was made not many would have made any profit by cutting costs so much to drive footfall into their stores that when the figures were calculated, and footfall figures showed that a record number of shoppers passed through their door and cash in the tills – the profit margins were weak and almost non-existent!

    Tough times indeed and if the added increase in 2009 from the landlords does go ahead as expected – we’ll see even more closures on the high street – and in some cases the death of the high street in some towns!

    ForRent Woolworths could never change?

    So what was the last quarter all about and who else could be hanging in the balance?

    The biggest had to be Woolworths, MFI & Adams – then with the demise of Woolworths and EUK brought Zavvi to its knees. Whittards followed suit and as we readied the chime of Big Ben to usher in 2009 and for many to forget what happened in 2008, rumblings came from Land of Leather, Iceland, WH Smith and Jessops – as well as Land Rover/Jaguar and the biggest shock was the car company that had never made a loss, Toyota, suddenly found that after 70 years of gains, a $1.66 Billion loss would be entered on their books.

    So what will happen in 2009 and what lessons did we learn from the fallout of 2008??

    Yes there was an economic turn down and credit crunch that pushed the house prices down (and will continue to do so throughout 2009) jobs were cut throughout, and expect more with companies continuing to struggle against the growing uncertainty. Big companies such as Tesco, M&S, Ikea etc.. will continue to push ahead, perhaps not as strong as they were in the past 3 years – but push ahead they will. A lot more ecommerce and value tracking will be done – as the high street empties more people will start to either head for large out of town complexes or bigger city centres but ultimately online and ecommerce will be even stronger in 2009 – and looking at the companies that fell away at the end of last year – you will se that either their online strategy or online presence was weak, poor and ill-equipped to compete against the stronger and more focused pure play e-tailers (Amazon, Play….)

    So 2009 how can a company like EMC help out retailers that find themselves wondering how and where to move and ultimately survive the belts and braces of “Retail 2009”

    • Its going to be about a strong retail focus and business case – how is your business equipped for the
    • Suppliers, distribution, local vs national vs worldwide?
    • ecommerce – can and does your platform fulfill all your needs and wants – if not now is a good time to review what you have and look at either a new build or enhancements (take a look at my blog from last year for an in-depth review of what e-tailers should do with their ecommerce direction)
    • 360° Retail – stack up your business models and review the channels that you use, how you use them and get the most of out of them
    • Customer..Customer..Customer – understand your customer, how they want to shop your store and give them the service that they expect and want

    2009 is going to be a very tough year for retailers and will be a fight for survival for a lot – but it doesn't need to be the end – some reviews, honest appraisal of your retail vision and 5 year plan – and especially reviewing your high street portfolio (why run 100 stores that lose the company money when you could be more profitable by running 30 stores and a phenomenal ecommerce site?)

    As long as CEOs and MDs realise that success is measured on the number and size of stores footprint – it is and always should be about the profitability and sustainable growth of the business. Let 2009 be the year that your company steps up, to scale down in order to survive – there is no room this year for egos or “size matters” management.

    If you want to know or understand what you need to do in order to keep on track email us: talktous@conchango.com

    Published Fri, 02 Jan 2009 16:47:43 GMT by Derek.Dunlop
  2. Why do we need more ICANN-assigned top-level-domains?

    I read today on BBC News website that The Internet Corporation for Assigned Names and Numbers (ICANN) is considering introducing many many more top-level-domains (TLDs) for the internet addressing system to go alongside the existing ones such as .com, .org, .net etc...

    I don't understand the rationale for that. We already have the problem where an organisation establishing a new domain has to go and purchase the .net, .org (and various other TLDs) in order to ensure that those addresses are not hi-jacked by phishers or cybersquatters, why do we need to make the problem worse?

    Better would be to remove the constraints put in place by ICANN and do away with a finite list of TLDs completely thus allowing organisations to use their organisation name as their TLD. I've never really understood the advantage of prepending/appending "www." and ".com" onto nearly every single website that we visit; I'd much prefer it if the web followed the naming conventions employed by the newsgroup protocol NNTP which "walks" the hierarchy of all NNTP content the further along the address you go (e.g. nntp://microsoft.public.sqlserver.ssis). That's not the case with HTTP addresses today which has a number of problems such as:

    • URIs are only hierarchical after the first single "/"
    • contain needless detritus like "www"
    • use different seperators depending on where you are in the URI (i.e. "." or "/").

    As a suggestion, wouldn't the following URIs make more sense, be more concise and be inherently more consistent than those used today (which are shown in brackets):

    I certainly think they would. I admit that I've got my rose-tinted-specs on here because I don't know enough about the Domain Name System (DNS) nor about URI addressibility to know if this is or ever has been technically feasible but I would hope that it is. I certainly don't believe that the current system of addressibility on the web is optimal. Interestingly in the article linked to above it is also stated:

    In June 2008 Icann announced proposal to allow an unlimited number of new gTLDs, citing greater competition and lower costs as the benefits of a more open system

    Good, that's exactly what I'm talking about here although I see the benefits as being greater simplicity and consistency, not lower costs and greater competition (those justifications from ICANN are not explained). Extending the finite list of current TLDs though feels like a step in completely the wrong direction; that list should be getting shortened, not lengthened. In other words, ICANN have (bafflingly) made two proposals in the last six months that are contradictory to each other; one in June saying they're going to get rid of the list of TLDs and now another saying thay're actually going to extend that list.

    I'm wading into what is, for me, unknown territory but most of this stuff just seems like basic common sense. What say you?

    -Jamie

    P.S. I had similar complaints almost 4 years ago to the day when I wrote New TLDs on the horizon.

    Published Tue, 23 Dec 2008 13:48:00 GMT by jamie.thomson
  3. Adding OpenId to Oxite, Part 2

    (Part 1 is here)

    The main part of the Openid support is in the controllers and in the view. Fortunately the heavy lifting has been done already, with a library called DotNetOpenId and sample code that started life in Rob Connery's storefront sample, and was worked on by my colleagues Howard Van Rooijen and Pete Worthington before I got hold of it.

    First, install the DotNetOpenId library and reference it from the Oxite.MVC project

    Add an action called OpenIdSignIn to AccountController:

            public ActionResult OpenIdSignIn()

            {

                var openid = new OpenIdRelyingParty();

     

                if (openid.Response == null)

                {

                    string claimedUrl = Request["openid.claimed_id"];

     

                    // Stage 2: user submitting Identifier

                    Identifier id;

                    if (Identifier.TryParse(claimedUrl, out id))

                    {

                        IAuthenticationRequest request = openid.CreateRequest(claimedUrl);

     

                        // email and display name would be nice, but we can do without it

                        ClaimsRequest claimsRequest = new ClaimsRequest

                            {

                                Email = DemandLevel.Request,

                                Nickname = DemandLevel.Request

                            };

                        request.AddExtension(claimsRequest);

     

                        request.RedirectToProvider();

                    }

                    else

                    {

                        ModelState.AddModelError("_FORM", "Invalid identifier");

                        return View("SignIn");

                    }

                }

                else

                {

                    // Stage 3: OpenID Provider sending assertion response

                    switch (openid.Response.Status)

                    {

                        case AuthenticationStatus.Authenticated:

                            {

                                ClaimsResponse claimsResponse = openid.Response.GetExtension<ClaimsResponse>();

     

                                string nickname;

                                string email;

                                // did we get a claims response?

                                if (claimsResponse == null)

                                {

                                    nickname = openid.Response.ClaimedIdentifier.ToString();

                                    email = string.Empty;

                                }

                                else

                                {

                                    nickname = claimsResponse.Nickname;

                                    email = claimsResponse.Email;

                                }

     

                                LogOpenIdLogin(openid.Response.ClaimedIdentifier, nickname, email);

                                return RedirectToRoute("Home");

                            }

                        case AuthenticationStatus.Canceled:

                            ModelState.AddModelError("_FORM", "Canceled at provider");

                            return View("SignIn");

     

                        case AuthenticationStatus.Failed:

                            ModelState.AddModelError("_FORM", openid.Response.Exception.Message);

                            return View("SignIn");

                    }

                }

                return new EmptyResult();

            }

     

            private void LogOpenIdLogin(Identifier claimedIdentifier, string nickname, string email)

            {

                // if the user record does not exist, create it

                string userName = claimedIdentifier.ToString();

                IUser user = MembershipRepository.GetUser(userName);

     

                if (user == null)

                {

                    Guid defaultLanguageID = LanguageRepository.GetLanguage(Config.Site.LanguageDefault).ID;

     

                    MembershipRepository.AddOpenIdUser(userName, nickname, email, defaultLanguageID);

                }

     

                FormsAuth.SetAuthCookie(userName, false);

            }

     

    And in the SignIn.aspx view add a form for the OpenId to be entered:

                 <div id="openid">

                    <h2>Use Your Open ID</h2>

                    <div id="spacer"></div>

                    <form method="post" action="<% =Url.Action("OpenIdSignIn") %>" class="login">

                  

                    <!-- BEGIN ID SELECTOR -->

                    <input type="text" class="openidinput" size="40" id="openid.claimed_id" name="openid.claimed_id" />

                    <script type="text/javascript" >

                        idselector_input_id = "openid.claimed_id";

                    </script>

                    <script type="text/javascript" id="__openidselector" src="https://www.idselector.com/selector/9ef50c2962fc7066564dc829214efbe0ef945335" charset="utf-8"></script>

                    <!-- END ID SELECTOR -->

                    <input type="submit" value="<%= Localize("Login") %>" class="submit button" />

                    <br />

                    </form>

                    <div class="hint">

                        Open ID is an identity system that allows you to sign in to websites with a single account.

                        Your username and password are secure with Open ID - and you don't have to remember yet another password.

                    </div>

                </div>

     

    And that's all.

    We are using a nice bit of Javascript Ui from IdSelector.com which, as you can see, has a serial number in it. Unfortunately they've stopped issuing these. I hope a good replacement comes along.

    There’s lots more that can be done with OpenId here. For instance, the OpenId login form would be useful on the comments page - OpenId users are more likely to be just casual commenters, whereas the people writing the blog could take the time to make a local login. The users created via OpenId do not have any permissions, so they can add comments but not post; which is a sensible default.

    I have more than one OpenId, so it would be nice to group them together into my account. Oxite is not yet an OpenId provider, which would be interesting.

    A mature system would be able to block open ids based on patterns in the url, allowing or disallowing providers based on security considerations. But Oxite first should gain ability to list users, and change their permissions – e.g. admin, editor, contributor or locked out, and track the user's time and IP of the last login, etc

    I’m sure that I made mistakes in this implementation – there’s lots that I don’t know about MVC and about OpenId.

    Published Tue, 23 Dec 2008 12:48:00 GMT by Anthony.Steele
  4. Surface Card Sorting


    Before the festive holiday kicked in I intended to design a Microsoft Surface Card Sorting application but time ran out without me getting much further than a brief conversation over a cuppa with some user experience colleagues and a few very rough and barely legible sketches of the application interface. To make sure I don’t forget any initial thinking here’s some wee thoughts on the surface card sorting software.   Please add your comments or thoughts to these rambles to help shape the software. 

     

    Card sorting is an effective exercise for grouping information on a web site. Topics are written on index cards and the participants then organise the index cards in to logical groupings. It offers a valuable insight of the user’s mental models, revealing how they organize information and think the site should be structured. There are two types of card sort - open and closed sort.  In an open card sort a users arranges the content in to logical groupings and then gives the stack a category label.  In a closed cart sort the user sorts the content in to pre-defined categories.  It is common to follow an open card sort with a closed cart sort.  Once the categories have been defined a closed card sort allows us to see how users sort content in to these groups.  If you want to know more about Card Sorting then for a detailed description read Card sorting: a definitive guide

     

    Card sorting sessions work well enough for me without the need for a computer-based card sorting program.  When the target audience is geographically wide spread then card sorting software can be used to conduct remote card sorts.  So why am I suggesting more software when there are already a number of card sorting programs and there hasn’t been great adoption of these existing ones?

     

    Card sorting exercises are extremely effective but are costly because they are time consuming to set up, administer and analyse the data. Card sorting software reduces costs but so far the actual user experience is considerably less than that of a hands-on physical card sort.  This is where a Surface application comes in.  It offers the cost saving without compromising the end user experience.

     

    Before running a card sorting exercise you recruit participants and create a content inventory.  These activities happen irrespective of whether it’s a real or virtual card sort. Next, you prepare the cards for the session.  There would be minimal cost savings in the preparation although the software does make writing the cards easier. With card sorting software the virtual index cards are generated from the content inventory doc. This also ensures that all the cards are neat and legible.   Alternatively this could be done using perforated index cards and mail merge, but not having to print out the cards is a time saver, not to mention more environmentally sound.

     

    The real cost saving Card Sorting software has over hands-on real card sorting exercises is in the data analysis.  A computer program records the data so it can be analyzed to provide meaningful results.  It is this data analysis where card sorting programs come in to their own and save considerable time and money.  A physical card sorting exercise can be carried out and then the data entered in to statistical software for analysis, but this data inputting is time consuming.

     

    My concern with existing software is that it's not easy to use and this distracts the users focus away from the core task of organising the content.  A Microsoft Surface Card Sorting application offers an engaging and immersive way for participants to interact and manipulate digital content through touch and natural gestures.  The actual physical exercise of sorting index cards in to logical groupings work well for me and Microsoft Surface offers a similar digital experience to physical card sorting.

     

     

    For an overview of how the Surface application might work, consider the following scenario...

     

    Louise, a User Experience Consultant, places her admin card on the surface tabletop to unlock the card sorting program.  The admin card holds basic information such as her name and email address. Several options to run the program in admin or user mode are displayed around the admin card. Louise taps to select the user mode.

     

    The first participant, Simon, arrives and Louise passes him his identification badge.  This identifies his name, email address and the project he’ll be doing the card sorting exercise for.  Louise has set up multiple projects for card sorting exercises but has assigned one project to Simon.  Louise places her card back on the table and selects the Open Card Sort option. A set of virtual index cards are scattered on the desktop.  Each card includes a topic.  As the facilitator, Louise gives Simon a brief introduction to card sorting and demonstrates how to group the content in to stacks by sifting through the index cards and moving them in to high level groups.  Louise places her admin card back on the table and taps the reset option to re-scatter the index cards so Simon can start the exercise. Louise also enables record audio, then lifts her card up and leaves Simon to organize the cards.  The participant is encouraged to think aloud.  The sound recorder captures their thinking and gives us an insight in their rationale behind the groupings. 

     

    Simon sits down at the high-resolution tabletop display and begins to group the content.  The interactions are natural and intuitive.  Simon drags the card around the table tops.  He can rotate them, flip them and arrange them in to stacks.  He is unsure about one of the topic labels so flips the card over by tapping the reverse arrow in the cards top right corner.  Simon writes a note using a tablet-style pen and then flips the card back over. An icon appears on the virtual card to confirm that a note is attached to this card.


    On the table is a virtual stack of blank category cards. Simon drags one of these over to a stack he has created and gives the card a category label. Once the stack has a label Simon can zoom in so that this stack takes over the tabletop display and removes any surface clutter.  Simon moves some of the card around in this stack and then pans back out to a view of all the stacks.  Simon gets a little confused as to whether it matters how many stacks he creates.  Simon taps the Help card and this tells him all he needs to know.  He closes this card and continues with the exercise.  Simon creates the stacks and then clicks done which sends a message over to Louise who is working in the room outside the usability lab.  Louise gets the message and walks over to the table to wrap things up. 

     

    The next participant is ready to go straight away as a new session starts without any need to tidy up the index cards. After the day’s sessions are complete Louise goes to the admin interface to analyse the data.  She decides not to include some of the sessions in the data analysis.  Louise chooses not to include two test sessions, and also excludes Frank who on further analysis was not a good match for their personas. Louise first eyeballs the raw data, then views the matrix of how often content was paired together. Finally, Louise views the dendogram.  This is when the magic happens and the clustering algorithms set to work.  This is the bit that is going to involve all the head scratching – developing the program to create the dendogram.  We’re currently looking at different visual ways to present the data in a meaningful way, so any ideas please add your comments.

     


    That’s where my rambles end for the time being, although I’ll follow up this post with some sketches and more detailed information on the interface and interactions as we starting working this up from rambles in to hopefully a usable cost-saving card sort application.

     

    Published Mon, 22 Dec 2008 17:20:00 GMT by Richard.Wand
  5. Adding OpenId to Oxite, part 1

    I am following up on my last post on Oxite by showing how to add OpenId login support to it. I won't finish this today. This first one will cover the repository changes needed.

    First, download the Oxite source and set up the database. From a database perspective, the table where user logins are stored is called oxite_user. In code this is referenced via the IUser interface.

    In general, I would like to use the OpenId "claimed identifier" as the user name. User names have to be unique, so this the user name “http://AnthonySteele.myopenid.com/” is used up by my OpenID login, but I think we can live with that. We can tell OpenId logins from regular ones by eye (OpenId logins look like Urls), but I'd like a flag to do it unambiguously.

    In the code this flag is an enumeration:

    namespace Oxite.Data

    {

        /// <summary>

        /// How does the user log in

        /// </summary>

        public enum UserLoginMethod: byte

        {

            /// <summary>

            /// Default/unknown value

            /// </summary>

            Unknown = 0,

     

            /// <summary>

            /// The user has a local user name and password

            /// </summary>

            LocalLogin = 1,

     

            /// <summary>

            /// The user logs in using an openId from a different site

            /// </summary>

            OpenId = 2

        }

    }

     

    There could be Cardspace or some other kind of login later. the flag needs to be stored on the user data in the database, with all existing logins marked as “local login”. In SQL, execute:

    alter table oxite_user

    add UserLoginMethod tinyint not null default 1;


    Add the login method to the IUser interface:

        public interface IUser

        {

    ... as before...

     

            UserLoginMethod LoginMethod { get; set; }

    Then fix the fake implementation of IUser with an auto property:

        public class FakeUser : IUser

        {

            #region IUser Members

    ... as before...

     

            public UserLoginMethod LoginMethod { get; set; }

     

    Then do some drag and drop to regenerate the LINQ data classes, which will give the database-backed User class a property UserLoginMethod, of type short. Now we want the strongly-typed wrapper:

     

        partial class oxite_User : IUser

        {

            #region IUser Members

     

            ... as before ...

     

     

            public UserLoginMethod LoginMethod

            {

                get

                {

                    return (UserLoginMethod)UserLoginMethod;

                }

                set

                {

                    UserLoginMethod = (byte)value;

                }

            }

     

    The Oxite membership repository does not yet have a way to add users, so we need to add one:

     

        public interface IMembershipRepository

        {

            ... as before ...

     

            /// <summary>

            /// Add a new user with an OpenId login

            /// </summary>

            /// <param name="userName">The claimed identifier</param>

            /// <param name="displayName">the name to use onscreen</param>

            /// <param name="email"></param>

            /// <param name="defaultLanguageId"></param>

            /// <returns></returns>

            IUser AddOpenIdUser(string userName, string displayName, string email, Guid defaultLanguageId);

     

    This is implemented in the fake repository as follows:

            public IUser AddOpenIdUser(string userName, string displayName, string email, Guid defaultLanguageId)

            {

                FakeUser newUser = new FakeUser();

                newUser.ID = Guid.NewGuid();

     

                newUser.Username = userName;

                newUser.DisplayName = displayName;

                newUser.Email = email;

     

                newUser.LoginMethod = UserLoginMethod.OpenId;

     

                Users.Add(newUser);

     

                return newUser;

            }

    And in the Linq to SQL repository as follows. This isn't perfect (particularly the choice of salt should be unique to the user, and it's not clear how the email should be hashed), but it will do until more complete user-adding code is in place in Oxite.

            public IUser AddOpenIdUser(string userName, string displayName, string email, Guid defaultLanguageId)

            {

                oxite_User newUser = new oxite_User();

                newUser.ID = Guid.NewGuid();

                newUser.Username = userName;

                newUser.DisplayName = displayName;

     

                newUser.Email = email;

                newUser.PasswordSalt = "NaCl";

     

                newUser.Password = saltAndHash(userName, newUser.PasswordSalt);

                newUser.HashedEmail = saltAndHash(email, newUser.PasswordSalt);

     

                newUser.LoginMethod = UserLoginMethod.OpenId;

                newUser.DefaultLanguageID = defaultLanguageId;

                newUser.Status = 1;

     

                dataContext.oxite_Users.InsertOnSubmit(newUser);

                dataContext.SubmitChanges();

     

                return newUser;

            }

     

    So that’s the repositories and domain objects.  Next: the controller and view code to make OpenId logins possible.

    Published Mon, 22 Dec 2008 15:05:00 GMT by Anthony.Steele
  6. Commerce Server blog #2 - Incremental Staging projects

     

    I've been working on an eCommerce Project for the last 18 months built around Microsoft Commerce Server and over that time have picked up a lot of hints, tips, hacks etc. I've been meaning to document a lot of this stuff for a while so it may be old news to some of my current colleagues, but might help out those of you who are starting out on a similar project.

     

    This time I'm looking at Commerce Server Staging (the most under appreciated feature of CS 2007, apparently) and in particular running incremental staging projects.

    One of the biggest challenges that we face on my current project is the sheer size of our product catalog (approx 8 million items). This becomes an issue when you realise that the staging process works by exporting the source catalog to XML, transferring the file to the relevant locations and then importing the XML back into the destination catalog!

    So, incremental staging is vital for our project to ensure that we only stage what we need - we were always going to have problems when we had to stage the full catalog due to the sheer size of the data. Unfortunately, it's hard to avoid this as if we set up a new staging project to run incrementally, the first time this project runs, as it has never run before it will always attempt to stage the full catalog.

     

    The staging process writes to two Access .mdb data files during operation. These files can be easily opened in Access which tells us the following:

    1. [Commerce Server 2007 install directory]\Staging\Events\Events.mdb

      This database contains two tables – one reference table with event codes, and one event table which basically contains the same entries as in the event log, but grouped by staging project where possible.

    2. [Commerce Server 2007 install directory]\Staging\Data\StagingLog.mdb

      This database contains only one simple table:

      Staging Log

     

    • The first time an incremental staging project runs, if no entry is in this table, then the full catalog export is exported.
    • Once the first incremental staging project has completed (successfully) an entry is added to this table, with a time stamp of the current date and time.
    • The next time an incremental staging project runs, the latest time stamp for the project is used to perform an incremental export of the catalog.
    • The staging service does not seem to bother with any referential integrity on the ReplicationId in the StagingLog.mdb, my tests indicated that the service just selects all the entries from the table for the project name and gets the latest timestamp to use in the export.

     

    So, we can trick the staging service into thinking that it has already run by simply adding a new entry in the StaginLog.mdb with the current date and time and an arbitrary GUID for the replication ID, with a status of Completed.

    N.B. this assumes that the source and destination catalogs have been replicated by some other mechanism (e.g. SQL backup and restore) and are therefore in sync before this is done.

     

    The incremental staging project now works as desired -the first (full) catalog staging job has never occurred and only incremental changes will be staged from now on.

     

     

    Published Mon, 22 Dec 2008 11:11:00 GMT by james.broome
  7. An early Christmas present

    Seasons greetings to all =0) As I have said in one of my previous postings I subscribe to Mark Wilson's Blog as his postings apply a lot to the stuff I am trying to learn myself and has helped me out many times to learn new stuff about Virtualisation.

    Last week while reading through his blog I noticed he was writing his upgrade exams to windows server 2008 for his mcse and left a comment stating I had written the same exam a few months back and as stated in another of my previous blogs that I felt it wasn't as hard as the upgrade exams from mcse 2000-2003. For posting of this comment on his page one of the fields it asked was website so I put my blog page in there and it seems mark went to the page and actually read some of my blogs as on my scanning through my rss feed of Mark's blog this morning I came across something that will keep me smiling inside for quite a while. Mark honoured me by mentioning and tracking back to my blog page about my last posting about the discount on Microsoft Virtuali