Archive for June 2008

I want a monopoly.

I really enjoy The Week Magazine. Every Monday I'm provided with an amusing overview of world events collated from often opposing editorials of the various news outlets worldwide. A filtered "best of the best" -- or -- to quote the byline: "All you need to know about everything that matters" ... It is an easy read, and is not blatantly skewed left or right. It usually gets 'my blood boiling' to see the editorials and articles nationwide ... The "Only in America" notes are especially embarassing.

My most recent fit of 'outrage' prompted by the Week was their coverage of the FCC Hearing in Boston. Comcast, with it's infinite collective intellect, paid "line standers" to hold places in line prior to the meeting happening. This was done to "allow Comcast employees interested in Net Neutrality" that were unable to get time off work to attend the meeting ... But it turns out the line holders were merely a mini "sleeper cell", most of whom had no interest in the hearing anyway -- riveting testimony -- to the point of boredom, and eventually slumber.

This is my proverbial straw. I call Comcast a monopoly. In my area, there is one cable service provider and one telephone service provider (who handles DSL and phone service). I have two choices: internet, or not. But I work from home in the tech industry, so going without internet isn't really a choice. I don't watch television, but am unable to have high-speed internet without "basic" digital cable -- I pay an additional $45 monthly with no choice in the matter, for a service I do not use. The same applies to Embarq, ultimately. In order to have DSL service, I would need local phone service -- something I am wholly uninterested (being one of the many who communicate exclusively via cellular) in, the minimum being somewhere around $35 monthly.

I'm okay with the money. I have come to terms with paying $90 monthly for internet connectivity (advertised as "always on internet") with the side effect of having moving pictures on the various televisions in my house. Unfortunately, the service is far from "always on" ... My most recent experience involved the service running for 5 minutes, and stopping for 2, then restarting. Just long enough for anything running relying on a connection to drop.

It happened for two days in a row, at which point I broke down and called support, asking for help. They believed me at the time, they were unable to ping my modem. They agreed to send a service tech "this afternoon". I called at 7am. Issues persist, though seemingly fixed at some point during the day. They called me asking if my service was okay, and I responded "yes, for now, but I still need a tech to come out -- there is something wrong with the signal or my modem, so please have the tech bring a spare and tester" ... The problems reappeared intermittently throughout the rest of the day. Finally, at 6pm, as I am about to leave for dinner, they call again verifying I'd like a tech to visit. "yes" ... The tech shows up at the door with no spare modem and no testing equipment whatsoever. When asked, the response was akin to "yah - we don't believe you are having trouble, and it wasn't worth carrying it in" ... I was immediately irritated.

Long story short, the tech ended up having to make two trips to the truck, which amused me because the extra trips up three flights of steps could have been avoided had they just brought the damn tester initially. I ended up with a new modem and an extensive lesson on signal strength tolerances. I was right, the signal was bad. My whole day wasted due to shotty service and dis-believing techs. What ever happened to "the customer is always right"? Just bring the bloody tester if I've taken the time to call, sit on hold listening to an annoying lady repeat new channel lineups, wondering all the while what a "friendful customer" is. (She says: "For friendful customers, our lineup has changed ... " ) ... This particular voice is like fingernails on a chalkboard, especially when you realize you've been on hold for 20 minutes and know "SportsSouthwest has been added on channel 23" because of the ten times she'd mentioned it prior.

Overall: I loathe having to call Comcast for anything. I am tolerant of short-lived outages (usually no more than 30 minutes at a time). One month, the service was out so often, I wrote a script to run on a local machine pinging various hosts on an interval to track "to the minute" how much service I had received. Thankfully, after _serveral_ calls and various requests to speak to supervisors, I convinced them to credit my account for a whole month of service, as my logs indicated I was working with around 25% uptime. Unfortunately, the credit never showed up on a bill, and my blatant refusal to actually pay them caused every subsequent bill to show up as "past due", at which point I would call them, verify the credit, and make sure I wasn't going to get a service shutoff. It took four months for the credit to go through and return me to a normal billing cycle.

Then we get into the traffic shaping going on, and all hell breaks loose. I get exceptional upspeeds for the first 10 seconds of any transfer. I can see progress go from 400k/s and immediately drop to 30k after 10 seconds. It seems any activity on BitTorrent ports causes a vast decrease in overall throughput, both up and down. My router showing 10 open connections, nothing excessive, and no explanation for why my connectivity is shot. Why would you even tolerate this kind of stuff, as a consumer? I pay for my service, and have done so on this same account for the past 5 years.

The newest, most fun experience: They don't believe I am me. I am now unable to modify, upgrade, downgrade, or cancel my service. For the past five years, It has not been an issue. Magically, a few days ago, I was asked to verify the last four digits of my social security number ... A question I don't usually get wrong ... unfortunately, somehow, someway, the SSN on file at Comcast is no longer mine, and because of which, I am unable to even ask about the account. They will accept payments from anyone, but require the SSN as an identifier (which if I'm not mistaken is illegal, but out of the scope of this discussion, there is probably some stipulation going on with account numbers, etc).

I decided not to act on it. It would be a waste of my time to go jump through the hoops required to prove my identity to them (which involves a trip to the office with an old bill, ID, and Social Security card in hand, and likely lots of waiting around). It simply isn't worth it to me. I've not modified the account in any meaningful way in years. When I finally do decide to dump Comcast (I've seriously considered getting a t1 or the likes directly, they are getting very cheap), I will have to have it shutoff for non-payment, which isn't an issue to me because it's not my social security number they will be sending the non-payment notification to. I told them it was their issue, and they should restore their records to the SSN that actually signed up the account. They claim there is no log of any change, but their logs "only go back so far" ... The have zero legal recourse should I, the individual paying the bill for the last 5 years, decide not to pay anymore. They can call me on the phone number listed in the account, but will be able to verify my Social Security Number. The worst they can do is turn off my service, which isn't really "always on" to being with.

If I had a choice, I would not use Comcast at all. Please support Net Neutrality -- The last thing I want is for my monopoly the dictate which points on the internet get priority throughput.

Google Analytics after onLoad

update: This was written during Dojo 1.1, and is outdated. The current documentation can be found at http://docs.dojocampus.org/dojox/analytics/Urchin, as some things have changed regarding parameters and setup since this blog post.

You've all seen it, especially in the Ajax world. The page is stalled, waiting to render, the status bar woefully proclaims "waiting for google-analytics.com ... " The culprit being the ever popular urchin tracker, and the [synchronous] script tags placed
at the bottom of your webpage:

 
<script type="text/javascript">
    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
    var pageTracker = _gat._getTracker("UA-123456-7");
    pageTracker._initData();
    pageTracker._trackPageview();
</script>
 

This is usually before the body tag is closed, which causes [at least] Dojo's addOnLoad() function to wait until after ga.js has been loaded, and executed. I notice it most on the SitePen Dojo QuickStart guide. The whole guide is sent as valid HTML and CSS, then enhanced to break major sections into a custom tabbed view, with simple navigation. Unfortunately, all the code to do that is run from within an addOnLoad function, and my poor pitiful ethernets here in Tennessee make ga.js take upwards of five seconds to load. Long story short, sometimes I'm presented with a nasty jolt of rendering as the navigation is added, and the unselected chapters go hidden.

I decided it was a safe bet I could just append a script tag to my head element, and run that onLoad, allowing the rest of the code to execute as soon as the Dom was ready, regardless of Google being ready. This should work with any page that uses Dojo >= 0.9 ... I'm going to test it on this site for a while before considering making it another utility of the Toolkit. It's working so far, let's see if it picks up my traffic (the Analytics dashboard said it was getting data, but I just started it today, so I won't know until tomorrow).

This is just plain JavaScript, with some fancy scope magic for convenience. It uses Dojo because I do.

 
dojo.provide("dojox.analytics.ga");
dojo.mixin(dojox.analytics.ga, {
	// _acct: String
	//		your GA urchin tracker account numbers.
	_acct: dojo.config.urchin || "",
 
	// _loadInterval: Integer
	// 		time in ms to wait between checking again
	_loadInterval: 420,
 
	_loadGA: function(){
		// summary: load the ga.js file and begin initialization process
		var gaHost = ("https:" == document.location.protocol) ? "https://ssl." : "http://www.";
		var s = dojo.doc.createElement('script');
		s.src = gaHost + "google-analytics.com/ga.js";
		dojo.doc.getElementsByTagName("head")[0].appendChild(s);
		setTimeout(dojo.hitch(this, "_checkGA"), this._loadInterval);
	},
 
	_checkGA: function(){
		// summary: sniff the global _gat variable Google defines.
		// 		if it exists, run _gotGA, otherwise, do another interval
		setTimeout(dojo.hitch(this, window['_gat'] ? "_gotGA" : "_checkGA"), this._loadInterval);
	},
 
	_gotGA: function(){
		// summary: initialize the tracker, we've got ga.js loaded
		var ga = this._tracker = dojo.hitch(_gat, "_getTracker", this._acct)();
		ga._initData();
		ga._trackPageview();
		this.GAonLoad.apply(this, arguments);
	},
 
	GAonLoad: function(){
		// stub function to fire when urchin is complete
		// you also have access in this function to this._tracker, which is the
		// root tracker instance you called _initData() on
	}
 
}); 
 
// start it all up after body is ready:
dojo.addOnLoad(dojox.analytics.ga,"_loadGA");
 

I've hard-coded my UA-# into the code, but you would be able to define it as part of your djConfig variable, either before dojo.js is loaded:

 
<script type="text/javascript">
    var djConfig = { parseOnLoad:true, urchin:"UA-123456-7" };
</script>
 

or directly on the script tag:

 
<script src="dojo/dojo.js" djConfig="urchin: UA-123456-7, parseOnLoad:true"></script>
 

you can see the file is namespaced dojox.analytics.ga in the example. If the file were actually located there, you would be able to simply dojo.require("dojox.analytics.ga"); to include analytics tracking on any Dojo-enabled page.

update: It works! (or at least seems to.) All of yesterday's traffic apparently was tracked, and showed up in my analytics dashboard this morning.

update 2: This is now in trunk, as of revision [14006], and is known to work with 1.1 without issue. 1.0 is untested. It will be released with 1.2.