Monthly Archives: June 2011

Revamping an image: Google+

The fact that Google called their new project “Google+” was a smart move. People aren’t going to say “I shared that link with you on ‘Google Plus.’” They’re going to say “I shared that link on Google.” People refer to Buzz by its name just like they refer to Facebook by its name; those are identifiable and easy enough to say. But the awkwardness and even silliness of the sound of “Google Plus” disinclines people to refer to it that way. They’ll just call it Google.

This means that if Google is successful in this all-or-nothing, last-ditch effort to get into social, their brand name will signify both search and social. Had they given this project just another brand name like Orkut or Buzz, it wouldn’t impact Google’s identity nearly as much.

Google+ will either save the company’s anemic social track record, or it will forever seal their reputation of incompetence in the social scene.

Goodreads Across the Web

This week I released a Kynetx app I’ve been wanting to write for a long time: Goodreads Across the Web.

This app displays an “Add to Goodreads” button to book pages on Amazon.com and Barnes & Noble. It also displays the average user rating from Goodreads. Clicking on the link takes you the detail page on Goodreads for that particular edition of the book, so you can add it to your shelves.

I make use of the Goodreads API and a few simple Kynetx rules. For Barnes & Noble, I had to use dialoguing to get the ISBN, since they don’t put the ISBN in the URL like Amazon does.

You can get this app for the KBX here.

Are you a Goodreads user? What else do you want this app to do?

Using Google Apps Script with Kynetx

I posted a few weeks ago about aggregating stats for TomatoFlix or any other Kynetx app. I set up an endpoint on ktest.heroku.com to let me see those stats.

But that only gives me aggregate data. What if I want to observe trends over time? For example, is the popularity of the Redbox website changing? What is the most frequently used movie website during the weekend? On week nights?

In order to get that kind of information, I need a way to retrieve and store my stats regularly. It turns out that Google Apps Script can do just that. In this post, I’ll show you how to combine a time-based trigger that runs an Apps Script function. Then I’ll show you how to make a RESTful endpoint to expose the stats from your app. Finally, I’ll mention how to combine the two to get the data we want.

Starting with Apps Script
First, go create a new spreadsheet in Google Docs. Then, create a new script (click on Tools -> Script Editor -> Create a new script). That takes you to the Script Editor. Name the function whatever you want and have it do something simple. Here’s an example that increments cell A1′s value every time is is called:

Now set up a trigger to run that function every minute. From within the Script Editor, go to Triggers -> Current Script’s Triggers. Then click on “Click here to add one now.” That will give you a screen like this:

Have it run your function every minute. Now leave the spreadsheet and come back in a few minutes to see that it worked.

Setting up a RESTful endpoint to expose data
I wrote about using Kynetx to create RESTful web services a couple months ago. We’re going to use the same principles here, so go read that post if you haven’t already.

In the case of TomatoFlix, all the stats are tracked using app variables. Implementing this web service endpoint is then a simple matter of writing a rule that responds to a webhook event, creating a JSON object with the data, and returning it. For this example, I’m using Sam Curren’s webhook module to make things easier. That means I need to add one line to the meta block:

use module a8x157 alias webhook

Here’s the rule that does all the hard work:

That produces a JSON document that lives at this URL: http://webhooks.kynetxapps.net/h/a163x53.dev/stats.

Tying it all together
Now we’ve got the pieces we need. Go back to the Google Docs spreadsheet you created. Add another sheet. Set up a header row that has one column for the date/time and one column for each of your data points. For TomatoFlix, it looks like this:

Now create a new script (or a new function in your existing script). This one is going to be more complicated than the previous one, but not by too much. Basically we’re going to be appending rows instead of changing the same cell every time. Additionally, the data we put into those cells will come from a UrlFetchApp.fetch() call to the webhook URL of the rule we just wrote. Here’s what it looks like for TomatoFlix:

The last piece is to set up a trigger to call that function. I’m having mine run every day at 3 AM.

That’s it! Now your stats will be nicely aggregated into a spreadsheet, and you can crunch numbers to your heart’s content.

Conclusion
I’ve never used Google Apps Script before today, but I’m very impressed with the power it gives you. I’m glad to see that they have native event handlers and triggers, which is what made this all possible.

Triggers also make it easy to raise KNS events on a schedule, something that has been on the developer wish list for a little while now.

What cool ideas do you have for using Google Apps Script with Kynetx?

Using web events to do dialoguing

My last post was about using an HTML form with KRL to get data from a page and submit it back to the server. This post describes another method for doing the same thing, but this method is less vulnerable to interference from other code on the site.

I’m writing an application that runs on Facebook. Unfortunately, Facebook munges HTML forms somehow, making it impossible to do dialoguing the way I explained last week. This new method does not depend on the behavior of HTML forms, so it works great even on a JavaScript-heavy site like Facebook.

Here’s the process:

  1. Like before, we use jQuery to get the information we want. This could be data extracted from the page, or it could be input provided by the user.
  2. Using JavaScript and the KOBJ object, we get a reference to the ruleset that we want to handle the data.
  3. With that reference, we raise a web event in the ruleset and pass along the data we collected from the page.
  4. The ruleset then handles the event and returns any appropriate directives.

In my application, I’m asking the user for a first and last name to search the BYU directory. I put an HTML form on the page to collect that information. Then there is a JavaScript function that runs when the user clicks the “Search” button. That function pulls the data out of the form and raises an event with that data to my ruleset. Here’s how that part looks:

(You’ll also notice that I’m setting the page_params.kynetx_app_version to be "dev". This is due to the way I structured my application; I need that so that I don’t have to deploy the ruleset every time. You probably won’t need to do this, but read more here if you’re interested anyway.)

The rule that handles the event is very straightforward. Here’s what it looks like:

The function listnames() is defined in the global block, but it’s not really relevant to this discussion.

Combining client-side processing with server-side in KRL

My next post describes another way to do dialoguing. If this method doesn’t work for you, try that one.

Sometimes you need a Kynetx app to have access to the data on a page in the user’s browser, but you can’t do all the processing you need on the client side. Here’s an example:

I wrote an app a while ago that took the BYU Bookstore’s “MyBooklist” web app and let the user look up those books on Amazon to compare prices. (The Bookstore has since added this functionality to its own website, so I’ve discontinued my app.) I needed the ISBN numbers from the page (client-side), but then I needed to look them up in the Amazon product API (server-side, with KRL). I wrote some JavaScript and a special rule to allow me to extract that data from the page and send it back to the Kynetx servers so I could process it.

The process is pretty simple. It goes like this:

  1. The first rule emits some JavaScript that will use jQuery to get the appropriate pieces of information from the page.
  2. The rule also puts a hidden form on the page. The script adds the extracted data into fields on that form.
  3. When the script finishes collecting the data, it triggers the submit action on the form.
  4. All the while, this first rule has been watch()ing for that form to be submitted.
  5. The second rule handles the event that gets raised (through watch()) when the form is submitted.
  6. That rule extracts the data from the form and does any necessary operations with it (API lookups, storage, etc.) and takes appropriate actions.

Here’s a simplified version of the first rule from the BookComparison app:

You’ll notice we’re creating a series of input elements all with the name isbnList[] and some subscript. This will come in useful in the next rule, where we can foreach over those inputs. Here’s the second rule:

This second rule handles a web submit event with the ID of the form given in quotes. Thereafter, it iterates over each of the ISBN numbers returned from the form. In the original app, this involved looking up the ISBN number in the Amazon API and then returning the price data back to the page (via an action like replace or append.)

Can social media influence be measured?

And even if it can, does it matter?

Holden Page says no. And more and more I’m starting to agree.

Empire Avenue and Klout are two services that measure your social media activity and attempt to attach a meaningful number to it. Klout wants to call it a measure of influence. The problem is that, as Tom Ohle put it, “Until someone can measure sentiment, trust and reputation, influence isn’t measurable.” (Tom works at Empire Avenue.) He mentioned to me that Empire Avenue started out with the same goal, but then decided to turn it into a game instead, since all the social media “metrics” out there can be gamed anyway.

It was interesting to hear the perspective of someone who works at Empire Avenue on the fact that this attempt to measure social media influence only produces a number that may or may not be useful. At least they have turned it into a game that is (as some would have it) fun to play. Klout hasn’t gone that far (although the +K button adds a human element to the mess of statistics).

In the end, I have to agree with Holden. Go ahead and measure my social media influence or activity or clout or whatever you want to call it. I don’t really care. I’m using social media for the sake of using social media, not because I want to be validated by a number.

(This post came out of a conversation I had today with Tom and Holden on Twitter. You can read most of it here.)

Simple stats for Kynetx apps

TomatoFlix has become rather popular lately. It runs on several different sites: Netflix (hence the name), IMDb, Redbox, Movies.com, and Fandango. I want some more detailed information about where people use it the most.

I decided to use app variables as simple counters. The idea for this came from a similar thing that Ed Orcutt did with HoverMe.

At the end of each rule, I added a postlude that increments an app variable identifying the website where it was run. The rule for Netflix now looks like this at the end:

Simple enough. Every time the rule gets fired on Netflix, that counter gets incremented.

Now to build a front-end for viewing the stats. I’m not too picky about this, since no one will look at them besides me. I use Randall Bohn‘s ktest Heroku app as the endpoint. Then I just build a simple notify() like this:

Now I just have to add a bookmark to my toolbar that goes to my app’s url on ktest.heroku.com and we’re set. (Sam Curren‘s Kynetx AppBuilder kTest Link app makes that really easy to find.) Here’s what it looks like:

And since ktest runs the dev version of the app as if it were a bookmarklet, I don’t have to add ktest.heroku.com to the dispatch block (which might confuse users downloading the app).