An interesting read on December 20 from the 9th Circuit Court of Appeals on how terms of service should be displayed on websites and in apps:
Users are put on constructive notice based on the conspicuousness and placement of the terms and conditions, as well as the content and overall design of the app. Id. at 1177. For example, courts will not enforce agreements where the terms are “buried at the bottom of the page or tucked away in obscure corners of the website,” especially when such scrolling is not required to use the site. Id. (citing to Specht v. Netscape Commc’ns Corp., 306 F.3d 17, 23 (2d Cir. 2002)). Similarly, courts decline to enforce agreements where the terms are available only if users scroll to a different screen, Hines v. Overstock.com, Inc., 668 F. Supp. 2d 362, 367 (E.D.N.Y. 2009), complete a multiple-step process of clicking non-obvious links, Van Tassell v. United Mktg. Grp., 795 F. Supp. 2d 770, 792-93 (N.D. Ill. 2011), or parse through confusing or distracting content and advertisements, Starke v. SquareTrade, Inc., 913 F.3d 279, 293 (2d Cir. 2019); Nicosia v. Amazon.com, Inc., 834 F.3d 220, 237 (2d Cir. 2016). Even where the terms are accessible via a conspicuous hyperlink in close proximity to a button necessary to the function of the website, courts have declined to enforce such agreements. Nguyen, 763 F.3d at 1178-79.
Huuuge’s app is littered with these flaws. When downloading the app, the Terms are not just submerged—they are buried twenty thousand leagues under the sea. Nowhere in the opening profile page is there a reference to the Terms. To find a reference, a user would need to click on an ambiguous button to see the app’s full profile page and scroll through multiple screen-lengths of similar-looking paragraphs. Once the user unearths the paragraph referencing the Terms, the page does not even inform the user that he will be bound by those terms. There is no box for the user to click to assent to the Terms. Instead, the user is urged to read the Terms—a plea undercut by Huuuge’s failure to hyperlink the Terms. This is the equivalent to admonishing a child to “please eat your peas” only to then hide the peas. A reasonably prudent user cannot be expected to scrutinize the app’s profile page with a fine-tooth comb for the Terms.
Accessing the terms during gameplay is similarly a hide-the-ball exercise. A user can view the Terms through the “Terms & Policy” tab of the settings menu. Again, the user is required to take multiple steps. He must first find and click on the three white dots representing the settings menu, tucked away in the corner and obscured amongst the brightly colored casino games. The “Terms & Policy” tab within the settings is buried among many other links, like FAQs, notifications, and sound and volume. The tab is not bolded, highlighted, or otherwise set apart.
Here is the full decision: Decision.
When Google App Engine was released I attended Google’s sprint in New York City excited at the possibility of being able to host python applications without having to deal with the hassles of maintaining a server. I spent the week after the sprint rewriting a Plyons project so that I could host it on App Engine.
The rewrite left me extremely frustrated:
- I had designed the application with a relational database in mind, and couldn’t stop myself from thinking about the data in a relational way. After the rewrite, the database layer of my project was both ugly and inefficient.
- Beaker (the session and cache middleware that ships with Pylons) was extremely buggy when interacting with GAE. (I would log into my application from Firefox, open up same application with Safari, and it would show me as logged in even though Safari didn’t have any cookies set)
- Since the pylons project rolled its own user management / authentication system, I wasn’t taking advantage of Google App Engine’s ability to interact with Google Accounts.
This was almost a year ago. I didn’t look at Google App Engine again until a train ride a few weeks ago. I was in the process of tutoring a friend for the LSAT exam and I wanted him to memorize a few terms for the exam. I urged him to make a set of flash cards so that he could regularly quiz himself. I searched online for a website that would allow me to easily create and share flashcards. I found a few, but none that saved a revision history of the edits made to a card.
My goal was to create an application that allows users to log in and create and edit flash cards. I had another requirement: I did not want to spend more than two hours on the project. Unfortunately, from past experience I know that writing code for a user management system with passwords and email confirmation can take a week in itself.
I figured that this would be a good time to try and use Google App Engine to see how easy it would be to integrate an application with Google Accounts. It turned out to be much simpler than I had originally expected. There are only three function calls that you have to know about when integrating Google Apps within your app:
- When your app wants to log a user in: users.create_login_url(“/”) where the string passed in is the URL that you want Google to redirect the user to after they login.
- To check to see which user (if any) us logged in, your app can use the users.get_current_user() command.
- When your app want log a user out: users.create_logout_link(“/”) where the string passed in is the URL that you want Google to redirect the user to after they logout.
And that is it! In five minutes I had a user management / authentication system for my application (with CAPTCHA, confirmation email, and forgot password functionality that is available with every Google account). With the user management part of the application taken care of, the rest of the application was extremely simple and straight forward to create.
For me, the biggest win in using Google App Engine is not the ability to send my application into the cloud (and thus not have to worry about scaling and system adminitration). Rather, I love not having to build a user management system every time I create a new application.
The code for the flash card application lives at Github.
The application itself runs here.
I love the Planet feed aggregator, but I hate managing it via a text configuration file. I created a WordPress plugin that automatically creates a Planet configuration file from the links that are stored in a WordPress database. Every time a link is updated, deleted, or created, a new planet configuration is generated.
For more information on how to install and configure the plugin, visit the plugin’s homepage. The source code for the plugin is hosted at wordpress.org.
A few weeks ago my employer helped the NY State Senate parse the MTA budget information into a machine searchable format. (The MTA originally published the budget as a PDF.) To parse the PDF I used a utility called pdftohtml to first convert the PDL into an XML document. I then used the python library lxml to convert the document into a set of csv files. The results of this labor can be seen on TOPP’s data site.
Soon after I published this data, however, I was told by a number of people that the data would be more useful if presented in another format. At first I just started creating a bunch of command line python scripts that would suck in these csv files, and spit them out in different formats. I quickly realized that I could accumulate these scripts and create a quick and dirty web application.
Over a few train rides I created an application called DataIO, and today, I finally got a chance to upload it to Google App Engine. The application is pretty simple to interact with; instructions are located on its front page.
Continue reading “DataIO”
For some reason it took me a while to figure out how to compile a flash plugin for Flowplayer. Here were the steps that I took to finally get it working:
Continue reading “Compiling a Flowplayer Plugin on Mac OS X”
I had promised to clean up and release some of the plugins that went into creating Streetsblog.net. Here is the first one: Geo Blogroll.
Inspired by a friend I am going to create list of new years resolutions:
- Learn a functional programming language. Any suggestions on which one to try out first?
- Make fewer mockups and write more code. Web frameworks these days allow for such quick development that I think I would be more productive if I just skipped the Omnigraffle/Photoshop step.
- Learn how to engage in effective Test Driven Development. I have heard of the benefits, but I have never seen a good tutorial on how to do this effectively. Maybe I just need to look a bit harder.
- Don’t think about work while I am playing and don’t think about playing when I am working. Focus is always good. I am sure at least one person will be happy with this resolution.
- Make a daily to do list with no more than three items. This was suggested by some lifehacker post and it seems like a great idea.
- Recycle more at home. I recycle consistently at work because we have containers for different type of containers, but since I do not at home, I get lazy more often.
- Contribute more back to the open source community. I have written a bunch of code recently that I haven’t yet checked in to a public repository. I have to make contributing back a higher priority.
Recently I tried exporting some posts from one WordPress 2.5 blog to another WordPress 2.5 blog. The import worked perfectly, but then I realized that I had forgotten to import one of the posts. Rather than doing to the whole import again, I decided to just import the post that I had forgotten. Unfortunately, WordPress brought over all of my categories again, leaving me with duplicates of all of my categories. Ugg.
I wrote a small python script that takes a wordpress export file and strips out information about categories and tags. It’s a pretty simple script, but I will share it anyway: script
A few coworkers and I launched Streetsblog.NET yesterday. The website is actually a vanilla install of WordPress working in conjunction with a vanilla install of Planet with a bunch of custom WordPress plugins. I will release the plugins when I get some time to clean them up.
At TOPP we have been considering switching Streetfilms over to using FlowPlayer. There are number of advantages to using FlowPlayer:
- It is released under a GPL3 license.
- It has a neat new jQuery interface.
As I learn more about the advanced features of FlowPlayer I will blog about them, but here is a quick introduction.
Continue reading “Quick Introduction to Flow Player”