Archive for the ‘Website Owners’ Category

PayPal’s New API: So Close, Yet So Far

Friday, February 16th, 2007

I got an email from the PayPal Developer Network today announcing PayPal’s new “NVP” (or “Name-Value Pair“) API. Clearly they’ve learned that the complexity of SOAP is counter productive to adoption. Here’s what the email had to say about their new API:

NVP Is Your Integration MVP
We’re proud to announce that PayPal’s Name-Value Pair API has launched. Complex SOAP structure is now gone. All API methods are supported, except for AddressVerify. Get exclusive sample code – download two SDKs (Java and .NET). Get Details

Taking a look at their examples (in .ASP, .PHP, or ColdFusion) and their SDKs (for Java and ASP.NET [v1.1]) it’s nice to see they are using POST instead of GET. The following is one of their functions from their PHP examples (CallerService.php) that illustrates how their code is calling their NVP API (I edited for line-length only):

function hash_call($methodName,$nvpStr)
{
   //declaring of global variables
   global $API_Endpoint,$version,$API_UserName,
          $API_Password,$API_Signature,$nvp_Header;

   //setting the curl parameters.
   $ch = curl_init();
   curl_setopt($ch, CURLOPT_URL,$API_Endpoint);
   curl_setopt($ch, CURLOPT_VERBOSE, 1);

   //turning off the server and peer verification
   //(TrustManager Concept).
   curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
   curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
   curl_setopt($ch, CURLOPT_POST, 1);

   //if USE_PROXY constant set to TRUE in Constants.php,
   //then only proxy will be enabled. if USE_PROXY constant
   //set to TRUE in Constants.php, then only proxy will be
   //enabled.
   //Set proxy name to PROXY_HOST and port number to
   // PROXY_PORT in constants.php
   if(USE_PROXY)
      curl_setopt ($ch,
                        CURLOPT_PROXY,
                        PROXY_HOST.”:”.PROXY_PORT);

   //NVPRequest for submitting to server
   $nvpreq= “METHOD=”.urlencode($methodName).
            “&VERSION=”.urlencode($version).
            “&PWD=”.urlencode($API_Password).
            “&USER=”.urlencode($API_UserName).
            “&SIGNATURE=”.urlencode($API_Signature).$nvpStr;

   //setting the nvpreq as POST FIELD to curl
   curl_setopt($ch,CURLOPT_POSTFIELDS,$nvpreq);

   //getting response from server
   $response = curl_exec($ch);

   //convrting NVPResponse to an Associative Array
   $nvpResArray=deformatNVP($response);
   $nvpReqArray=deformatNVP($nvpreq);
   $_SESSION[’nvpReqArray’]=$nvpReqArray;

   if (curl_errno($ch)) {
        // moving to display page to display curl errors
        $_SESSION[’curl_error_no’]=curl_errno($ch) ;
        $_SESSION[’curl_error_msg’]=curl_error($ch);
        $location = “APIError.php”;
        header(”Location: $location”);
    } else {
        //closing the curl
        curl_close($ch);
     }

return $nvpResArray;
}

Much nicer and simplier than having to go to all the effort to set up a SOAP call.

Unfortunately, PayPal missed a huge opportunity to make their new API fully RESTful. Instead of designing a URL-centric REST interface (with a hypermedia component to keep the purist or the pure RESTafarians happy) they instead tunneled method calls over HTTP!  They used methods like “DoDirectPayment” and “RefundTransaction” Sheesh! (Note: these links to their methods load slower than any website I can remember visiting in ages and while loading my browser does lots of clicking. What the heck is going on in there I have no idea! You can go to the main docs via a much faster downloading PDF here. Wow, if that isn’t usually an oxymoron!)

Though much easier than calling SOAP, clearly not very RESTful.  Three steps forward, and two steps back. Sigh…

URLs for Multilingual Web Sites

Monday, February 5th, 2007

Another URLian has appeared: Brad Fults. Brad just added himself to our wiki and became a signatory; thanks Brad! Better yet, on his user page on our wiki he linked to his post Designing URLs for Multilingual Web Sites; execellent job Brad!

That was a subject I’ve been planning to write for a while, and I’ll probably cover the issue in the future to here on the WDUI Blog to future the conversation but I doubt I could have done as good a job as Brad for my first post on the subject.

One option he did not cover was using using language in filenames, such as #1 - an extention:

example.com/bar/baz.en-US
example.com/bar/baz.en-GB
example.com/bar/baz.de

Or a #2 - suffix to an extension (note I had to add an .html extension for this option):

example.com/bar/baz.html.en-US
example.com/bar/baz.html.en-GB
example.com/bar/baz.html.de

Or as an #3 - extension prefix (also needed an .html extension):

example.com/bar/baz.en-US.html
example.com/bar/baz.en-GB.html
example.com/bar/baz.de.html

Or as an #4 - filename prefix:

example.com/bar/en-US.baz
example.com/bar/en-GB.baz
example.com/bar/de.baz

Or #5 - one level up in the path:

example.com/bar/en-US/baz
example.com/bar/en-GB/baz
example.com/bar/de/baz

Unlike Brad, I didn’t provide an evaluation of these simply because I haven’t researched the subject enough at this time. Maybe he can do a follow up post providing an evaluation of each of these.

However, I can say I don’t really like any of these options, nor are any of the options Brad provides sit well with me except possibly his “Modified Directory Structure (#2)” combined in creative ways with his “Use of Accept-Language HTTP Header (#6)” the latter a.k.a. Content Negotiation. Whatever the case, there will be more on this subject in the future, I’m sure, and it’s good to have this discussion taking place.

Which is Worst: the URL for IE7 Add-ons, Firefox Extensions, or Greasemonkey?

Friday, February 2nd, 2007

I am working on a project that had me was writing about browser plug-ins and I needed to link to the main page for Microsoft’s Internet Explorer Add-ons, for Firefox’s Extensions, and lastly for Greasemonkey for Firefox

I actually looked up those three in opposite order than I have them listed above. Greasemonkey’s URL was pretty good although it’s a shame it’s not greasemonkey.com/.net/.org; the .com resolves to a 403 forbidden page, the .org resolves to a list of advertising links, and the .net resolves to Grease Monkey International, a franchiser of automotive preventive maintenance centers! Whatever the case, I feel pretty good that this URL is going to have really good persistence. It should be around at least as long a Greasemonkey is relevant if for no other reason than to return a 301:

http://greasemonkey.mozdev.org/

The second URL for Firefox extensions was not so good, but I still think there a pretty good chance it will still resolve a year from now:

https://addons.mozilla.org/extensions.php?app=firefox

Then there is Microsoft’s horrific URL for Internet Explorer Add-ons.  What were they thinking?  I’ll bet this URL doesn’t resolve three months from now let alone in a year of five:

http://www.windowsmarketplace.com/category.aspx?bcatid=834&tabid=1&WT.mc_id=0107_20

URLs like this one from Microsoft are a crying shame. Sadly, Microsoft is one of the few companies that can get away with this without be negatively affected. On the other hand, most companies haven’t a clue how bad URLs like this can affect them.

That said, I’d love to get your input:

  1. Why is Microsoft’s URL so bad?  Help me find and explain all the reasons why companies should care not to be so careless when designing their URLs. Why is it bad for users, and why is it bad for Microsoft?
  2. Design the Ideal URLs. Assume you have no constraints at all – no badly designed content management system and no inflexible server technology — and suggest the ideal URL for each of the above three resources. Heck,  you can even change domain names if you want to. So what would be the best URLs for each of the three above?

Best Practice: Always ID your Heading Tags

Thursday, January 18th, 2007

Here’s a simple best practice. Always ID your heading tags! For example, if you’ve got an <h2> element, be sure to make it <h2 id=”some-heading”>.

IDing heading tags is especially important on long documents.

Why? Because if you don’t, someone else can’t reference the part of the document that they want to reference in a blog post or somewhere else. And if they can’t, they just might reference someone else’s web page instead. Or if they do reference it, readers who click over to your URL might give up on reading before finding the appropriate document, and never come back to your site when they might otherwise have become an avide reader. How often have you see a link to a web page where the person linking included the text “Scroll down to the section entitled…“  Bleach!

Given the heading tag mentioned in the first paragraph above, and assuming it was contained in a document entitled “whitepaper” in the root of www.foo.com, you can point straight to that heading using a URL fragment like so:

http://www.foo.com/whitepaper#some-heading

Ben Coffey talks about this same problem over at URLs for Specific Portions of Documents.  He also talks about CiteBite which helps bloggers and others link directly into a part of a document as if there had been an ID there. But publishers, if others start using CiteBite on your content simply because you don’t include the ID attributes they need to link to your directly, guess who will get the Google PageRank?  Not you… ;-)

One more thing. If you are creating content that will be displayed above or below other content, i.e. blog posts that get listed with other blog posts on the same HTML page, you’ll need to make sure your IDs are unique. I personally have started using a convention that appends the date in “YYYYMMDD” format to the end of a meaningful fragment, seperated by a dash, as in:

http://www.foo.com/whitepaper#some-heading-20070118

This tends to work for me because I almost never post more than once per day. Also, though I personally dislike the inclusion of dates in URLs because of how difficult it makes things for users to remember or discover the URLs, having the date as a fragment suffix is not quite at bad. People using the browser URL auto-complete can still easily find the URL they visited recently enough that its URL is still in the browser’s cache. YMMV.

Lastly, if you are going to ID your heading tags, you probably should also create a table of contents. ‘-)

Lessons Learned from Delicious Praise

Tuesday, January 16th, 2007

I learned an interesting lesson about URLs and social software; change your article’s URL or publish it under multiple cases, even with 301 redirects, and you’ll end up with fragmented references.

Back in August 2005 I published the article Well Designed URLs are Beautiful on my personal blog and have since had well over 400 people tag it on del.icio.us. Unfortunately during that same time, I’d changed my blog configuration twice to improve its URLs with one more change planned. Of course for each change I made sure the old URLs were redirected with a 301. Unfortunately, these chances resulted in my article being tagged from three different URLs, and hence splitting up it’s ranking on del.icio.us three ways!

So, when changing URLs, be careful. You could harm yourself in the process.

P.S. As an aside, this speaks sadly to ones ability to reorganize a poorly organized website, notwithstanding the fact that Cool URIs (aren’t supposed to) change. I can understand why del.icio.us and others don’t automatically test their links for 301s on an ongoing basis because of the resources required, but delicious and others could offer a “check me” test for links. This would even give them a legitimate reason to periodically email their users and say “Hey, here are all the links that moved!” That email could even ask “Should we keep the changes?” to guard against spammers, though I don’t think this would be a big issue. It is hard enough to get delicious links, how would spammers get them to begin with?

Anyway, I hope to see things evolve in the future where changing links won’t be such a big issue. And yes, sometime in the reasonably near future I plan to be an advocate for some specific plans to enable this.

Intro, Part 15: About URLQuiz

Wednesday, January 10th, 2007

As a way to gather a broad spectrum of opinion and engage the community on many different URL-related topics, we’ll be offering a URLQuiz from time to time. Inspired by and patterned after Dan Cederholm’s very well received SimpleQuiz series, we’ll take a simple URL Design question, present a few different alternate approaches, and ask readers to weigh in on which they believe to be the best and why.

Dan proved that his SimpleQuiz was very effective at quickly emerging a consensus for a best practice when a consensus was possible. Building on Dan’s pioneering efforts, we hope to leverage his technique to address the constantly debated issues in URL Design and hopefully arrive at some consensuses of opinion on URL-relates issues ourselves.

So look for the first URLQuiz, part of an ongoing series, here at the Well Designed URLs Initiative blog in the near future.

Intro, Part 11: Each Post will Identify Audience

Wednesday, December 27th, 2006

Here at the Well Designed URLs Initiative we plan to address a wide audience and cover a plethora of URL-related topics. If it wasn’t obvious from yesterday’s post we plan to publish content for a variety of roles so we will categorize all our posts by the audience we are targeting.

Using our audience categories you can subscribe to our RSS feed then configure your feed reader to filter out all but those topics which are likely to appeal to you so as not to be overwhelmed by the rest. Some of our audience categories encompass other categories such as Everyone and Internet Professionals so we’ll plan to tag only the highest level category that applies to avoid duplication. For example, if you are a web developer you might want to filter out all but the Everyone and Internet Professionals, and Web Developers categories. Of course, if that’s too much trouble just subscribe to our entire feed and just ignore those posts that don’t interest you.

The following is the list of categories we’ve set up by audience role:

NOTE: If you read this post shortly after it is published, most of those links above will just redisplay this post. Let me explain. Because of the way our WordPress blog software works, those links would have displayed a 404 Not Found error if no posts existed for the given category. To avoid that I’ve tagged this post with all audience categories contradicting what I said above; that we would only put a post in its highest level category. Moving forward we shouldn’t need to do this again.