Eric Boyer

Jul 19 2011

Pay Per Click and You

This article originally appeared on Codesta’s blog

Background

We recently started advertising our services on Google through their AdWords platform.  About 3 days in we decided that we needed to streamline the site and provide better keywords to Google to improve the experience for users clicking on our ads.  This meant stopping advertising, re-designing our site and migrating our content to SquareSpace, tweaking the ad campaign and then re-launching. 

There was some learning and growing pains at the start, and there are tons of resources out there for getting started in paid advertising for search engines. It is a big field with lots of information about tweaking and tips on how to analyze your data. This article is meant to be more advanced than just a starting tutorial, giving advice on what help me tune our AdWords campaign. Some of these tips are also geared to more of a high cost, niche advertising area than bulk consumer oriented searches.

Onto The Tips!


Quality Score

From reading all the help documentation on AdWords, this is the biggest factor in determining how much Google charges you and how high your ad gets to be displayed. Sometimes you can make up for this by paying more for your ad but improving this will help lower your costs and improve the position of the ads. This is essentially Google’s way of determining how satisfied a searcher will be with the results of clicking an ad. Once there is some Click Data, this will also be factored into the placement of the ad. If you think about it, Google is essentially trying to optimize the amount of money that it will get by optimizing the CTR and the CPC. So it can display ads with high click throughs (combination of past CTR, and quality score) or ads with a lower CTR but higher price.

Limit Scope

I think the first thing that you have to learn when starting an AdWords campaign is not to be too greedy. This can lead to under performing ads and higher costs. Target the areas which are core to your business and display it on the website. This will not only improve the quality score of the keywords but lower the cost of being displayed on the front page. The easiest way that I found to do this was by including the Geographical location with our keywords (ie. software development + toronto). Also trying to think like a user trying to find your business can help to tune the keywords that a user may enter to find your site.

Link it to Analytics

This is really a basic tip, but is key in determining statistics like bounce rate, number of pages per visit etc. Google Analytics gives you the ability to segment based on paid traffic making it easy to determine how the paid visitors are interacting with your site.

Conversions

Conversion tracking is useful in finding out if a user performs some sort of action after clicking on the ad to get to your site. This is useful in determining the cost of some sort of success state. For our site we ‘convert’ on the contact page. If a user lands on the contact page after clicking on an ad we consider it successful. We also convert when a user uses the ‘Contact Us’ form, to track the amount of people that are sending us lead emails.

Use Negative Keywords

This is especially important for keywords that have 2 meanings. Development is one that can be used in multiple contexts. Someone searching for Mobile Development could be looking for a contractor or just learning how to actually do mobile development. In this case, adding the negative keywords that relate to learning, such as tutorial or getting started, can make sure that we aren’t advertising when someone is searching for help.

Use the + Modifier When Making a Broad Match

Broad matches can sometimes be way too broad. Using the + symbol in a broad match will limit the scope of the match to those having the term (or its close variations). This helps target your keywords which will limit scope and help lower the front page bid. This is also a great way of geo targetting ads; just add a +<city> and you can have a broad match scoped to users searching within the city.

Technology Keywords vs. Custom Software

I created two distinct ad groups focused on an over-arching concept when designing our campaign. One was focused on the technology we work with (ruby on rails development, Apple iOS, Google Android) while the other was more focused around local searches trying to highlight our ability to produce quality custom software. The one focused around local custom software has performed significantly better so far. My suspicion is that the ads are being shown on search queries which the user is trying to find out information around a programming topic.

The decision to split the campaign into two separate ad groups was made from guidance contained in the help guides. The guides recommended we create targeted ad groups selling the same service. We also created a custom landing page that would give a broad overview of the services we provide and the technology we work with. I thought these two changes would make the two ad groups distinct and improve the keyword quality for both. So far, this has not been the case.

How do you Advertise for a Low Volume High Reward Site?

Very early on I determined a few metrics for success. One was having high value, low volume leads. This meant being highly aggressive on very niche terms that applied directly to the services that we are selling. We determined that we could set high CPC values to bring in users which were already broadly searching for a company to satisfy their needs in our area. Combine this with a fairly low volume approach means that we aren’t spreading ourselves too thin and we are staying within our budget.

Don’t Fall Victim to the Tweaking Mentality

This was very hard to resist at first. You need a few days to a week of data to make informed decisions. Combine this with our low volume-high value approach meant that making tweaks can mean you never reach a steady state to make valid statistical conclusions.

Search Terms Used to Click on an Ad

I tended to refer to the statistics in Google Analytics about which search terms lead to a click on our ad. This data exists in AdWords but never seemed to be as up to date. Seeing the search terms allows you to tweak negative keywords and your keyword matches. Having this information is invaluable in determining if a user was satisfied when reaching your site, based on the bounce rate and the number of pages they visited.

Refresh

Wait for AdWords to refresh your keywords before reading to heavily into any of the data it gives you. There is a delay which can be misleading at first, ranking your quality score higher or your CPC lower; giving you the impression that those keywords are going to perform better than they will if you don’t go back and check.

Gauge Success

It is key to be able to gauge the success of a campaign in terms other than just the number of clicks and the CTR. To do this you need to collect other stats, like conversions and more page tracking oriented stats like bounce rate and pages per visit.

Our high value-low volume approach meant that we need to capitalize on every visitor. Early on into the campaign I noticed that visitors coming from the display network had a 100% bounce rate (especially in the mobile space). That quickly lead me to stop displaying on that network. Plus what we are advertising struck me as not really applying when someone is playing a game or in app. After making that change our bounce rate for paid traffic is down to 32%, with 6 pages per visit, almost double the site average.

Resources

Beginner: http://blog.octoclick.com/
- Great resource covering a ton of topics to get you started with this advertising model.

+

Migrating to SquareSpace from TypePad and AWS EC2 Instance

This article original appeared on Codesta’s blog.

What Prompted The Switch?

Our old design was showing its age. It had two domains, one for our main ‘brochure’ site and one for our corporate blog. Resulting in two different PageRanks from Google and a somewhat jarring visual change when going from one to the other. We started to run an AdWords campaign and realized that we needed to modernize the look and feel of the site, improve the SEO footprint, and reduce our costs at the same time. In addition, I was having a hard time implementing the features we wanted with the old platform. I decided to give SquareSpace a shot after I had had enough of Typepad. I was not disappointed. After an hour of work, I had a limited import setup and some great styles that only needed a bit more refining to get it up to par with our old site.

Old Design

Our blog has gone through a few re-designs and re-implementations without really focusing on the goals of the site. This time, I made up a small list of features that I wanted to see in our company’s website.  
- easy for anyone to alter content
- easy to customize
- all one domain
- no broken links
- no servers we had to maintain
These features were around 3 key goals: keeping the blog manageable by someone other than a designer/programmer, reducing the hosting overhead, and keeping the SEO we already had. Also because the main site was no longer hosted on Amazon EC2 there wasn’t the possibility of losing it randomly one day as fail over infrastructure did not exist for a lower priority site.

Why Not Stay With TypePad?

Typepad had some of the features that we were looking for. The platform can put up static pages and it has a fairly robust HTML authoring system but the additional features of SquareSpace added to what was already a growing list of benefits.

The biggest issue with Typepad was the lack of redirects. We were suffering from a few previous redesigns which had not made redirecting links a priority, so we had some broken links into our site. SquareSpace provides 301 and 302 redirects along with URL Rewrites. Also there is a good site search for anyone who does get a 404 page.

The second biggest issue was that customizing it required knowledge of their templating syntax and CSS. Both of which are a barrier to improving the site by non-developers and developers. Being able to jump in and change a lot of the basic properties visually is a huge productivity win.  

The Import

Well, this didn’t go as smoothly as I was hoping for. Importing a blog from Typepad is supported in SquareSpace via a dump file. They also allow you to input your login information so that they can spider your permalinks and redirect them to the new articles. The automatic link redirection didn’t work for me, twice. Having to do this by hand, without a bulk uploader took a long time.  

The formatting of the posts also took a long time to correct. It appeared that the import or the WYSIWYG editor inserted additional HTML that had to be cleaned up. 

Otherwise it worked as advertised. The content was there, images were imported, author names were associated correctly, and the dates were properly assigned.

What Are The Benefits?


Manageability

This was a huge improvement as well, no more static HTML server. Everything is much easier. Adding new posts, comment management, site layout etc…  

Experts not required

SquareSpace makes it easy enough for just about anyone to customize the look and feel, alter the text and get to a point where it looks really good. I have to say that it isn’t 100% there yet. Custom CSS is still required and the amount of options on some of the pages/widgets is quite overwhelming. 

SEO

Hosting the blog, and the main site on the same domain should collapse the Page Rank onto the one site if the redirects are handled properly. Having all the unique blog keywords associated with the main site lends credibility to your main site and gives users a better way of finding out about the company. Most of the main site’s content is static and won’t get updated very often, having a constant stream of new posts that are linked in the sidebar throughout the site keeps these pages somewhat fresh.

Cost

Due to our setup we were paying for Typepad (whose fees are about 25% lower than SS) plus AWS EC2 fees for a Windows box. Combining everything and decommissioning the EC2 instance should save us a bit of money each month. Not a huge amount but icing on the cake no less.

What Difficulties Were Experienced?

The two major issues that I experience were sidebar panels ‘selective display’ not working properly (which I talk about later) and the blog import. The blog import was less of a technical hurdle and more having to just spend the time to fix it.

Choose your blog name carefully as well, as it can’t be changed. Setting up a custom domain just solves the URL display issue but you can’t alter the name of the admin account.  

Webmaster

Using Google Webmaster was invaluable in finding out which links where pointing to the site and redirecting those to the appropriate pages. There were links from 3 previous versions of the site that were no longer valid. Fixing these links not only helps users, but improved the SEO of the site as well.

Looking Forward To SquareSpace V6

There has been talk about v6 of SquareSpace coming out very shortly. Some of what has been hinted sounds awesome. After seeing what they put together for v5, I’m looking forward to getting my hands on v6. Having the ability to test the site out in v6 without having to commit is also huge and will make migrating a less painful process.

I’m a little hesitant on the new visual changes, I don’t know how the migration from v5 to v6 will deal with the customizations that have been made.  I hope that the amount of time porting over is relatively short as I don’t really want to be spending another few days re-customizing a new skin.  The upside is that it sounds like it won’t be a forced upgrade, meaning that we can leave things exactly as they are.

‘Customizing’ Templates and Code

This is a huge improvement over Typepad. I don’t want to have to learn another templating language. On the other hand, SquareSpace does not provide the same level of customizability that having access to raw HTML does.  Having ‘generated’ pages makes setting up a lot of things painless, and sidebar widgets do a good job of providing a lot of basic functionality required. If worse comes to worse, you can also break out the HTML/JS/CSS and customize a page in any way you want. The constraints that SquareSpace imposes are good trade-offs in the debate between customizability and simplicity.

Facebook Like in SquareSpace

This was surprisingly easy to do with Facebook’s iframe approach.  Just click on one of the HTML snippets for a Journal, and input the following:

<iframe src="http://www.facebook.com/plugins/like.php?href=%PERMALINK%&send=false&layout=button_count&width=100&show_faces=false&action=like&colorscheme=light&font=arial&height=21" 
scrolling="no" frameborder="0" style="border:none; overflow:hidden;height:21px;width:90px" allowTransparency="true"></iframe>

This will insert the smallest Like widget that has a count. I also killed the floating of it and positioned it so that the button lined up on center with the rest of the HTML sections:

.journal-entry-tag .post-snippet-1{float:none; position:relative; top:7px;}

Improvements

Side Panels can’t be set to selectively display on their own pages. This is one of the most brain dead things I have encountered in this migration. Why can you not set the side panel to display when in a page on that side panel? In the end this was solved with some custom CSS, to hide/show the side panels on the require pages, totally defeating the customizability. This also shows up on some of the other built in pages like search and 404s.  Manymany, forum posts are on this topic.

It bothers me a lot to see how many different files are being downloaded. Each page has a bit of custom CSS, but overall a lot of the YUI files included could be combined into one file and served. Image sprites could help as well but weren’t as big of a deal as the other resources.

The amount of HTML in the templates is excessive. There are wrappers around wrappers.

Bulk Uploader for redirects, this is key when migrating sites. Entering one at a time and waiting for a request-response loop was painful.

Has it Been A Success?

I would say so, our site is easier to maintain, easier to navigate, it has gotten more traffic, and after a year or so of no updates to a lot of the areas, we are finally improving sections. One thing that is an aside from improving the platform and design is the content of the blog. Having great, original content in areas which are new and upcoming drives visitors and links to your site.  Having those improvements under one domain makes it easier to do Adword campaigns and make improvements in SEO more impactful.

Wrapping it All Up

SquareSpace provides a lot of compelling features at an attractive cost. For us the benefit of having a simple, straightforward site means that developers don’t need to be involved to manage upgrades or customizations. This keeps the developers focused on what they should be doing and gives the tools to those that need them.  

Will we stay within the SquareSpace confines? Probably, the blog and site are small enough that SquareSpace handles it admirably. The trade-off between a custom site or even an open source solution and hosted solution has swung in favor of the hosted solution for sure. For us, there is no way that a custom deployment is possible to compete on price, ease of use, and customizations. For a small team this is key, pay someone else to worry about a product that is not core to your services.

Jun 25 2011
Jun 09 2011
What are mainframes? is it like the cloud?

Jun 08 2011

Native vs. HTML5 Mobile Development Part 2

This article original appeared here: http://www.codesta.com/blog/2011/5/31/native-vs-mobile-html5-part-2.html

In my previous article, I gave a broad overview of the major functions of the components that we used to build out an in-field mobile application and server side component to synchronize the mobile information back to. Here I will break down and compare the products in categories, and the benefits/pitfalls for each.

Platform Support

Platform support has to be the lowest common denominator of the technologies that are being used. In this case it is Sencha Touch. Sencha Touch is currently officially supported on Apple iOS, Android, and BlackBerry 6; PhoneGap is supported on iOS, Android, BlackBerry 4.6 +, Palm WebOS, Windows Phone and Symbian. Supported is the key word here as the support features and API do vary from platform to platform. Separate deployments are necessary when targeting the different platforms which adds a bit of overhead. PhoneGap has already anticipated a need in this area and started a project called PhoneGap Build, to automatically build the HTML5 mobile site for the supported platforms with no setup locally. This greatly simplifies deployment to multiple platforms.

Performance

This is the one area that is concerning when starting to use these technologies. Overall, in this project, it didn’t end up being an issue. As always, your mileage may vary. The performance will obviously be lower than anything native, however I didn’t find that the executing JavaScript was typically the bottle neck. PhoneGap’s main functionality is written in native code, so overall it performs well. Calling in to it results in overhead to intercept the custom URL, parse it, dispatch the function and then interpret the result. Care has to be taken not to tie up the JavaScript interpreter as it does run in the main thread. If it becomes unresponsive, the application will suffer and may be killed by the OS. If you have some performance critical piece of code, creating a PhoneGap plug-in mitigates this and provides a way of accessing a faster environment and off-loading the calculations.

Recently, Apple introduced changes to the Nitro engine that iOS uses to JIT the JavaScript and improve performance. This change does not affect the UIWebControl that PhoneGap uses to host the application, thus this benefit does not extend to native HTML5 applications. The likely scenario is a technical limitation instead of malice on the part of Apple.

Look and Feel

One area that was noticeably different than native applications was the visual differences. The smoothness of the animations and occasional frame rate drops were noticeable. Also orientation changes are more “blocky” than natively as the change is not triggered until after the orientation is completed resulting in a refresh and recalculation at the end of the event instead of throughout it.

The Sencha Touch framework has excellent default styles. Applications look really polished with a high level of attention being paid to subtle details. The CSS is compiled from multiple, logically separated Sass stylesheets. Being able to specify styling in on area is a huge benefit.

Debugging

Debugging JavaScript on the mobile device is just about the toughest thing that was encountered. There is no way to get access to anything as nice as the developer tools in WebKit or Firebug in FireFox. Fortunately most of the time you can develop in Chrome/Safari on the Desktop and test to make sure that everything works on the device. Testing on the device should happen quite often to ensure that everything works the way you expect. If you’re using PhoneGap, on the desktop, you will have to emulate the APIs it provides, which could be extremely difficult depending on what you are trying to do. 

Try/Catch statements are your friend when debugging, and PhoneGap provides a hook for the console allowing log messages to be printed to the application log. These are invaluable. Some improvements are being made in this area but it is still far behind the native development tools. Breakpoints, variable inspection, and stack inspection are sorely missing from the mobile development.

Running your project in the iOS simulator is not sufficient for performance testing. It will perform wildy different; the iOS simulator has access to the better resources of the host computer. The application will actually look really good in the simulator with the animations being buttery smooth.

APIs/Object Model

PhoneGap provides access to the mobile phone features through exposed JavaScript objects. This works reasonably well for the most part. There are some difference between the exposed API and what is being proposed by the W3C. Most notably was the File access and Contacts in iOS, which has undergone significant rewrite in the latest version, 0.9.5. It is impressive to see them attempting to bring it closer to the proposed W3C specs and providing the native features that elevate the application beyond a simple web app. However, the changes are happening quite quickly so you have to be aware of breaking changes when upgrading versions.

Sencha Touch contains a fully fleshed out Object Oriented framework. This is just about the biggest change coming from web programming, and especially from jQuery. The differences here are quite significant however if you already use one of the related frameworks, like Ext, then you will be right at home (well, you will be missing some features you are used to). When programming with Sencha Touch, you are chiefly manipulating framework objects which encapsulate their HTML and behavior. This can be really daunting at first, because simple operations that have been straight forward are now hidden beneath different concepts like layouts, card switching, and parent-child relationships.

The object model is well designed and well laid out. It is very easy to work with and understand once the initial ramp-up is complete. Personally I feel they take the OO to the extreme so it can be a little tough to follow. Also, there is probably a technical reason, but it seems odd that most of the widgets inherit from 2 different Component classes and two different Container classes.  I would hazard that including the concept of Mixins to the framework would greatly reduce the depth of their OO hierarchy. There are some missing functions that I would have thought to be there, or others that did something unexpected such as events that weren’t fired when I expected them to either, but it is all part of the learning curve. Overall there were now show stoppers, and work well enough.

The Sencha Touch framework induces this feeling that a developer shouldn’t directly manipulate the HTML. This feeling stems from the heavy OO design; the feeling that you may cause behavior to break, or that you are limited to functions in the object model and anything else isn’t possible. It is something to be aware of and to move past. 

Documentation

PhoneGap has great API documentation. It’s clear, with good examples, and easy to follow. However, when you try to find out information on building instructions, or developing plugins, it degrades into a wiki type free for all. It is still manageable, but not nearly as clean as the API documentation.

Sencha Touch has wonderful documentation at first glance. Until you start using it and find out that some of the documentation is just slightly wrong. At a cursory glance when evaluating the framework nothing looks wrong and there is some significant detail written for some methods.  But, you’ll run into links to classes that don’t exist, wrong type signatures for functions, and wrongly named properties.  The occurrences are rare, so it is easy to get past; especially since the source is just a click away. 

Community

PhoneGap has a reasonably active development community, taking the time to answer questions in the Google group and respond to issues. Code is still being developed at a reasonable pace, by a few main contributors along with additions from anyone who is willing to sign the Contributor Agreement. 

Sencha provides paid support for Sencha Touch giving you access to dedicated resources and support forums. The response rate on places like the Sencha Forums, and StackOverflow are acceptable and there seems to be a handful of people willing to help and lend a hand. I don’t think that Sencha accepts source code from outside its organization which is a little disappointing but not surprising. Having a company backing a product really improves the experience of using it.

Productivity

Personally, I would say that while there are definitely some productivity improvements by switching to HTML5 and JavaScript over iOS, it isn’t a significant amount. It really depends on the programming area, trying to do something like a gradient background on a UIView/Panel is significantly easier with CSS, than attempting to mess around with the CALayers. However, once again, the area that suffers is debugging. Both Android and iOS have great debuggers that allow for some detailed analysis. It just isn’t there for the JS runtime. Some of the productivity gains in development will be lost if issues are found on the device that cannot be reproduced in a desktop browser.

Bugs

The developers at Sencha Touch should be commended for putting out a framework where debugging on the device is tough. I cannot imagine the amount of pulled hair that has been lost to this project.  There are a few issues with the framework that I have run into. Twice running into reproducible undefined object errors, other times errors that were seemingly triggered based on the UI state, or timing. One of the most severe bugs when starting the project was incorrect orientation. This was due to a combination of issues between both Sencha Touch and PhoneGap. The ‘onorientationchange’ events were not being fired properly. It made me question the platforms as being viable. If something as simple as this was broken from the start, what chance is there for the rest? What ended up mitigating this was the ability to change the source for both projects, and fix the issue.

Storage

Storage is an area where the limitations of the ‘native’ HTML5 app show up. The easiest storage option, ‘Web Storage’, is limited to 5Mb with no way to increase it. This limit can only hold 2.5M characters due to the fact that the character representation is encoded in UTF-16, a 2 byte format. There is no way that you can store any amount of significant image data in storage that small, so it will have to be read off the disk using the File APIs. However there are ways around this limitation, if you are willing to spend the extra time. I’ll discuss these in a future article.

Overall Development Experience

The ease in which you can change UI elements or switch around views was probably one of the best aspects of using this technology. Going from one design to another is extremely easy, especially if the code is organized properly. Developing in JavaScript is a nice change from Objective C and its liberal use of closures can simplify logic and allow for interesting ways to solve problems. One area that is quite annoying is the binding of the ‘this’ variable. Many of the Sencha Touch functions/callbacks take a scope parameter to set ‘this’ properly which is necessary but tedious.

Future Ideas

It would be a lot more interesting (and probably perform better) to see PhoneGap implemented using the JavascriptCore framework. While not currently technically possible, due to Apple not exposing the JS context of the UIWebView, it has been demonstrated to work in a standalone environment.  This would be a lot more like the approach that Appcelerator Titanium has taken, providing APIs that compile down into Objective-C/Java code.

Another idea would be to include a Desktop shim with PhoneGap to emulate, or at least stub out the functions that are used. This would greatly improve desktop debugging which is a necessity when developing with these technologies. Most of the additions that PhoneGap makes to the document are going to be in the W3C spec, so eventually desktop browser will have at least some implementation of the features.

Conclusion

The promise of HTML5 and associated technologies to do mobile development is alluring. The overall feeling I have after working with the technology is that it is roughly 80% there. Close enough to be attractive and viable for a limited subset of problems. However it does come with serious limitations.  Hopefully this article has been able to provide a good overview of the technologies strong points and its limitations. Developing with this technology was very enlightening and allowed me to explore these uncharted areas of mobile development. Both products are well done, and well supported. I expect that some of the issues that I’ve mentioned will fade away over time as this method of developing applications matures.

May 24 2011

Blog Visuals

Definitely going to have to spend some time over the next few days implementing some sort of custom skin.  Hadn’t really had much time and didn’t really expect anyone to actually stumble on it :)

+

Sench Touch/PhoneGap Tips and Tricks

Another blog article by me on Sench Touch and PhoneGap was recently posted on Codesta’s blog.

App Variable

Do not name your application ‘app’ like a lot of the examples do when using Sencha Touch. On Android, PhoneGap injects an object named ‘app’ that will overwrite your own. Not extremely hard to figure out but annoying if you have to replace the variables all over your code base.

Multiple IDs

Do not use the ‘id’ parameter of an object in Sencha Touch unless you are sure that only one will exist. If multiple objects having the same id are in the page, you will start to get unusual bugs. Even if you are transitioning from one to the other, the brief period where two exist is enough to trigger the bugs. You are better off using classes (property ‘cls’) to refer to panels.

Managing Multiple Panels

Sencha Touch comes with the ability to ‘garbage collect’ orphaned components. The documentation refers to it running ‘periodically’. Another way, when removing panels from view, is to register an event handler on ‘hide’ to remove the panel from its parent. This will ensure that the new panel is completely in view and the old one is completely hidden before destroying it. This ensures that the HTML elements are removed at that time, leaving no DOM clutter.

// when it is hidden, remove it. 
item.on('hide', function(obj){
     parent.remove(obj, true); 
});

localStorage

By far the easiest way to store data is to configure your model objects to use ‘localStorage’ to store your data.  This is a simple key-value store which Sencha Touch will maintain for you.

app.models.User = Ext.regModel('User', {     
   fields: [
     {name: 'name', type: 'string'},
     {name: 'id', type: 'int'},
   ],
   proxy: {
     type: 'localstorage',
     id: 'ap-users'
   },
});

There is a bit of overhead for each model, as Sencha Touch will maintain a record for the total amount of records, a record that lists the records by id, and each record will be a JSON string. The biggest thing to be aware of when using localStorage is that there is a space limit per domain that cannot be circumvented. This is 5Mb, or 2.5M characters as the encoding is UTF-16. The only way around it is to use another data store. There were two relatively straightforward options, that will require an interface between PhoneGap and Sencha Touch:

- ‘indexedDB’ – it is essentially SQL for a web application (usually implemented with SQLite). Sencha Touch does not currently have a proxy for this option, but is should be easy enough to create a compatible one. Each one is also limited on a per-domain basis. The trick here is that you can circumvent this storage limit by opening up the meta info about the databases in <application path>/Library/WebKit/Databases/Databases.db.  There is a table called Origins, with a column called ‘quota’ which you can change to whatever you want.  You will need a SQLite adapter for Objective-C to open it.  Which begs the question …

- File System – because we have access to the file system through PhoneGap, we can store whatever we want, which could mean making an adapter to Sencha Touch and having it serialize data to the File System, exposing NSManagedObject to JS or creating our own SQLite DB. Either way this will require work to create a JS component that speaks to the native code and implements the proper API for Sencha Touch.

Orientation

Orientation was down right broken with Sencha Touch and PhoneGap when I started. I believe things are improving but it still doesn’t work completely. It was still necessary to add some code to fire the event into PhoneGap. There are a few pull requests open with this feature but it hasn’t been resolved.

UPDATE: this was fixed May 17th 2011

Swipe

There was a desire to implement a ‘swipe to delete’ functionality that was similar to iOS, where when you swipe on an element in a list view it reveals a delete button which can be used to delete the element.  Tapping anywhere else closes the delete button. The trickiest part of implementing this functionality was the order of events on the body. For some reason there was an additional ‘touchstart’ event being fired right after the swipe event.  It required ‘double registering’ event handlers that only activate once. 

var elements = Ext.select('.task-delete', item).first();
var slideAnim = new Ext.Anim({from: {'width': '0px'}, to: {'width': '24px'}, autoClear: false});
slideAnim.run(elements);
//put an event handler on the body to find out when a tap happens outside of the box
//because the swipe event will actually fire a touchstart event, we register two single use
//callbacks. This gets the trick done, but I wish there was a better way.
Ext.getBody().on('touchstart', function(){
   Ext.getBody().on('touchstart', function(evt, html, config){
      //don't set the width if we are actually touching a delete icon
      if(!evt.getTarget('.task-delete')){
          elements.setWidth(0);
      }
   }, this, {single: true});
}, this, {single: true});

Another little caveat here is that testing this on a Windows based machine resulted in different behaviour, with respect to the firing of events.

Form ‘Labels’

Sometimes you want to display information in a form that isn’t editable, but shouldn’t look disabled either. I accomplished this by subclassing an Ext.form.Field, and styled it to look like a label. It’s not perfect yet, and needs some of the styling extracted to be more generic.

Ext.form.LabelField = function(config){
  Ext.form.LabelField.superclass.constructor.call(this, config);
};

Ext.extend(Ext.form.LabelField, Ext.form.Field, {
 isField: true,
 value: '',
 renderSelectors: {fieldEl: '.x-form-labelfield'},
 renderTpl: [
   '<tpl if="label">',
   '<div class="x-form-label"><span>{label}</span></div>',
   '</tpl>',
   '<div class="x-form-label x-form-labelfield" style="width:70%; text-align:right"><span>{value}</span></div>',
 ],
 setValue: function(val) {
   this.value = val;
   if(this.rendered){
	  this.fieldEl.update('<span>'+ val + '</span>');
   }
   return this;
 },
});

Ext.reg('labelfield', Ext.form.LabelField);

Animation on Hidden Components

Do not use animation on hidden components. Check to see if they are hidden before making the call.  Not doing so can lead to all sorts of visual artifacts. Floating elements also seem to cause problems sometimes, so experiment with turning animation on/off.

Picker

Pickers seemed to, by default, expand to fit the screen which can look a little weird on an iPad. I want something much more like a UIPopover.  I accomplished this by adding these properties to an Ext.Picker object:

width: 175,
enter: 'right'
enterAnimation: {disableAnimations: true, type: 'fade', duration: 100},
exitAnimation: {disableAnimations: true, type: 'fade', duration: 100},
stretchX: false,
stretchY: false,

This is useful when clicking on a text field and wanting to show a Picker. The animations are disabled due to graphical glitches (see #8 above).  All you need to do now is a ‘showBy’ call and the picker will be in a popover.

Stores – sync(), stale data, events, filtering

Stores are confusing at first because they seem to be like an ORM but because they are designed mainly for AJAX interaction, they try desperately not to hit the data store. This can be a little frustrating when using local data storage. The data can become stale in a store if there is another store accessing the data at the same time. As well, events aren’t passed to stores that don’t perform the operation.  The result of this is you can’t listen, globally, to see if anyone makes a change to the data.  So the next question is: why don’t you just create one store and use it everywhere? There are two reasons: the filters are applied per store, adding filters to a store could affect elsewhere in the code if you are using the same store. The second is that when you query associations, they will return new stores with proper filters set. Completely by-passing any sort of global stores that may have been set up for that model.  This is convenient but makes it tough to track changes to stores.

MVC – events

This was one of the areas I found hardest to wrap my mind around. You are building a mobile application using web technologies. In this case, there is no backend server component. So it is no longer straight forward to determine where the model-view-controller separation lines should be. Should the view know about adding an object? Should the controller display popovers? Should you pass just the ids to different controller methods or the actual object to save time?

Sencha Touch provides models, views, and controllers which help organize the application into separate components. The controllers are really geared for a web application so they do things like keep track of history, and a URL path which is not required in a native mobile application.  So the best way that I found to structure the application was very similar to a server side response, where in a controller method you would load the data from a store or use the whole store, pass it to the view(s), register for events on the view, then display the view. The views would implement either custom events or bubble up events on their child controls to indicate to the controller to perform actions.  Views were responsible for all their children and displaying any additional screens when prompted by the controller. This results in a well structured MVC application which is easy to change and easy to trace the flow of events.

iPad Launch Screens

iPad launch screen support in PhoneGap is completely non-existent at the moment and needs improving. Currently PhoneGap will display the Default.png after the application has finished loading until the WebView has finished loading. What happens on the iPad is a little image in the top Left is displayed.  Fixing this was a little more complicated as it required re-working the UIImageView that was created, and ensuring that it responded to orientation changes.

UINavigationController

There is no UINavigationController or UISplitViewController available for SenchaTouch. You will have to create your own. This isn’t too hard, because there isn’t a lot of functionality desired. You will need an array to push/pop to, toolbar to display, and any other functionality to manage the addition or removal of views. I created a custom UISplitViewController type control that allows pushing of {list, panel} pairs and managed the animation, and removal of the components when popped. Separating the managing of displaying the views helped encapsulate that functionality and left my controllers to just create the desired views and push them on to the main view.

Ext.util.Observable.capture

This is a great tool for debugging events from components that inherit from Ext.util.Observable. Found out about it in a video that Sencha posted to their Vimeo channel. All you have to do is hook up a logging function and you can inspect the order and parameters of events that roll in.

Ext.util.Observable.capture(new Ext.Panel(), 
   function(){console.log(arguments);})

May 17 2011

Native vs. HTML5 Mobile Development

Codesta previously published a blog article of mine about my experiences developing a non-native app using Sencha Touch and HTML5 tech. It can be found here: Native vs. Mobile HTML5.

Recently we were approached by a company that wanted to equip their field teams with tablets to improve their productivity and decrease the amount of manual data entry. The approach was to have a custom mobile application built to sync to a server backend. The hardware requirements for the mobile device were not fully specified, due to product immaturity at the time, so to leave the greatest room for flexibility it was decided to go with a ‘native’ cross-platform HTML5 solution.PhoneGap and Sencha Touch were chosen to realize these goals and help increase developer productivity. What follows are an introduction to the technology, the technical limitations and the experiences that I had developing a non-trivial app for this relatively unexplored technology.

The experience coding native iOS applications is quite different than HTML5 applications. There are many similar concepts but getting started with these technologies is still a bit of a ramp up due to learning the frameworks, APIs, and some of the quirks involved. No Objective-C or Java experience is necessary to develop for PhoneGap, as it is all taken care for you. However, having the experience is very useful to develop additions and debug problems. Hopefully the gap between native and HTML5 apps will reduce overtime as it matures. As always with new technology, there are some hiccups that get in the way of making it a truly painless experience. Learning from these lessons and contributing back improves the ecosystem making these applications a viable alternative.

There are two ways to develop HTML5 apps for mobile devices: deploy the application on a remote server which users access with mobile Safari, or wrap the application with a native wrapper. Trying to effectively emulate native apps with HTML5 and Javascript is out of the question. It probably will never be completely possible. But will it be close enough in certain areas that it doesn’t matter? Perhaps, and that is the key area for these technologies. Providing a mobile interface quickly and cheaply to your service is becoming an increasingly desired attribute for site owners. Having a mobile prototype that works now, helps validates a company’s strategy. Being able to quickly iterate on ideas until something clicks with users is key in today’s fast changing business climate. 

Sencha Touch is a Javascript framework targeted to mobile devices. It can run in either the mobile Safari or a native web control in an application. It is similar to other JS frameworks and has similar concepts to Ext, as it is made by the same company. Ajax, data models, UI widgets, controllers, JSON parsing and other features are all provided by the framework to allow you to integrate with server side components and store data locally. Sencha Touch was chosen as it was the most mature framework that had reasonable support for tablet based UIs. jQuery Mobile was still in alpha 1 at the time, and as it had already missed the target date getting to that stage, I couldn’t see it being ready in the timeframe that we were targeting. However, jQuery Mobile development is continuing at an exciting pace and will have to be re-evaluated when starting a new project.

PhoneGap puts the ‘native’ in ‘native HTML5’.  It is native wrapper that displays your HTML5 & JavaScript in a web component locally on the device and provides an API that tries to be consistent across multiple mobile devices. The APIs that it provides to the JavaScript code go a long way in accessing native features; elevating a local web app above just a simple HTML page. APIs are provided to the JavaScript environment by intercepting special URLs, parsing them for parameters, executing native code and then calling back into the JavaScript environment. This approach has a number of issues, some of which are limitations of the environment:

  1. Execution will be slower than just straight native code. But you should already have expected this.
  2. Poor tooling support.
  3. The ‘hacky’ feel of this interception method.

Sencha Touch and PhoneGap are excellent pieces of software, providing a framework and the tools necessary. On paper, their inherit promise to write once and run everywhere provides a compelling alternative to maintaining a separate code base for all platforms. Centralizing logic, one code base, less ramp time, and using well known technologies are all very desirable qualities to the decision makers and even to developers themselves. And, for the most part, it achieves these goals at the expense of others, which I’ll talk about in part 2. One of the most desirable qualities is a reduction in development hours and associated cost. Unfortunately there are still areas which time investment needs to happen; bug fixing and testing must still be done a device by device basis, as there are numerous differences and quirks between the WebKit implementations on mobile devices and the PhoneGap APIs exposed depend on the platform.

The goals and priority of the project have to be explicitly stated up front so that you can evaluate the options realistically. Saving money and time at the expense of usability is a common trade-off in software development. Using these tools is no different, careful consideration of what you are gaining and loosing will make sure that you are not caught unaware. Next time I’ll go more into a breakdown of the features and the comparison between native development to help anyone weigh the options and decide if the trade-offs are worth it. Overall the mobile HTML5 environment is evolving at a rapid pace and many products are starting to step in to provide frameworks and tools to developers wanting to develop in this environment.

Nov 29 2010
Looking mighty empty here.
— Eric Boyer

Page 1 of 1