a memo

Hits and Pings - Keeping Score

It's finally time to add some industrial-strength scorekeeping to Berylium in the form of hit counters and trackback support.

The Hit Parade
Hit counters keep track of how many views an object has gotten, both total and possibly within some period of time. They also track time of the most recent view.

I'm going to say that a view is recorded whenever the object is the $object in an HTTP request, that is, the requested object. Appearances in lists or as containing objects don't count as views. However, some child objects will need to count as views even though they aren't the requested object-- say you wanted to track the number of times a character is seen. You would need to ping that character's counter every time it shows up in a requested scene.

The appropriate solution seems to be a Counter class with a method like $counter->view(objtype, id); that would insert or update a counter record for that object.

There would also need to be a boolean p_counter property that, if found when an object was loaded as the primary object ($object) and method=view, would call $counter->view() for that object.


And Speaking of Pings
Trackback[?] is a system for keeping track of other objects or external URLs that link to a particular object. For external URLs, it's voluntary: a blogger who links to a story on your site might take the time to ping the "trackback URL" for the story, thus sending Berylium information about her referring entry. For this we will try to duplicate, as much as possible, the Moveable Type implementation since they invented it.

But internally, trackback pings could be handled automagically-- whenever an object is posted with [object:id] tags, those objects can be pinged. I'm not sure I want to go quite that far yet, but it should definitely be possible. And pretty cool to see which documents reference an image, for instance.

What I'm really interested in getting out of trackback is going to be very application specific: a trackback ping would occur, to use our previous example, whenever a character is added to a scene. Or for community sites, whenever you click to add a link to someone else's content on your most recent post.

From MT's spec:
The possible query parameters are: title (title of the entry); excerpt (an excerpt of the entry, which, if longer than 255 characters, will be cropped to 252 characters and ... added at the end); url (the permalink for the entry); and blog_name (the name of the weblog in which the entry is posted).
These are all referenced to a global object ID in their system, Berylium would need to use parentobjtype and parentid. These could just be a flavor of Comment, but it might make more sense to implement them as their own class because parentobjtype and parentid are already being used to tie the comment to the container object.

What I've already been doing is using comment->source and filling it with an objtype:id reference. Actually, that would be fine, right? Source for an external object would be the URL. And the rest of the "trackback" flavored comment would absorb the other info.

So for any given object, I could pull up all the trackback comments where source='object:id'. But that still doesn't tell me how to find the top 5 most-linked objects. That sounds like a job for another field in the Counter class.


Which Brings Us Full Circle
So in addition to tracking total views and periodic views, we also want to track total trackback pings and periodic trackback pings-- that way we can see which object get the most views, and which objects are most-linked by doing a select and sorting on the appropriate field.

The trick is, what other stats should we be tracking? I don't want to have an ever-expanding counter table with new columns added every release.

Since much of this data (all of this data?) is application-specific, the counter table could just be a generic scoreboard, and it's up to the app to increment the right field. Or any object could have multiple flavors of counter that track it: select all the view-flavored counters where objtype='document'. So then the call is $counter->ping(objtype, id, flavor, increment=1, period=3600).

OK, that's one issue. The next issue is whether it's possible to integrate round-robinness, so that at any given time of day we can find the most-viewed objects over the last 24 hours. I'm not sure that we can do that with any degree of accuracy without having one record per hit and constantly expiring old records. I think Tobi Oetiker's RRD Tool could solve this problem on an app-dependent basis.

More interesting (and doable) might be to keep an average hits per period count based on the creation date of the counter and an arbitrary period. One could also track max hits per period for all-stars lists or something.


Bottom Line
Okay, this is getting abstract. I think the conclusion is that Berylium really needs a Counter class, and already has the beginnings of a trackback implementation, although it might be fair to say that a Trackback class is necessary as well.

I guess I know what I'm doing on Monday.

By Chris Snyder on March 15, 2003 at 11:49pm

jump to top