Blog

    Happenings and acts of geekery.

Mobile app for the 2013 Ivy+ Annual Fund Conference

We have heard a lot of positive feedback on the mobile app we built for the attendees of the 2013 Ivy Plus Annual Fund conference hosted by Cornell University this week. We are happy to help!

Released for iOS, Android, and mobile web users, the app offers up-to-the-minute schedule information, an attendee listing, and "the Stream" - a combined twitter and in-app message feed. One feature that attendees won't see but will appreciate is the ability for the app to function even when the network isn't available.

The app is integrated with Cornell Connect (using the Harris Connect REST API) to pull both schedule and attendee information over for display. A separate mobile app admin console manages any on-site registration needs, schedule updates, broadcast announcements, and most importantly check in activity.

Tracking who has actually showed up for the event is as simple as a search and a touch for the welcome desk staff using the check in feature. It's turned off for this event, but the app does have the ability to inject "so-and-so just checked in!" messages to the Stream too.

And of course, no app is complete without a dashboard - ours shows the 'hot spots' of content and gives us a good idea of which platforms we should target for future projects. The mix does shift from one group to the next - far more than we ever expected.

If you think an app like this would be useful for your alumni or professional group event, please drop Steve a note. We'll be happy to demo everything for you and discuss the various options available to you.

CounterMarch reinvents registration and check in for University of Delaware Alumni Weekend 2013

We are excited to announce that we have signed an agreement to provide registration and self check in services for the University of Delaware Alumni Weekend 2013!

UD will use our robust Reunion registration software to power a simple, user friendly advance registration process, comprehensive administrative and reporting tools, and a self-service on-site check in process guaranteed to reduce wait times. Registrants will receive a confirmation email containing a QR code that they'll scan from their phone or printed page, receiving their name badge and tickets for the overwhelmingly popular Mug Night and other events they registered for in seconds. We expect to practically eliminate the lines at check in thanks to this new system.

The registration system will be a "one stop shop" for the 40-50 events happening across campus during the weekend, standardizing the registration data and simplifying administration across the board. This system will also include the option to make your annual fund gift to the designation of your choosing at the time of registration, encouraging participation in more ways than one.

We're delighted to work with our newest client and look forward to a much improved registration cycle for Alumni Weekend, happening May 31-June 2, 2013!

CASE District 2 Conference Sponsor and Speaker

We are proud to be a silver sponsor of the CASE District 2 conference this March.

As part of our sponsorship, CounterMarch is donating the use of a system for the speakers to share their presentations with attendees. Rather than handing out business cards and emailing bulky files around, speakers will be able to upload them to our system for easy discovery and download by attendees.

The URL for the system will be shared with all speakers and conference attendees closer to the event. We hope that everyone attending the conference finds the service easy to use and helpful in their professional development.

Company founder Steve Rittler will be co-presenting two sessions at the conference as well.

Tools and Tactics for Volunteer Engagement will be presented with Lori Kennedy and Jessica McMullan from Lehigh University. Our talk will detail how we got our arms around volunteer engagement. We'll talk about how we defined a sustainable, scalable process in partnership with groups across campus and existing volunteers. We'll share our goals, how we're doing against the plan, what we measure (and how), and what's next. You'll leave this session both excited and prepared to implement your own volunteer engagement process regardless of the size and scope of your advancement shop.

Modernizing Reunion Management will be presented with Kim Barrett from Cornell University. This talk is unique in that we're using the complete redevelopment of Cornell's Reunion management system as our functional example of how to manage a project with multiple independent stakeholders on an unrealistic timeline (with, as you might expect, an immovable deadline!). We'll discuss the challenges we faced (institutional, personal, and technical), how we decided to "train as we go", actively including volunteers in the development process, and the tremendous successes (some unforeseen) this project yielded. Registration and onsite activities have never been smoother! You'll leave equipped to take on a huge project with the right mindset and useful tools the moment the session ends.

We're excited to contribute to advancing the profession and share our expertise with everyone in Pittsburgh. See you in March!

Cornell Mobile App Using the Harris Connect API

Last January we released a mobile app for the Cornell Alumni Leadership Conference that was extremely well received by alumni and staff alike. The app (CALC 2012 iOS | CALC 2012 Android | CALC 2012 Mobile Web) featured the conference schedule, session surveys, attendee listing, and "the Stream" - an aggregation of tweets and attendee-shared messages in one consolidated conversation view. The app was heavily used by about a third of the attendees.

The 2013 version of the app was designed to meet three major objectives: integrate with registration, improve responsiveness, and overhaul the user interface. Here are the resulting apps: CALC 2013 iOS | CALC 2013 Android | CALC 2013 Mobile Web.

Integration with Harris Connect

Last year we employed the usual lowest common denominator approach to integration: spreadsheets. That introduced a whole host of issues including timeliness of data, proper formatting of the sheet itself, and adding another human to the data transfer process. We knew we had to do better this year because we really wanted to highlight the sessions that people had registered for in the conference agenda. Extracting relational information like that in spreadsheet form wasn't going to end well.

Cornell uses the Harris Connect system for their alumni online community and event management needs. Recently Harris annouced beta availability of their OpenAPI that would allow us to get access to the registration data automatically. A "beta" label doesn't scare us, so we plowed right ahead with it thanks to the help of the ever-awesome Kim Barrett (Cornell Connect project manager), Eric Slosson (Harris Client Relations Manager), and Irwin Horowitz (Harris Technical Architect).

Much to our delight the API allows us to retrieve the data in XML or JSON format - JSON please! A couple quick hours of work and we we're all set. The process of loading and checking the attendee and schedule data went from several hours to just a couple minutes, eliminating all timeliness, formatting, and human factors in the process. Now that we have the integration components built we can very quickly build mobile apps for other Cornell (and other Harris user) events very quickly (and cost effectively)!

What did we do with this data? The app has a session bookmarking feature that we were able to preload for every attendee. We used those bookmarks to also show the next session the attendee was scheduled to attend on the home screen of the app.

Improve Responsiveness

The CALC app caches a lot of data locally so that key information is accessible to the attendee no matter what kind of data coverage the event venue has. This approach requires us to think carefully about how we load, store, and refresh that data on the device.

One thing we are never particularly happy about is any noticeable delay between user interaction and an update on the screen. We use PhoneGap and jQuery Mobile for our applications, which means our apps are essentially browser-based within a native wrapper. As a consequence, we're heavily dependent on the performance of the mobile device browser and its javascript engine. We invested a considerable amount of research time testing and timing several possible solutions for the "touch delay" on both old and new devices on both Android and iOS. In addition, we reevaluated the use of jQuery Mobile (which survived the cut!) and our client-side templating solution (which was moved from the comatose jQuery Templates project to Handlebars). Adam also built a much improved read-through cache mechanism reducing both data traffic (good for battery life) and rendering time. The result was a much faster appliation that felt closer to native than the 2012 edition - with the added benefit of being supported by a cleaner, more modular codebase.

Overhaul the Interface

Last but certainly not least we wanted to break free of the stock-standard "this is supposed to look like an iOS application" default look and feel that jQuery Mobile provides out of the box. From the first sketch to the final implementation we wanted to make the first screen to be both useful for information delivery and simple to "fat finger" your way around.

We also dropped most of the jQuery Mobile list views and replaced them with leaner, meaner HTML and CSS, wrapped in the really nice pull-to-refresh iscroll plugin. Not only was this a nice usability improvement, but it also gave us better rendering performance.

In Conclusion...

We met the three objectives, building a much-improved core under a better performing user interface that was used by even more attendees than last year. Our admin dashboard told us so in real time!

PhoneGap 1.x, Google Analytics, and XCode 4.2

So I was working on a PhoneGap app for the Lehigh/Lafayette Challenge and realized it might be wise to include an analytics package so we'd have something to work from for next year. A quick Google search yielded me this blog post on including Google Analytics in a PhoneGap app.

The problem is, the instructions are outdated...and the package docs on github are also out of date. Commence headdesk. Bang. I don't know the first thing about Xcode or Objective-C, so this was quite an adventure!

Here's what you need to do to use this in an iOS PhoneGap app (jQueryMobile 1.0RC2, PhoneGap 1.1, Xcode 4.2) so that the plugin works with the PhoneGap 1.x plugin architecture. Guaranteed to work as of right this second with these versions. I'm sure it'll break again soon :-)

  • Go get the code from the PurpleCabbage Github site
  • Drop GANTracker.h, GoogleAnalyticsPlugin.h, GoogleAnalyticsPlugin.m, and libGoogleAnalytics.a in the Plugins folder in your Xcode project. Right click on Plugins, Add Files to , select 'em, make sure "Copy items into.." is selected, and click "Add".
  • Modify GoogleAnalyticsPlugin.h to comply with the new plugin architecture
  • /* OLD VERSION - will not work */
    #import <Foundation/Foundation.h>
    #import "PhoneGapCommand.h"
    #import "GANTracker.h"

    @interface GoogleAnalyticsPlugin : PhoneGapCommand<GANTrackerDelegate> {

    }

    /* Replace all of that with this */
    #import <Foundation/Foundation.h>

    #ifdef PHONEGAP_FRAMEWORK
    #import <PhoneGap/PGPlugin.h>
    #import <PhoneGap/NSData+Base64.h>
    #import <PhoneGap/JSON.h>
    #else
    #import "PGPlugin.h"
    #import "NSData+Base64.h"
    #import "JSON.h"
    #endif

    #import "GANTracker.h"

    @interface GoogleAnalyticsPlugin : PGPlugin<GANTrackerDelegate> {

    }

  • Drop the GoogleAnalyticsPlugin.js file in the www folder for your project. I put my stuff in a subdirectory (assets/js) just to keep things neat.
  • Don't forget to include it in index.html with a script tag!
  • <!-- google analytics -->
       <script type="text/javascript" charset="utf-8" src="assets/js/GoogleAnalyticsPlugin.js"></script>
  • Now setup your app startup scripts to initialize the GA code too
  • /* Wait for PhoneGap to connect with the device */
    function onLoad() {
    document.addEventListener("deviceready", onDeviceReady, false);
    }

    /* PhoneGap is ready to be used! */
    function onDeviceReady() {
    window.plugins.googleAnalyticsPlugin.startTrackerWithAccountID("UA-YOUR-GOOGLE-SITE-CODE");
    /* i like to throw a startup event in there just to know how many launches we get */
    window.plugins.googleAnalyticsPlugin.trackPageview("startup");
    /* other startup code here */
    }
  • You'll probably also want to track every jQuery Mobile "page" view too. I just hooked in to the 'pageshow' event. You can track pageviews (which I'm clearly faking here) and "events" (better explained here).
  • $(document).ready(function(){   
       /* track page views */
       $('div').live('pageshow', function(event, ui){
          var pagename = $(this).attr('id');
          window.plugins.googleAnalyticsPlugin.trackPageview(pagename);
          return true;
       });
    });
  • This will save you some hair pulling: the Android PG/GA plugin uses a js method named "trackPageView". The iOS version is named "trackPageview". Yeah...case sensitivity strikes again. Save yourself hours of screaming by watching for that.
  • Now we have to make PhoneGap aware of the plugin. This is the undocumented part.
  • In your /Resources/PROJECTNAME.plist file, open up the Plugins area and add a new item. The name is "googleAnalyticsPlugin" (which is the name of Javascript object). The value is "GoogleAnalyticsPlugin" (which is the name of the Obj-C object). This took a ton of trial and error.
  • Last step: allow the app to reach external hosts. You could list each one individually, but I wildcarded it for this project. Under ExternalHosts in that same PROJECTNAME.plist file, add a line, and set the value to "*". You can see it in the screenshot above.

So from this point forward, you should be able to see pages being logged in Google Analytics from your mobile app. Hope this helps!

PhoneGap, FileTransfer, and ColdFusion

I like PhoneGap. Really. But I bashed my head on this for a while so if this saves you the headache, you're welcome!

The app I am working on uses the Camera API to capture an image and then submits it to a back-end service for inclusion in an online photo gallery. Pretty simple.

When you capture the image, you have two choices for how to handle the data:

Camera.DestinationType.DATA_URL
Camera.DestinationType.FILE_URI

The problem with DATA_URL is that the cameras on mobile devices are getting to be too darn good. That DATA_URL is a Base64 encoded string that can very quickly run you straight out of memory. Therefore, you are strongly encouraged to use FILE_URI instead which is simply a pointer to a file on the device file system.

How do you then get this file moved up to the server? Use the File API's FileTransfer object.

var imageURI = PATH_TO_FILE_AS_GIVEN_BY_CAMERA;

var options = new FileUploadOptions();
options.fileKey="file";
options.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
options.mimeType="image/jpeg";
/* ColdFusion barfs if you don't set this */
options.chunkedMode = false;

var params = new Object();
params.formfield1 = 'send other data along for the ride';
   params.formfield2 = 'using more fields like this';

options.params = params;

var ft = new FileTransfer();
ft.upload(imageURI, "http://YOUR_URL_HERE/SOME_FILE.cfm", win, fail, options);
/* don't forget to create functions for win and fail conditions */

The key line here is options.chunkedMode = false;. From what I could tell by reading Ben's blog post , ColdFusion simply can't handle chunked form data. Two hours of searching and evaluating alternatives...and then I noticed this option.

So...lesson learned. Base64 will not only drag your app down but probably crash it as well. FileTransfer (sans chunks) is the way to go.

How I got started with ColdFusion

Steve Bryant had a great idea that the entire ColdFusion community should post about how they got started with ColdFusion on the same day. Count me in!

I started my first job after earning my computer engineering degree as a software test engineer in the summer of 1999. If only I knew how boring that would be! Three months in to that job I went to my boss and asked to be put on a different project - it was that bad!

A couple days later he took me down to the first floor of our building and introduced me to Sam Raimond. Sam was an interesting guy - he had an insatiable curiosity for all new technology. While he wasn't really a programmer, he would mess with just about any new piece of software that came out. In the late 90s, there was an awful lot for him to play with!

Sam was the project manager for the document management system (DDCS) used by a rather large organization up the street from us - NASA. DDCS was a combination of IIS, WebDBC, and Xerox DocuShare running on some ancient Gateway servers - far from sexy, but absolutely mission critical. My boss knew I could build websites, though I hadn't done anything more than HTML and some really basic javascript. Sam didn't seem bothered by that. He handed me the box with ColdFusion 4 server in it, told me he didn't know CFML, and that he was pretty sure nobody else in the company knew it either. My new project: take the four programs that comprised the DDCS system and rewrite them in ColdFusion. Challenge accepted.

The first module took me three months to build. The second, third, and fourth combined took three weeks. Even if we had set out an aggressive rebuild schedule we wouldn't have expected this to come together so quickly. Needless to say, ColdFusion made a lot of people we reported to very, very happy!

I learned how to do this by spending lots of time on the (at the time) Allaire forums and regular attendance at both the DC and Baltimore ColdFusion User Groups. Sam was insistent that we never miss a meeting of either group, even though I was extremely reluctant to go at first. The thing is, once you meet the CF community any reluctance to go as a "newbie" falls away quickly. I remember being immediately put at ease by the friendly people who were there. Some of the stuff people presented was amazing! I'd always come back to work with a whole bunch of ideas and even less time to build them.

One thing I've never forgotten is that it was because of the welcoming, fanatical ColdFusion community *and* the power of the platform that I have been able to enjoy the career that I do. Macromedia recognized the value of the community when they acquired Allaire and Adobe saw it too when they bought Macromedia. No matter the corporate parent the server has seen tremendous improvement from one version to the next with a corresponding jump in the number of things that developers can do easily. I've made a pretty darn good living and a few really great friends thanks to my ColdFusion skills and intend to continue using it as long as the platform keeps evolving (I'll keep the friends regardless).

Interesting footnote: I've known Rob Brooks-Bilson for (omg) 10 years now. Today, thanks to his "How I got started" post, I learned that our first projects were both conversions from WebDBC to ColdFusion. Ironic, indeed.

Philly Merge Conference: July 15th, Philadelphia

Got an entrepreneurial itch? It's almost impossible to avoid if you're in the business of creating things. The creation part is simple (relatively speaking)...but building a business around it? Not quite as straightforward.

Philadelphia is home to a rapidly growing entrepreneurial technology culture. That excites those of us who work in tech in the Philadelphia area, and we want to help it grow by creating a conference for people with a dream to meet people with the means to make that dream a reality – whether that need is for business support or technical development skills.

This conference is called Philly Merge and will be held on Friday July 15 at Jon M. Huntsman Hall at the University of Pennsylvania. By bringing together local developers with entrepreneurs we intend to share success stories, establish a forum for peer education, strengthen the local developer network, start new businesses and have fun while doing so. The entire purpose of the conference can be simply stated as "get started."

We'll have sessions on topics both legal and technical, financial and inspirational -- ending the day with a panel of VC folks who will share with us what they're looking for in both a company and a pitch. We've stocked the speaker list top to bottom with local people who "get" Philadelphia, have done these things themselves, and know what it takes.

It's our belief that you'll finish the day with a feeling of "I can do this" - and you'll have a great idea of what it's going to take to get started. For us, this is a "get started" effort too - we'd appreciate your support, feedback and participation!

So why not sign up today? It's only $29!

Register Today! 


Philly Merge is sponsored by Wharton Computing, Adobe Systems, Future Media Concepts, Chariot Solutions and CounterMarch Systems

Fun with Twilio, Part 2 (The Results!)

Last week I wrote up a summary of a project I threw together that leveraged ColdFusion and Twilio to enable the reunion crowd to vote for their favorite performance.

Well, everything went off without a hitch on Saturday! In fact, I spent an hour on Friday night changing how the system worked to cater to both smartphone and "dumbphone" users. I promised a writeup on how it worked and what the results were, so without further delay...

Promotion

We printed up about 1000 stickers - just plain old Avery mailing labels - with two ways to cast your vote. First was via SMS to the number printed on it. The second way was for those "in the know" who understood what a QR code was.

The parade commentators plugged the voting in the warmup before the parade started, between acts and again at the very end. This definitely helped our cause - there was nothing else to pay attention to during those times, so the exclusivity of the promotion really stood out.

We handed out the stickers to as many spectators as we could along with each of the reunion classes while they were lining up for the parade. After a quick explanation of what was at stake (a new award!), some classes eagerly set to work with their phones. They loved that there was something to do while they were waiting for the parade to start.

This was the extent of the promotion. For an app that came together really quickly, there wasn't time to get word out in advance -- and honestly it wasn't necessary. This was a very "event specific" thing that required no prep on the part of the participants.

How It Worked

There are two ways to cast a vote: SMS or using the QR code. The original idea was to use the QR code to launch your text messaging app with the appropriate class year already entered as the body of the message (we'd print unique stickers for each class). You can't do that on iOS - only Android. We then realized that was dumb - if you were going to text, it's easier to just do that rather than fiddle with a barcode reader. There had to be something nicer for the barcode crowd.

So Friday night around 11:30 I sat down with Dreamweaver CS5.5, jQuery Mobile and ColdFusion to toss together a really quick web-based mobile app. One hour later it was skinned, released and running. One hour!

Results

All told, reunion attendance was around 1000 people. There were unregistered spectators and probably some unregistered guests floating around too. Out of this crowd, we collected more than 1200 votes! Roughly a tenth of them were submitted using the mobile app. The URL was not public, so the QR code would be the only (easy) way in. At a couple cents per SMS, this was good, cheap fun - and nothing went wrong.

Lessons Learned

  • PEOPLE LOVE TO PARTICIPATE! Everybody wanted to know the results before they were announced. They were really amused when I pulled out my phone and showed them the graph of results...up to the second
  • QR codes look really scary to people who don't know what they are
  • QR codes CAN be safely dressed up! I took advantage of an excess of error correction code built in to the QR structure and "Fireworks-ed" in the Lehigh shield. It looked less intimidating.
  • Make sure auto refresh was active for your Twilio account (thankfully mine was...though my heart stopped when I got an email in the middle of the parade from them!)
  • The alumni band will, upon finding out they lost, make plans to hack the vote next year. Bring it.
  • Do not send an acknowledgement for every vote - you'll hit a limit pretty quick.
  • Call-to-vote? Entirely possible with Twilio. Might be fun to add it just for fun!

One key enhancement for next time: Screens at the reviewing stand showing the real time voting totals. With ColdFusion, Blaze DS and Flex this is maybe another hour of work.

The Award!

The result was a decisive win for the class of 1976. Their re-enactment of Rocky was entertaining, colorful and energetic...and they certainly weren't shy about voting for themselves!

For their efforts, they were the inaugural winners of the Stephen C. Rittler '99 Reunion Parade Fan Favorite Award!

Fun with Twilio

With the rush to build full-fledged mobile applications for smartphones, sometimes we forget that there are still a lot of people on...shall we say...dumbphones. So what do you do when you want to interact with as many people as possible? You drop down to the lowest common denominator: voice and SMS.

Lehigh University's annual reunion features a parade of classes through the heart of campus. Every class does a performance for a theoretically impartial panel of judges who take the reaction of the crowd into account during their voting. Awards are given, like the "Best Alumni Band Award" (given to the one and only Marching 97 alumni band) and the Petty Flag (for the overall best performance). This year, we wanted to add more crowd interaction to the mix.

The idea was to bang out a quick "vote via SMS" app so everybody watching the parade could vote (as many times as they like) for the class they thought did best. The powers that be have decided to add an award based on the results too.

Enter Twilio! The best part: it's stupid simple to build this kind of app using their REST API. First thing was to sign up for a number - it's only $1/mo. I then set the "SMS request URL" to a page on my server.

Then on the page I pointed it to, I set up code to handle the text that was being sent in. The entire message is passed in in form scope as the "body" attribute with all the other attributes (sender phone number and their account locale information) sent along too.

<cfif structKeyExists(form, "body")>

   <cfset classYear =    reReplace(form.body, "[^0-9.]", '', 'all') />

   <cfif classYear is not "">
      <!--- add to vote total --->
      <cfset v = entityNew('vote') />
      <cfset v.setVote(classYear) />
      <cfset v.setFrom(form.from) />
      <cfset v.setFromCity(form.fromCity) />
      <cfset v.setFromCountry(form.fromCountry) />
      <cfset v.setFromState(form.fromState) />
      <cfset v.setFromZip(form.fromZip) />
      <cfset v.setTimestamp(now()) />
      <cfset entitySave(v) />
</cfif>
</cfif>

Then, I send an acknowledgement message to the sender:

<cfhttp url="https://api.twilio.com/2010-04-01/Accounts/{REALLY_LONG_ACCOUNT_ID}/SMS/Messages" method="post" username="{YOUR_USERNAME_IDENTIFIER}" password="{YOUR_ENCODED_PASSWORD}">
         <cfhttpparam name="From" type="formfield" value="XXXYYYZZZZ" />
         <cfhttpparam name="To" type="formfield" value="#form.from#" />
         <cfhttpparam name="Body" type="formfield" value="The class of #classYear# thanks you! Feel free to vote as many times as you like." />
      </cfhttp>

That's it! Already they're thinking of other uses for this kind of tool. I'll be sure to post again on Monday with the writeup on how it went.

More Entries

About the blog