Some retail and grocery stores equip shopping carts with a device that requires a deposit before the cart can be taken out. This increases the cost of a shopping cart and is a hassle for shoppers to remember to bring change.
Humans are lazy and like free things. There’s the natural tendency to abandon the shopping cart instead of walking 10 meters to return it (hopefully you are better than this). People might also take the cart home but never bring it back the next time they go shopping. Sometimes it takes a little incentive for people to return their shopping carts,
In this situation I think the deposit works most of the time, but not so much because there is money involved per se. Convenience is something we want and it is a lot more convenient to return the cart so you can reuse your coin. Of course, there is still a minimum value for this to work (if all it took was a penny this might not motivate as many people).
There are some downsides to this system in that it is a hassle for shoppers but I think in practice if someone regularly visits a store, they will always come prepared. For one-off shoppers they probably won’t be buying much so there’s no need for a cart anyways. Thus this solution helps keep the carts tidy without much overhead.
Continuing the adventure of my move, I did a lot of furniture shopping. During university I never had to worry too much about furnishing a residence as I only spent at most a few months at a given place. However signing a long-term lease and purchasing furniture requires a lot more thought and responsibility. Furniture is expensive not only in terms of money, but also convenience since it is a hassle to deliver, install, and move. Mattresses and pillows are essential creature-comforts considering we sleep on them for a third of our lifetime which is why I believe thinking long-term is key.
Houses are built with different layouts and features, making it difficult to split costs and assign rooms. Here is one solution to aims to provide a fair split: Everyone bids on a room in round robin fashion (if they skip then they cannot bid on that room anymore). The highest bidder gets that room and the process continues with the remaining rooms/people. This works well since the sum of all the rooms should equal the price of rent, so when bidding on any room, you are able to know how expensive the sum of all the remaining rooms are. Thus the price of a room will continue to rise as long more than one person thinks that price a good deal.
Furniture can be expensive and the price tag by itself does not provide enough information to make a good decision. A different way to view the price is amortization, where the cost of an item is divided over several periods to better align the cost with usage. For example, an $800 couch can also be thought of as paying $80 per year, for the expected lifetime (say ten years). Putting it this way, wouldn’t you pay a fraction of a dollar per day to have a nice couch?
If multiple roommates are sharing furniture, what is the best way to also share the price? One idea is to have one owner per piece of furniture. This way it is clear who will be taking what when moving day comes. If costs are skewed, for example someone buys a $800 couch but the other only buys a $400 table, each person can pay the other a 15% “usage” fee for using each other’s furniture. This brings everyone’s expenses get closer to the average cost while maintaining the clear ownership.
At the showroom
Getting what you want
A common way for salespeople to greet customers is by asking “What brings you here?” This provides the salesperson valuable information about how likely they can make a sale, or the types of offers that might appeal. My initial reaction used to be to limit the amount of information I gave because I would then be the one holding the cards. However, after some experimenting and thinking, it is better to give clear specs of what I have in mind because now they have a better understanding of what I am looking for (who would have thought huh?). Nonetheless it is still important to verify the facts provided, for example asking rhetorically “New as in unopened?” can help ensure it is indeed what you think the salesperson meant.
Source of knowledge
Most people don’t shop for furniture very often so we don’t bother keeping up with the latest technologies or even the basic definitions. For example, what’s the best mattress for me, spring, latex, foam, or memory foam? Thus you should take advantage of their knowledge, getting immediate answers instead of wasting time scouring the Internet.
Sales (FOMO) tactics
The root of these tactics is how people react to uncertainty and deadlines. Even if a customer understands the different types of mattresses, how can someone determine for a given mattress whether it is right for them? Are you going to walk in a showroom in your PJ’s? How can anyone sleep with the lights on? How do you know if a mattress can maintain its original quality after a few years?
Difference in experience
One thing to be wary of is the difference in knowledge and experience of a salesperson. It is their job, they are probably good at it, but most importantly, they have all the time in the world. You don’t. I suggest noting down key facts, taking pictures of sales tags, and reading reviews/prices from online.
Salespeople get a bad rep for using pressure tactics like “i would be surprised if this remains in stock by the end of this week” to invite doubt and FOMO. Stores also use flash sales to create this urgency. Yes, you should definitely try to take advantage of the offer, however be wary as to whether the prices were first hiked up so that it looks like you are getting a good deal. Just remember that ultimately you are the one making the purchase and will be sleeping on it for a long time, so don’t settle for less. There are definitely salespeople who care about the customer, but at the end of the day they still need to meet their target and you need your sleep.
Bonus: How did Casper get popular without a showroom?
This requires a separate post but in short I think they are really good at marketing the product at the right audience online through a variety of targeted mediums. Their website is informative by highlighting individual features with simple graphics. Gorgeous pictures give light to what your life could be like by purchasing a Casper. The high prices in whole dollars provide the impression of respect and prestige. All of this is contributes to the branding and conveys a sense of quality and luxury.
Then, distinct market segments are targeted through different channels. For example, an ad on a podcast might be purchased where the host, whom the audience already has a connection with, reads an excerpt explaining the product and provide a promo code. Promo codes are important because it makes the audience feel special and provides FOMO because they don’t want the code to expire before they have taken advantage of it. This higher chance of purchase with a promo code is worth the slight decrease in margins and also means one more customer who can provide testimonials to friends.
I think they have done a really good job at marketing the product and I hope my analysis (not endorsement) doesn’t come off as being negative or judgmental.
1] DON’T FALL FOR PRESSURE TACTICS An old article yet still has some good tips
2] Boiler Room movie about pressure tactics. At least buying a mattress is tangible and offers a good night sleep
3] Did you know BOO stands for Boo October’s Over? Yes, it’s recursive
I recently moved to California from Toronto and wanted to share some of my experience with the roads and driving conditions.
California driver’s license has two tests: a written knowledge and a road test. Be sure to book an appointment or line up very early because the lines get packed real fast. Enterprise seems to be the only car rental company that allows their cars to be used for road tests (ask them to provide you a letter stating their car can be used). Instead of a parallel park (as with Ontario road tests), here you will be tested to pull beside the curb within a feet or so, then backup for a few car lengths. There’s no highway component and only one road test (Ontario has a two-stage graduated system).
San Francisco and the South Bay have some of the worst traffic I’ve seen. The traffic lights seem to be optimized for major arteries, staying green for up to a minute or more. This helps alleviate rush hour traffic (it’s also possible to drive many blocks at night without ever stopping).
This does require some adjustments to the roads. Many roads have concrete dividers in the center so cars cannot simply turn left onto small roads (since this will block traffic). Thus U-turns are very common and major roads usually have two long stretches of left-turn lanes to deal with the buildup. These left-turn lanes have their own designated lights (whereas in Ontario the majority of intersections allow cars to turn left on a green light when it is safe). Overall it does seem like both systems work well for each cities’ own specific set of traffic patterns.
Many highways in California use meters (essentially a traffic light) to ensure sufficient gaps between cars while merging during rush hour. The on-ramps are usually very short and sometimes several merges are required before actually entering onto the freeway. One difference I’m still getting used to is when the rightmost lane merges into the one beside it. In California, the dashed lines between these two lanes just disappear, whereas in Ontario the lane markings make it obvious that the right lane is about to be merged.
There’s a lot of room for improvement for any road infrastructure because no one wants to be stuck in traffic. A zipper machine is useful when the direction of traffic alternates depending on the time of the day. There’s a lot of unused space underground and above ground for cars to travel, but this solution is likely more expensive.
1] Here’s a totally unrelated video about driving
Normally when eating out I don’t venture into salad territory because it doesn’t seem filling to me. It wasn’t until recently that I discovered the world of salad bars - being able to add edamame, beets, carrots, grapes, fresh croutons, and more - was a game changer. Although it can be a bit daunting at first, the number of possibilities makes it hard to get old.
When I had salad at home it was a side dish and, since we don’t prepare on the scale of a restaurant, this usually consisted of plain lettuce, tomatoes, cucumbers — and maybe some walnuts when we felt fancy. This is not to say we don’t eat veggies, just that we never could make a salad that could stand up as a meal on its own.
Food is no longer just a means of survival; it is a way to celebrate culture, tradition, and creativity. Recipes are passed down generations, some relentlessly refined, others persistently preserved. New recipes are always being developed and even the definition of what constitutes a meal is always evolving (although not always for the better).
How did we get restaurants that specialized in salads? One possible explanation is that entrepreneurs experiment with new ideas and see whether it sticks. Salad bars weren’t a thing until only a few decades ago which mainly catered to the health-conscious population. Recently there has been a surge in supposedly healthy foods (remember the kale superfood?) but in a way, whether these foods are healthy or not isn’t important. Instead, the fact that people are making a conscious effort of trying to live a healthy lifestyle means they are more likely to pay attention all aspects of their life1. This trend has allowed more restaurants to offer their own take on the salad bar concept.
Specialization also occurs in companies. Early-stage startups must be competitive with only a handful of people. Co-founders often split the work with one focusing on business development while the other in technology. As the company grows, new employees are hired to further specialize in each area: salespeople, marketeers, mobile engineers, data scientists, etc. These new hires are more knowledgeable, experienced, and efficient at their specialization. Working together, they can build products that the same number of generalists cannot.
I first heard about this term a few years ago at Joist as a way to describe the depth and breadth of knowledge that someone has (vertical and horizontal lines of a T respectively). Here’s one description: being a domain expert (depth) means you can teach a whole university course, whereas having a lot of foundational knowledge (breadth) is like being able to give a hundred 5-min lightning talks.
It can be satisfying to be the domain expert as there’s a feeling of accomplishment and mastery. However being knowledgeable in a variety of areas makes it easier to communicate with others and can make it easier to grasp new concepts by relating to previous knowledge.
This article does a good job of explaining how the t-shaped concept is applied to teams. However, understanding our own self and determining the best way to improve can be challenging. We are all constrained by time and energy when deciding where to focus. One helpful tip is to only concentrate studying topics of personal interest because curiosity and passion is what keeps us going through challenges. On the other hand, trying new things, even just briefly, helps broaden your view. This might sound like a lot of commitment but remember, breadth of knowledge can be just dipping your toe in the water - at least now you know whether or not it is for you.
All of this is just to say that the base for a good salad starts with lots of greens, but it’s crucial to have a good mix of additional toppings for colour, texture, flavour, pizaz.
1 ↩ And now we can get special blue-tinted glasses because we look at our screens too much because we are so focused on specialization.
Special thanks to Jonathan Truong, Sneha Patel for reading previous drafts and providing feedback.
What this means for existing customers
I’ve released an update for Pronto Checker today which is likely the last. Just to be clear, the app will continue to work with this update. However because the app makes assumptions on how the PRESTO website is structured, the ability to check and refresh balance might not work in the future. Currently it still works and hopefully it continues to.
The reason for this decision was not made lightly. It’s been a while since the last update which was only necessary because of a major change on how the PRESTO website functions. Each time it changes requires a significant amount of time to update the app to continue working. Unfortunately there is no longer enough time for me to maintain the app anymore should another change occur, so I am letting everyone know in advance should another major change occur. In the meantime I’ve decided to make it free to download because I believe it is still useful to some people.
I’ve also taken this as an opportunity to discuss a few details about the development of the app for those interested. I’ve found behind-the-scene posts by other indie developers to be insightful and I hope this post provides interesting content as well. So beware! The rest of this post will be a lot more technical.
In-depth look behind the scenes
The PRESTO card supports the largest transit system in Canada, with over two million cards and a million taps every weekday. I’m a big supporter of public transit but my biggest annoyance was checking to see if I needed to reload money onto my card. I still remember talking to my coworkers whether creating such a single-purpose app was worth pursuing. Although it brings a lot of convenience to those who specifically face this problem, it certainly was a niche market (this would be an iPhone-only app, users can use the first-party website instead, auto-loading with credit card even removes the need for such an app). Nevertheless I had already hacked together a scraper so I thought how much more work can it be?
I knew I had to build some kind of scraper because unfortunately there is no public PRESTO api, not even a private one from what I could tell. There were two main ways of doing so: I could either regex parse the html page myself, or let the browser do it for me.
I chose the latter option because most programmers are lazy (plus a few other reasons, of course). This turned out to be a good choice because the process of checking a balance is split into two network requests: login and fetch card summary. To complicate things, I discovered that the webpages included some dynamic session token which meant that the app always had to query the homepage to get a fresh set of tokens just to login1.
Here’s a few other tidbits:
- An optimization I added was to use WKUserContentController (on iOS 11 and later) to prevent the browser from retrieving unnecessary content, thus reducing bandwidth usage and achieve faster page loading times.
- Since a user might have multiple accounts the app must be careful to use an ephemeral web session to clear cookies between logins.
- I was curious what I could add to make the app easier to use. I experimented with adding OCR so users don’t need to enter the 17 digits by hand. After adding some simple optimizations and being smart about the formatting of the card I got it working fairly reliably. The irony was that in early 2016 PRESTO redesigned their card slightly so that the card number was grouped together into four blocks (previously it was one contiguous string) which made the OCR less reliable.
All of this is done on the users device for several reasons. I did not want to store any of the information on a server because that would be a lot of onus on me to keep everything secure. It also meant a central point of failure in that all PRESTO would have to do to prevent this from working (if they wanted) was to block my ip2. The downside is that I would have to update the app should the PRESTO website change its structure, but I thought it was worth this trade off.
An important aspect of building reliable software is to be able to monitor it. The app anonymously reports when a user is unable to login, as well as other analytics to get insight. I chose not to use a third-party analytics library/service because it was overkill for what I needed. I didn’t want to bring along a blob of binary3 which I had no idea what else it might be collecting.
The way I sent my analytics was very straightforward. The app generates an anonymous unique id on first launch, then sends GET requests that includes the relevant information as part of the URL. I simply log those requests to a file and take a look every so often. Although there’s no fancy GUI, there just wasn’t much need.
Obviously this solution is too simple for the majority of use cases and it takes a lot of work to build additional features and scale out. However one thing I would point out is that there’s probably only a few key statistics that really matter in the initial growth stage. It’s important to identify and focus on surfacing that information to stakeholders in the easiest way possible.
One other technology that I would say is crucial to have once the basic features are completed is the ability to present service status information to user (eg. system downtime or app version out of date). This could be a simple popup or just presenting a webpage. Having such a system in place allows one to prepare for the unexpected.
I’ve been working on this project for a bit more than two and a half years and the cadence of work was very different from other projects I’ve worked on in the past. I mostly worked in short bursts where I focused on shipping a fix or adding a new feature, then left the project for several months. This provided for a few interesting observations.
The first time I jumped back into the project it took me a while to figure out how everything worked, almost as if I was reading someone else’s code. A bit of this was due to the gap in time, but a lot was also my relative lack of experience of software engineering back then.
This app is a prime example of basic separation of concerns, for example breaking the app into 1) core balance checker, 2) model/persistence of the balance, 3) UI to display balance. Thus I took the chance in my first rewrite to clearly mark the boundaries of each section of the app. I defined new
structs to make it more explicit about how different sections of the app could interact with each other, and tried to anticipate properties I would need in the future. A related problem I had to consider was the compatibility of the persistence layer between versions.
There was a benefit, however, to working on the app every couple of months. It was easier to identify the improvement of my ability to write quality code because in each subsequent reread I could always find places where I now had a better solution or way of organizing the code. It can be exhilarating to be able to rewrite some code in a way that avoids a hidden problem that my past self did not anticipate. However there’s also been a few times where I was pleasantly surprised that I had already handled a few special cases when rereading code. It’s also an interesting experience to see the progression of the Swift language. I started working on the app initially in Swift 1.2 and went through several migrations (remember 2.0?), seeing the language mature and get better over time.
Pricing, marketing, promotions
OK now onto the businessy side of things. Back then I listened to a few podcasts and followed indie developers who made their living by selling software. Creating apps is comparable to an investment (time is money right?). I thought it was a good opportunity to start with something small and build out a variety of different apps to provide a diversified income.
The feature I was bringing with this app is convenience and ease of use, which I hoped was enough of a reason for this to be a paid app. It would also be a lot easier to lower the price of an app than increase it4. And if I’m being honest, I would personally consider it a lot more impressive if I saw a steady stream of paid downloads with good reviews because this directly proves that people find it useful.
Initially after the launch I gave Google Adwords a try because I was curious what kinds of results I could get. I tried a variety of keywords, tweaking the landing page or linking directly to the App Store, etc. However I believe (it’s been a while) that I was barely breaking even because the CTR was pretty low. It was also more work than value when it came to testing different variations. I found it really draining to keep track of each hypothesis between testing (since it took time to see the results), or trying different layouts.
I also tried reaching out to press but didn’t get much response back. Thinking back there were several factors. Since this was a very niche app it’s hard to find the right customers when going to reporters, and reporters know this so it’s not worth their time. Furthermore, even if a person wants an app that can do this, there’s a high barrier due to the paid pricing. Realizing this, I tried making the app free in conjunction to cold-emailing. Eventually I got a link on the iPhoneinCanada blog.
Asking for reviews
When iOS 10.3 introduced an in-app review dialogue I knew immediately I wanted to add it in. At the time I didn’t have too many many reviews, which can be especially helpful to paid apps. This was in part because I didn’t add any invasive popovers because I wanted to create a pleasant experience for users. (Yet even if I did, I doubt the click-through rates would be high. The old process of leaving a review on the App Store was just too much to ask of users.)
There was a lot of small subtleties that I added to try to reduce user disruption and gain the best result. First the user must have successfully checked their balance a few times among several days. Satisfying this, the app then waits a few seconds after the next successful refresh so that the user can see their balance before they get prompted. This reduces the disturbance and hopefully results in the best possible result. Users will only see this popup at most once per version. Furthermore, the App Store now allows developers to keep the previous reviews after releasing new updates, reducing the need to continue showing these dialogues.
Process of sun setting
This brings us to the final topic of sun setting an app. I have a few vague memories of other apps doing this, but I’ve never really paid attention to the details of how other teams approached it. In my case however, the app will continue running as I am just giving everyone a heads up that no future app updates are planned.
I did debate if I should pull the app from the store. I didn’t want to continue selling it since I am no longer actively developing it. However at the same time I still see value in making it available to people. Thus I decided to make the app free to download instead.
Thanks for reading! If you have any feedback you can always reach me on Twitter.
1 ↩ the dynamic token requirement was added around july of 2016. Previously, without the requirement, I was able to include a cached version of the login page with the app, skipping the first request
2 ↩ if I was responsible for PRESTO website, seeing a single ip performing that many unique logins that would definitely be a red flag