Why I Quit Gowalla
April 26, 2011
Let me start by saying that I deeply respect the team at Gowalla and actually envy their fun work environment and exceptional level of talent. This post is to address the service they’re building, not the folks behind it.
Up until today, I had been a member of Gowalla for something like a year. I was immediately drawn to the service because of its ability to locate me, find the business I was present at and commit a check in. The iPhone and web interfaces are simple and beautifully constructed.
I quickly invited most of my friends who proceeded to sign up, making the experience even more entertaining. I checked in everywhere I went, from gas stations to my polling place. I took pictures, reported issues, and even gave feedback on the Gowalla GetSatisfaction page. I would consider myself to have been an active member of Gowalla.
Unfortunately, that was the peak of my experience and it was a slow downhill from there. There are several key places where I feel Gowalla is lacking and keeping themselves from being sustainable for the long run.
Incentivized Check-ins
I’m not sure I ever really understood what the driving force was behind me wanting to check-in everywhere I went. Most of the time the actual check-in was the end of the road. Phone away and on with other things. I liked being on the Leaderboard at the few places I checked into regularly, but that wasn’t permanent or overly hard to attain.
Locations, check-ins, and items need some incentive behind them (whether physical or virtual) to really be interesting after the newness wears off. There are plenty of ways to implement incentives, but I don’t think anyone (Gowalla, Foursquare, etc.) has really gotten it right.
Community
One of the first things I noticed when joining Gowalla was that basically none of my friends were on it yet which seemed reasonable since it’s a newer start-up and isn’t widely adopted. I invited quite a few people and even gave several friends a face-to-face walkthrough on why they should check it out (sidenote: shouldn’t there be a pin for accepted referrals).
Having a few people I knew well on the site made it much more interesting, but it never became more than, “Oh, he’s at Taco Bell again?!” or “I guess he just made it to work”. There is no sense of community and tends to feel more like a “people tracker” than networking medium.
Friends
In an effort to build community and interact more with the service, I added most of the people I follow on Twitter as friends on Gowalla. It quickly became obvious, however, that doing that is less than desirable.
I found I’m not all that interested in people’s check-ins when they live 2,000+ miles away. I’m also not interested in places I’ve never heard of or have no plans to visit. Most of the time I just turned off their Push Notifications, but then I had to ask myself what was the point of following them in the first place?
Split Attention
Almost any time I met with someone for lunch or coffee, I made sure to get my check-in settled before jumping into conversation. It didn’t take long to realize how this was a totally ridiculous practice. Why was I de-prioritizing my friends and family so that I could let the world know where I was?
The same question could easily be asked of Twitter, Facebook, and SMS, but the reason I am OK using those is because I feel like there is a community of people (see “Community” above) on the other end with which I’m sharing my life and continuing to grow our relationships. That’s not so much the case for me with Gowalla.
Purpose
Checking in to find that you’ve received a new item is definitely fun. I also really liked exchanging items at a location and tracking the history of where they’ve been. So, now what?
I can see collecting items and putting them in my archive as a goal. Most of the time, however, I just dropped them somewhere for someone else to pick up. I never felt satisfied with item collection alone being the end goal of my Gowalla experience. I liked finding new locations and becoming the creator, but what’s the incentive? Eventually, I earned a pin or two for creating Spots, but is that it? I never once looked to see what pins other people had earned. Pretty consistently I found myself needing more direction on what to do next. What’s the next achievement? What am I getting out of this? What do you want from me, Gowalla? If the service can be whittled down to sharing where I’m located, I’ll elect to simplify and just add my location to a Tweet.
This post is in no way meant to flame Gowalla or the great people that work there. I just need more from the service to justify continuing to invest my time in it. I think there are loads of opportunities (of which I’m sure they are working on some of them), but for now I value simplicity and privacy just a bit more.
Life with iPad
April 19, 2011
Link: Life with iPad
Rick Stawarz (@rickstawarz) wrote an excellent pair of posts about his experiences with the iPad as a laptop replacement. We definitely have some overlap in our “needs”, but he also brought to light some other great points I missed.
Making the iPad into a “Laptop Killer”
April 18, 2011
I’ve been using my iPad 2 for just over a month. I pulled the trigger and bought it with the expectation of using it primarily for reading (Twitter, RSS, Instapaper, Bible, Kindle). While that is mostly true to this point, I find myself wanting to use it for more. I find myself wanting it to replace my MacBook Pro, but can’t quite pull the trigger. Here’s why:
The Inability to “Create”
I’m not looking to edit Photoshop files and, frankly, I don’t even want to edit videos with the new iMovie app. Those things should be done on a computer with a mouse and keyboard, but I feel there are a few significant barriers blocking the transition from consumer to creator on the iPad.
Emailing
As I mentioned in my last post, it’s not possible to do something as simple as add an attachment to an email within the Mail app. That’s just not acceptable from a device that would replace my laptop.
Printing
Let’s be honest, there is no printing support for the iPad.
I know there’s AirPrint, but should I have to buy an HP printer? I already have a Brother printer that I love. I understand that Apple doesn’t want to mess with the thousands of different printer drivers out there (Trust me, I used to be a Linux-only guy), but isn’t that just a bit of a cop out?
There are also printing apps in the App Store. I haven’t tried them myself, but the reviews are very mixed. I have to believe it’s a bit of a kludge if it may require me to install software of my desktop computer to make it work.
I don’t print a ton even with my desktop or laptop, but when I need to it’s usually for a good reason and I need it now (concert tickets, receipts, meeting notes).
No Personal Storage Area / Home Folder
I would like to have a home folder that serves as a place for file storage. There are currently various apps that facilitate that storage (both locally and in the cloud) like Photos, Dropbox, Evernote, and GoodReader, but why not natively?
Common Data Storage Area
I’d like to have an area where I can dump a file and not require an Internet connection to access it. This folder would also serve as a common storage area where other apps could source files (much like Twitter and the Photo Library do now). For example, I’d like to download an image from a website and upload it to Twitter or send a stored Word document to someone through Skype.
Replace the USB Drive
When I plug in my iPad to a computer, it should mount like a USB drive. Loading or unloading the iPad should be as simple as drag and drop…no iTunes required, please.
This would allow a person to work on the file at their desk, load it up on the iPad at the end of the day, compose an email on the train ride home and send it off as an attachment. That easily matches the convenience of a laptop.
User Accounts
Although not at the top of my list, the iPad should have user accounts. Here are some cases where it would be nice:
- Perhaps my wife doesn’t want her apps arranged in the same manner as I do. Maybe she doesn’t want an app to show up on her screens at all. My wife uses the iPad entirely differently than I do.
- Two different people usually have different email accounts and mingling the two gets messy and confusing. I’d prefer separate instances of Mail.
- Maybe I don’t want to get work emails over the weekend, and likewise don’t want to be distracted at work with Push notifications from Word with Friends that remind me of the slaying Chris Bowler is administering.
- I’d like to play Angry Birds and beat all the levels myself, but am forced to share with our friends 5 year old who is giving me a run for my money.
- All apps with personalized logins require using shared accounts or logging out and back in each time a new person uses the iPad. Way too much hassle!
Is Apple telling me that my wife and I both need our own iPads? Perhaps. At their current price point I can get three or four iPads for the price of one MacBook, but then of course I’d have to buy all the apps twice. “They’re only $0.99,” you say. Unfortunately, that doesn’t hold much weight with the guy that will make a U-turn for the gas across the street that’s 1 cent cheaper per gallon.
The bottom line is that I really enjoy the iPad and it’s great for most of what I do. I feel like for Apple to take it to the next level and rightly deserve the label of the “go between” device it has to function somewhat more like a laptop and slightly less like a smartphone.
I’d really enjoy hearing your thoughts and responses on Twitter. Hit me up @gstjohn.
Sending Email Attachments in iOS
April 15, 2011
The bottom line is it’s not possible. At least natively.
I discovered this unfortunate circumstance this morning as I was trying to reply to an email with a screenshot from my iPad. I could have sent it from Photos, but that would have required me to write a new email and the recipients weren’t in my address book. I would also prefer to keep the screenshot associated with the original email for context. No such luck, though.
What about sending non-photo attachments (like a document)? Also, not possible. There is an app called GoodReader that (among other things) will allow you to send files as email attachments, but no such functionality is built into iOS. Do I really want another app to enable such a simple process? And for $4.99?
I love my iPad for 101 reasons, but how can we really call the iPad a “go between” device or “laptop killer” if it can’t natively do something as simple as send an email attachment. I think this discovery just reinforces for me even further that the iPad is a consumption device and isn’t suited for creation/productivity.
Hollywood fears Netflix
March 8, 2011
Link: Fearing iTunes-Like Domination, Hollywood Plots Netflix’s Downfall
Hollywood is scared of Netflix. They saw what iTunes did to CD sales and they want to stop the same from happening to them.
Why is the Entertainment Industry So Out of Touch?
Hollywood is the land of progressive thinking, but when the consumer evolves how they want to receive their media, it’s all freaking out and plug-pulling. How did this mindset work out for the music industry?
If it didn’t cost my wife and I $25 to get into the theater, I would see more movies (let’s not even discuss how many movies are total duds once you get in). “We had to raise the prices because our films are being pirated!” True, and I grabbed a torrent or two back in the day, but Netflix has provided a way for me to legally watch a movie with a price tag I can actually bear (same goes for Rdio and my now dwindling MP3 collection). I’ll even accept the fact that a lot of the instant streaming content is older films and Netflix throttles shipping discs. Why can’t Hollywood see what their consumers want and not only jump on board, but help expedite the process?
Companies that have had their hand in the cookie jar for a long time need to keep innovating and reinventing themselves to stay relevant or the consumer will eventually just leave them behind. Wake up, Hollywood!
A Great Method for Modeling Git Branches
February 16, 2011
Link: A successful Git branching model
This is probably one of the best tutorials I’ve seen on how to run a successful Git repository. Bravo!
Modeling Our Business Before Taking the Plunge
February 9, 2011
Link: The Magic Spreadsheet or Let’s Talk About Money
Noah Stokes shares on his blog about how we modeled Bold on “paper” before jumping in together. Planning is a very important exercise in business that I feel like a lot of creative-types are more than willing to overlook. Hopefully you find it to be just as helpful for your business.
Extracting Attachments From Emails With PHP
February 8, 2011
Yesterday I wrote about how to read emails with PHP, but I want to dig a bit deeper and discuss another part of the My Slow Low project that needed tackling: Extracting attachments from emails with PHP. For the purposes of this post, I will be specifically discussing file attachments, not HTML inline attached files.
This project was executed with CodeIgniter 2.0 so there are a few libraries and helper functions used that will not be available in other frameworks or with straight PHP, however, their functionality can be pretty easily replicated.
function email_pull() {
// load the Email_reader library from previous post
$this->load->library('email_reader');
// load the meals_model to store meal information
$this->load->model('meals_model');
// this method is run on a cronjob and should process all emails in the inbox
while (1) {
// get an email
$email = $this->email_reader->get();
// if there are no emails, jump out
if (count($email) <= 0) {
break;
}
$attachments = array();
// check for attachments
if (isset($email['structure']->parts) && count($email['structure']->parts)) {
// loop through all attachments
for ($i = 0; $i < count($email['structure']->parts); $i++) {
// set up an empty attachment
$attachments[$i] = array(
'is_attachment' => FALSE,
'filename' => '',
'name' => '',
'attachment' => ''
);
// if this attachment has idfparameters, then proceed
if ($email['structure']->parts[$i]->ifdparameters) {
foreach ($email['structure']->parts[$i]->dparameters as $object) {
// if this attachment is a file, mark the attachment and filename
if (strtolower($object->attribute) == 'filename') {
$attachments[$i]['is_attachment'] = TRUE;
$attachments[$i]['filename'] = $object->value;
}
}
}
// if this attachment has ifparameters, then proceed as above
if ($email['structure']->parts[$i]->ifparameters) {
foreach ($email['structure']->parts[$i]->parameters as $object) {
if (strtolower($object->attribute) == 'name') {
$attachments[$i]['is_attachment'] = TRUE;
$attachments[$i]['name'] = $object->value;
}
}
}
// if we found a valid attachment for this 'part' of the email, process the attachment
if ($attachments[$i]['is_attachment']) {
// get the content of the attachment
$attachments[$i]['attachment'] = imap_fetchbody($this->email_reader->conn, $email['index'], $i+1);
// check if this is base64 encoding
if ($email['structure']->parts[$i]->encoding == 3) { // 3 = BASE64
$attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
}
// otherwise, check if this is "quoted-printable" format
elseif ($email['structure']->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
$attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
}
}
}
}
// for My Slow Low, check if I found an image attachment
$found_img = FALSE;
foreach ($attachments as $a) {
if ($a['is_attachment'] == 1) {
// get information on the file
$finfo = pathinfo($a['filename']);
// check if the file is a jpg, png, or gif
if (preg_match('/(jpg|gif|png)/i', $finfo['extension'], $n)) {
$found_img = TRUE;
// process the image (save, resize, crop, etc.)
$fname = $this->_process_img($a['attachment'], $n[1]);
break;
}
}
}
// if there was no image, move the email to the Rejected folder on the server
if ( ! $found_img) {
$this->email_reader->move($email['index'], 'INBOX.Rejected');
continue;
}
// get content from the email that I want to store
$addr = $email['header']->from[0]->mailbox."@".$email['header']->from[0]->host;
$sender = $email['header']->from[0]->mailbox;
$text = ( ! empty($email['header']->subject) ? $email['header']->subject : '');
// move the email to Processed folder on the server
$this->email_reader->move($email['index'], 'INBOX.Processed');
// add the data to the database
$this->meals_model->add(array(
'username' => $sender,
'email' => $addr,
'photo' => $fname,
'description' => ($text == '' ? NULL : $text)
));
// don't slam the server
sleep(1);
}
// close the connection to the IMAP server
$this->email_reader->close();
}
I tried to comment the code above as best as possible to convey what it is I am doing with the information. This code is a method within a Controller, but I’ve only included the attachment extraction method of the class for this post.
For more information and to credit those I’ve learned from, please check out David Walsh’s post on Retriev[ing] Your Gmail Emails with PHP and IMAP as well as Chris Hope’s post on Extracting attachments from an email message using PHP IMAP functions.
Reading Emails with PHP
February 7, 2011
Last week I got to do a fun little side project which we called My Slow Low. The site is a simple photo collection of slow/low carb meals for those that are out of ideas on what to eat, but want to stick to their diet. While conceptualizing how we would build the site, the idea of emailing in photos came up. We didn’t want the hassle of account management and were trying to go for a more “mobile capable” option. This was my first time coding for IMAP with PHP and I figured some others could use a jump start from what I’ve learned.
PHP already has a nice IMAP extension which needs to be installed and enabled before going further. The core functionality is all there, but the specifics on how to use it aren’t necessarily all that clear.
Here’s a PHP class I put together to do some basic operations on an IMAP Inbox. It’s a bit tailored to this project, but could be easily revised to fit other needs or extended to be more full featured.
<?php
class Email_reader {
// imap server connection
public $conn;
// inbox storage and inbox message count
private $inbox;
private $msg_cnt;
// email login credentials
private $server = 'yourserver.com';
private $user = 'email@yourserver.com';
private $pass = 'yourpassword';
private $port = 143; // adjust according to server settings
// connect to the server and get the inbox emails
function __construct() {
$this->connect();
$this->inbox();
}
// close the server connection
function close() {
$this->inbox = array();
$this->msg_cnt = 0;
imap_close($this->conn);
}
// open the server connection
// the imap_open function parameters will need to be changed for the particular server
// these are laid out to connect to a Dreamhost IMAP server
function connect() {
$this->conn = imap_open('{'.$this->server.'/notls}', $this->user, $this->pass);
}
// move the message to a new folder
function move($msg_index, $folder='INBOX.Processed') {
// move on server
imap_mail_move($this->conn, $msg_index, $folder);
imap_expunge($this->conn);
// re-read the inbox
$this->inbox();
}
// get a specific message (1 = first email, 2 = second email, etc.)
function get($msg_index=NULL) {
if (count($this->inbox) <= 0) {
return array();
}
elseif ( ! is_null($msg_index) && isset($this->inbox[$msg_index])) {
return $this->inbox[$msg_index];
}
return $this->inbox[0];
}
// read the inbox
function inbox() {
$this->msg_cnt = imap_num_msg($this->conn);
$in = array();
for($i = 1; $i <= $this->msg_cnt; $i++) {
$in[] = array(
'index' => $i,
'header' => imap_headerinfo($this->conn, $i),
'body' => imap_body($this->conn, $i),
'structure' => imap_fetchstructure($this->conn, $i)
);
}
$this->inbox = $in;
}
}
?>
A fair amount of this is self-explanatory or commented inline, but I will go over the inbox() method because it is the core functionality. The IMAP inbox is much like an array with a numbered key starting at 1. In the inbox() method, I store that index so that the email can be moved, deleted, or read again later.
Next, the header is stored with the function imap_headerinfo(). This pulls down an object from the server containing information like the Subject, From: address, To: address, and text encoding type.
Using imap_body(), the body text of the email is retrieved. What’s returned isn’t overly clean as it’s just the raw body with boundaries included (see: multipart messages). If the received email is in HTML, there will be a plain text and HTML version included. It’s certainly possible to parse through this data like any email client does, but it’s definitely a little bit messy.
Lastly, ‘structure’ is retrieved with the imap_fetchstructure() function. This is very important if you are trying to access attachments as I was with My Slow Low. In my next post, I’ll go further into the details of saving an attachment from an email and share some more about how I implemented the email processor for My Slow Low.
Update: I’ve posted the follow-up to this article on extracting email attachments with PHP.
Bettween
February 4, 2011
Link: Bettween | Easily Track and Share Twitter Conversations
“Dang it, I know I talked to @sam_h about that a year ago, but what were the details?” This question led me to Bettween. Easily retrieve conversations you’ve had on Twitter, or filter down to conversations between you and another user. Remember that it was in the last 3 months? You can filter conversations that way too.
