With the Lightboxplus plugin any image you add to your posts will open as an overlay like this:

Wildlife Photograph author [http://www.forestwander.com/wildlife Nature Pictures by ForestWander Nature Photography]

To activate the plugin go to your dashboard > plugins and search for the plugin in the list, then click activate.

For photos that can be viewed as a slideshow, activate the Lightboxplus plugin just add more than one image to your post and they will automatically open as a slideshow when you click one of them. Don’t forget to add captions if you want these to show beneath the images.

Flowers photograph author [http://www.forestwander.[gallery]com/flowers Nature Pictures by ForestWander Nature Photography]

To create a gallery and slideshow combined on your page follow the instructions here:

http://help.edublogs.org/2009/07/29/inserting-a-photo-gallery-into-your-post/

make sure you check the link thumbnails to: image files radio button

you should get something like this:

Images from ForestWander Nature Photography downloaded from http://wiki.creativecommons.org/ and used under CC-BY-3.0

Print Friendly

On the way to work today I decided it might be interesting to blog one day a week on the contents of my day. So here is the first entry …

0800: Up, make tea and porridge for the family. Supervise/cajole/persuade 5 yr old daughter to eat breakfast, brush teeth + hair, get shoes on etc. Frantic exit, tearful drop-off. [Note to self - perhaps readers don't need to know about this aspect of my day!]

0900: Stop for coffee at Ground Control … realise have left wallet at home, nice lady gives me coffee anyway.

0930: Meeting with Student Support team to plan an induction program for new Business Analysts. We have 2 posts which are so far unfilled despite 2 rounds of adverts. Going to look over job advert later to see if we can make it more attractive.

1045: Desk time, answer a few emails. My measly 300 MB work mailbox is telling me it’s nearly full. My rather larger 1GB Gmail mailbox is nowhere near full. One of our schools is reporting that some of their Moodle modules have been ‘deleted’ overnight … sounds like a rollover mess up to me, will check database.

1130: Quick meeting to look at a couple of widgets that someone in School of Informatics has created that queries our student record system (SITS) and exam timetable to produce a course photo page for teachers and personalised exam timetables for students. Want to surface this kind of functionality into Moodle so this is interesting.

1200: The missing Moodle modules have indeed been overwritten by our automated rollover process – due to a lack of communication. Luckily we have scheduled backups on and so am now orchestrating the retrieval and recovery of the affected modules.

1230: Have arranged install of a new plugin for new eduBlogs site – just checked it is there and activated for someone in School of Informatics. It’s an RSS syndication tool (FeedWordPress) that allows you to create a syndicated blog based on specially tagged posts from other WordPress blogs.

1300: Lunch … made possible by my good friend Mike who is lending me a tenner! Chicken and chorizo wrap from Exmouth market stall.

1330: Main meeting of the day – met with web guys to discuss their plans for a student portal homepage and how that fits in with SLE2 and Moodle upgrade plans. So many elements to this it’s hard to see a way forward with our currently limited resources and the sheer amount of work to do. But, more meetings are scheduled.

During this meeting we looked at work done by Martin Hamilton at Loughborough Uni IT Services – my.Lboro

See http://www.youtube.com/watch?v=_2Vi6obOQ6s to find out about the background to this project

1530: Quick bit of research for a forthcoming meeting about digitally signed authenticated documents such as graduation certificates. Does PebblePad do this (no), do eportfolio tools generally do this (think not).

1645: The missing Moodle module saga rolls on. Whilst the missing modules backups are being recovered turns out the school is working on manually fixing *some* of the content … going to make it very hard to sort this mess out. We will have to revisit the whole module rollover thing for Moodle2 … maybe see if we can get hold of University of Kent’s rollover tool!

1700: The welcome sound of the City clock striking 5 o’clock! Home time.

Print Friendly

I went to a great event on this leap day at Senate House ‘Moodle 2: Making the leap’ organised by JISC Regional Support Centre. We heard pre/during/post migration experiences from 4 FE colleges who had made the move to Moodle 2.x from Moodle 1.x.

The most striking thing about their stories, and indeed from talking to others over coffee, was the diversity of setups both technical and organisational. The possible combinations of { virtual learning environment + student record system + database platform + ePortfolio } must surely be infinite! As well as that we also saw a range of uses for Moodle from straightforward course delivery to staff CPD to use as a student portal/intranet.

Why were we there? It was all about migration from Moodle 1 to 2 – how to do it? when to do it? what can go wrong? how to engage academics and students?

How to do it?

There are 2 basic approaches here:

  • upgrade installation in-situ
    This involves replacing the Moodle code old with new and letting Moodle do the upgrade – either via the interface or command line. This seems to be a better option for those with an externally hosted Moodle where there are relatively few code customisations or integrations. The further away your Moodle is from a ‘vanilla’ Moodle the harder this may be so watch out!
  • start afresh and populate via import
    Here a parallel Moodle installation is set up anew and courses are exported from old Moodle and imported to new. At one place a team of 8 staff manually migrated 471 courses in 2 days. This allows an opportunity to clear out old data but users and enrolments will need to be imported separately. When ready you simply need to change DNS settings to point your Moodle URL to the new installation IP address. You can keep the old one as an archive.

The interesting thing here is that there is no clear winner – it will depend very much on your setup and institutional policies on use of VLE. Some places insist on courses being rebuilt every year so for them the fresh install would be the way ahead. Either way both will probably involve a few days (weeks?) downtime while the work is carried out.

When to do it?
The resounding message here was ‘do it early’, probably before your academics go off for their summer hols – especially if you’re expecting them to check and develop their courses in the new Moodle. The start of the academic year is stressful enough so I can definitely see the logic here.

What can go wrong?
Lots! Or maybe nothing. Who knows? It really is a bit like that so testing is the order of the day. For the upgrade option make a duplicate site (and database of course) to test the upgrade process – see what borks it and fix it in your real installation. It could be something as simple as a dodgy filename buried somewhere in the content or rogue code in a label somewhere (paste from MS Word has a lot to answer for!) When testing try and replicate your original server architecture/platform as near as possible.

One college reported that 30% of courses failed to appear in their upgraded version! Whilst you may be able to fix this manually using an army of low-paid summer jobbers (as another FE did) if you are migrating 10,000+ courses then things start to get tricky!

If you have used 3rd party plugins in Moodle 1.9x and these don’t/won’t exist for Moodle 2.x then obviously you will lose this functionality so look at alternatives well ahead of time. The second migration option won’t carry over any users or user data (including glossary data) so you’ll need to deal with that.

How to engage academics and students?
The first step might be to hold mass-inductions (makes me think of Moodle as some kind of cult – maybe it is!) to show the wonders of Moodle2 followed by more personal and practical sessions with staff to cover the areas of major change (file management, navigation, blocks, quiz questions).

Another approach is to get the early-adopters to go over first and show the rest that the water’s lovely, come on in. For students it seems a stealth approach is best – as long as it works and does what they expect they don’t really care what version of Moodle you’re running.

The introduction of a new version of Moodle was used by some as a chance to reinforce the pedagogic principles of the VLE use while for others it was combined with a new swanky theme – you’re going to have to rebuild your theme anyway so why not?

Finally … incentivise! Several FEs who presented today use Moodle medals to award courses bronze, silver and gold standard. Any courses that didn’t meet at least bronze standard were not migrated – harsh but a good incentive for teachers to start engaging. One FE go even further and offer a Level 4 qualification in VLE use.

So, thanks to all the speakers, JISC RSC, ULCC and all people I ‘networked’. The emphasis was on sharing and helping and I personally found it a really useful day – I came away with a to-do list with over 30 ideas so watch out City!

    Print Friendly

Where did the last month go!? As explained in an earlier post Moodle URLs don’t make for very good tracking using traditional server logs or Google Analytics (GA). We have implemented a fix using pseudo-URLs for GA and here I’ll show the basics of code we’ve used (minus some institution-specific tweaks).

We’re aiming to create a pseudo-URL similar to:
{school}.{role}.{course}.{activity-action}.{id}

All the code is in a section in the head part of our theme’s header.html (Moodle 1.9x) or layout/general.php etc (Moodle 2.x) plus any other layout pages that you want to track. Actually, the code is stored in an include and just included where needed.

To set the scene, Moodle authenticates against Active Directory and gets some data from this into the global $USER on login. So we need this:


// get user department code
if (isset($USER->department)) {
$userDept = trim($USER->department);
} else {
$userDept = '';
}

Next, we have a bit of code that sorts these department codes into school codes ($userSchool). I won’t show these but they result in values like CASS, SOI, SEMS etc. You could just as easily set up a variable here that gets the category code, like this:


// get category ID
$category = $COURSE->category;

Getting the user’s role in context is a bit trickier, we’re really only interested in the highest level role at course context level for our purposes but I suppose you could adapt to get a role for the activity context:


// get role of user for the course context (level=50)
$gaUserID = $USER->id;
$gaRole = 'unknownrole'; //default
if ($gaUserID > 0) {
// get contextID for this course first
$gaQry = get_record('context','instanceid',$COURSE->id,'contextlevel','50');
$gaContextID = $gaQry->id;
// then count records to see if user has an entry in role_assignments table
$gaQryCnt = count_records('role_assignments','contextid',$gaContextID,'userid',$USER->id);
// note a user may have multiple roles in db so get highest one
if ($gaQryCnt > 0) { // ok, there are entries so get role
$gaQry = get_records_sql("SELECT * FROM m_role_assignments WHERE contextid='" . $gaContextID . "' AND userid='" . $USER->id . "' ORDER BY roleid ASC",0,1);
$gaQryObj = $gaQry[key($gaQry)]; // get key for 1st element in associative array
$gaQry = get_record('role','id',$gaQryObj->roleid); // get role name
$gaRole = $gaQry->shortname;
} else { // no specific course role, then what are they then?
if ($gaUserID == 1) $gaRole = 'guest'; // assuming standard Moodle setup!
if ($gaUserID == 2) $gaRole = 'superadmin'; // assuming standard Moodle setup!
// is user a Moodle admin?
$gaQryCnt2 = count_records('role_assignments','contextid',1,'userid',$USER->id);
if ($gaQryCnt2 > 0) $gaRole = 'superadmin';
}
} else {
$gaRole = 'notloggedin';
}

Now, to get the module shortname … this bit’s easy:


// get course shortname, could also use id, fullname,
// idnumber although latter not always given
$gaCourse = $COURSE->shortname;

Next we need the activity type and the action being undertaken, this could be split into several variables if required but we are happy with values like: mod-resource-view.

Getting useful info here required a lot of digging into how various activities constructed URLs, there is a lot of variation and custom request variables which are not all covered here (e.g. Turnitin):


// work out what major task is being done by looking at raw URL
$gaPagePath = $CFG->pagepath;
$gaTask = $gaPagePath;
$gaURLParts = explode('/',$gaPagePath);
$gaURLPartsCount = count($gaURLParts);
// we're interested in array elements 3 and above, the bits after Moodle root URL
// so if URL is http://moodle.college.ac.uk/course/view.php?id=102
// element 3 = 'course', 4 = 'view.php' (except for some admin pages, see below)
// following bit checks down the path and grabs relevent keywords to build task
if ($gaURLPartsCount > 3) {
$gaTask = $gaURLParts[3];
if ($gaTask == '') $gaTask = 'home';
}
if ($gaURLPartsCount > 4) {
if ($gaURLParts[4] != '') {
if (strpos($gaURLParts[4],'.') > 0) {
$gaTask = $gaTask . '-' . substr($gaURLParts[4],0,strpos($gaURLParts[4],'.'));
} else {
$gaTask = $gaTask . '-' . $gaURLParts[4];
}
}
}
if ($gaURLPartsCount > 5) {
if ($gaURLParts[5] != '') {
if (strpos($gaURLParts[5],'.') > 0) {
$gaTask = $gaTask . '-' . substr($gaURLParts[5],0,strpos($gaURLParts[5],'.'));
} else {
$gaTask = $gaTask . '-' . $gaURLParts[5];
}
}
}

// fix for moodle bug where admin urls are not getting reported correctly in $CFG->pagepath
// http://tracker.moodle.org/browse/MDL-20342
$gaTask = str_replace('/','-',$gaTask);

// fix for help
if ($gaTask == 'help.php') $gaTask = 'help';

// if there is a current action specified then append that to task but only for non admin stuff
if ($gaURLParts[0] != 'admin') {
if (isset($_REQUEST['currentaction'])) $gaTask = $gaTask . '-' . $_REQUEST['currentaction'];
// if there is a section specified then append that to task
if (isset($_REQUEST['section'])) $gaTask = $gaTask . '-' . $_REQUEST['section'];
// if there is an action specified then append that to task
if (isset($_REQUEST['action'])) $gaTask = $gaTask . '-' . $_REQUEST['action'];
if ( (isset($_REQUEST['frameset'])) && (isset($_REQUEST['page'])) ) $gaTask = $gaTask . "-ims-p" . $_REQUEST['page'];
}

Now, the last part of the URL, the task or page ID:


// now get task or page ID however best, this list not exhaustive
$gaTaskID = '';
// get id number if page has id=xx argument
if (isset($_REQUEST['id'])) $gaTaskID = $_REQUEST['id'];

// if $gaTaskID still 0 try looking for mod id in URL
// e.g. mod/forum/post.php?forum=7 or admin/roles/assign.php?contextid=27
// note that these URLS work best for course content related stuff not user or admin stuff
// this list is not exhaustive, just the ones I managed to identify
if ($gaTaskID == '') {
if (($gaURLPartsCount > 4) && ($gaURLParts[4] == 'forum') && (isset($_REQUEST['f']))) $gaTaskID = $_REQUEST['f'];if (($gaURLPartsCount > 4) && ($gaURLParts[4] == 'forum') && (isset($_REQUEST['f']))) $gaTaskID = $_REQUEST['f'];
if (($gaURLPartsCount > 4) && ($gaURLParts[4] == 'glossary') && (isset($_REQUEST['g']))) $gaTaskID = $_REQUEST['g'];
if (($gaURLPartsCount > 4) && ($gaURLParts[4] == 'forum') && (isset($_REQUEST['forum']))) $gaTaskID = $_REQUEST['forum'];
if (($gaURLPartsCount > 4) && ($gaURLParts[4] == 'resource') && (isset($_REQUEST['r']))) $gaTaskID = $_REQUEST['r'];
if (($gaURLPartsCount > 4) && ($gaURLParts[4] == 'quiz') && (isset($_REQUEST['cmid']))) $gaTaskID = $_REQUEST['cmid'];
if (($gaURLPartsCount > 4) && ($gaURLParts[4] == 'quiz') && (isset($_REQUEST['q']))) $gaTaskID = $_REQUEST['q'];
if (($gaURLPartsCount > 3) && ($gaURLParts[3] == 'calendar') && (isset($_REQUEST['course']))) $gaTaskID = $_REQUEST['course'];
if (($gaURLPartsCount > 3) && ($gaURLParts[3] == 'user') && (isset($_REQUEST['contextid']))) $gaTaskID = $_REQUEST['contextid'];
if (($gaURLPartsCount > 3) && ($gaURLParts[3] == 'blog') && (isset($_REQUEST['filterselect']))) $gaTaskID = $_REQUEST['filterselect'];
if (($gaURLPartsCount > 3) && ($gaURLParts[3] == 'blog') && (isset($_REQUEST['postid']))) $gaTaskID = $_REQUEST['postid'];
if (($gaURLPartsCount > 3) && ($gaURLParts[3] == 'blog') && (isset($_REQUEST['userid']))) $gaTaskID = $_REQUEST['userid'];
if (($gaURLPartsCount > 3) && ($gaURLParts[3] == 'help.php') && (isset($_REQUEST['file'])) && (isset($_REQUEST['module']))) $gaTaskID = $_REQUEST['module'] . '/' . $_REQUEST['file'];
}
// still no taskID? try update=xx from editing resource
if ( ($gaTaskID == '') && (isset($_REQUEST['update']))) $gaTaskID = $_REQUEST['update'];

// if still no taskID then set to 0
if ($gaTaskID == '') $gaTaskID = '0';

Finally, construct the pseudo-URL and set GA account #:


// now construct pseudo URL using . separator
$pseudoUrl = $userSchool . '.' . $gaRole . '.' . $gaCourse . '.' . $gaTask . '.' . $gaTaskID;
$pseudoUrl = strtolower($pseudoUrl); // all lower case for neatness
$gaAccount = "UA-xxxxxxxx-1"; // enter your GA account code here

PHP stuff over, in the html part of the header


<script>
// Google Analytics code as a function instead of inline
function gaSSDSLoad (acct,pseudo_url) {
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
var s,pageTracker;
s = document.createElement('script');
s.src = gaJsHost + 'google-analytics.com/ga.js';
s.type = 'text/javascript';
s.onloadDone = false;
function init () {
try { pageTracker = _gat._getTracker(acct); } catch (err) {}
pageTracker._trackPageview(pseudo_url);
}
s.onload = function () {
s.onloadDone = true;
init();
};
s.onreadystatechange = function() {
if (('loaded' === s.readyState || 'complete' === s.readyState) && !s.onloadDone) {
s.onloadDone = true;
init();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}

// now run script using GA account # and pseudo_url
// fix for IE8
if(window.addEventListener) {
/* W3C method. */
window.addEventListener('load', function(){gaSSDSLoad ("<? echo $gaAccount; ?>","<? echo $pseudoUrl; ?>") }, false);
} else if(window.attachEvent) {
/* IE method. */
window.attachEvent('onload', function(){gaSSDSLoad ("<? echo $gaAccount; ?>","<? echo $pseudoUrl; ?>") });
} else {
/* Old school method. */
window.onload = function() {gaSSDSLoad ("<? echo $gaAccount; ?>","<? echo $pseudoUrl; ?>"); };
}

</script>

File attached with code, don’t forget to edit GA account #
code_snippet

Print Friendly

this is a really useful demo site for troubleshooting problems … and you’re not sure if it’s your installation or Moodle generally: http://school.demo.moodle.net

Print Friendly

this article from Florida International University has a nice clear explanation of what’s new with Moodle2: http://ecampus.fiu.edu/whatsnewmoodle2.php

Print Friendly

When we started with Moodle at City back in 2009 we wanted to use Google Analytics (GA) to augment the stats that Moodle collects itself. Partly this is because user stats are a bit hard to get out of Moodle in a flexible and visually attractive way. True, you could deploy custom queries to the back-end database but we wanted to leverage the power of GA. Trouble is, GA uses as its base unit the URL, and Moodle’s URLs are not very informative.

We want to be able to look at stats for different type of activities and user role (e.g. student vs teacher), and to be able to differentiate between schools (and even departments). This just isn’t possible with the standard moodle/mod/{mod-name}/{action}.php?id={id} format of Moodle URLs – all this gives you is the ability to breakdown stats by activity type alone.

What we’re aiming for then is to send to GA some kind of pseudo-URL that contains the information we need to be able to analyse. A model for this pseudo-URL might look something like this:

{school}.{role}.{module}.{activity-action}.{id}

However an example URL from Moodle might look like this:

http://moodle.city.ac.uk/mod/turnitintool/view.php?id=123456

this tells GA nothing about the page other than it is a Turnitin assignment.

Using custom php in the Moodle theme header.html we can construct our pseudo-URL and send this to Google instead of the actual URL.

The URL we generate will look something like this:

law.student.gen_law_imm_2011-12.mod-turnitintool-view.123456

so now we can interrogate our analytics for school*, role, module, activity and action, down to an individual activity if we want but usually aggregated to some degree. There is also scope to extend this, for example, the Turnitin tool uses another request variable &do (values such as “intro” & “submissions”) which could tell GA a bit more about what is actually happening if it was included in the pseudo-URL. Other plugins and activities have other similarly useful request variables in their URLs.

[*Where do we get school from? Our user table grabs school and department codes from our user database on login via LDAP so it is available in the global $USER]

I won’t show the code we used to create the pseudo-URL (if anyone wants that see this post) but the adapted GA script from the header.html <head> section  is here **:


<?php
$pseudoURL = "blah"; // insert code here to build pseudo-URL
$gaAccount = "UA-xxxxxxxx-1"; // enter your GA account code here
?>
<script>
// Google Analytics code as a function instead of inline
function gaSSDSLoad (acct,pseudo_url) {
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." :
"http://www.");
var s,pageTracker;
s = document.createElement('script');
s.src = gaJsHost + 'google-analytics.com/ga.js';
s.type = 'text/javascript';
s.onloadDone = false;
function init () {
try { pageTracker = _gat._getTracker(acct); } catch (err) {}
pageTracker._trackPageview(pseudo_url);
}
s.onload = function () {
s.onloadDone = true;
init();
};
s.onreadystatechange = function() {
if (('loaded' === s.readyState || 'complete' === s.readyState) &&
!s.onloadDone) {
s.onloadDone = true;
init();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}

// now run script using GA account # and pseudo_url
// fix for IE8
if (window.addEventListener) {
/* W3C method. */
window.addEventListener('load', function(){gaSSDSLoad ("<? echo $gaAccount; ?>","<? echo $pseudoUrl; ?>") }, false);
} else if (window.attachEvent) {
/* IE method. */
window.attachEvent('onload', function(){gaSSDSLoad ("<? echo $gaAccount; ?>","<? echo $pseudoUrl; ?>") });
} else {
/* Old school method. */
window.onload = function() {gaSSDSLoad ("<? echo $gaAccount; ?>","<? echo $pseudoUrl; ?>"); };
}

[**Not sure who to credit this to, it wasn't me, someone in the webteam came up with this before I got here.]

In a future post I’ll talk about how we use Google Analytics and Moodle’s own stats here at City.

Print Friendly

It’s a hot topic alright but what is everyone banging on about? Moodle2 can be used out of the box without any repositories – you can still upload files from your computer. True, Moodle2 handles them in a different way and you no longer get the nice files area you used to get (unless you allow legacy files) but early reports suggest academics prefer this simplicity.

A really great White Paper by somerandomthoughts.com gives an in-depth account of the different use cases for repositories and Moodle2. Use cases is the key here – your institution must choose the right solution(s) for its needs. The key questions are around whether to link or copy and what that means for Moodle backups and audit activities.

“Repository” covers a wide range of things … YouTube is a repository, as is GoogleDocs, DropBox, Flickr and Picasa. These are things you may well use and wish to be able to link or copy files into Moodle. Repository can also mean some kind of institutional file store – such as Alfresco or Box.net. There are many more – the ones just mentioned are all supported by the standard Moodle2 installation. Either way you’ll need to consider carefully issues around authentication and licensing.

As we go forward with our strategy and start looking at Moodle2 we are beginning to formulate ideas on what repository options (if any) City adopts. One of the things I’d like to tackle is the tendency for academics to use Moodle as a personal file archive, keeping old course data, backup zips, student work from years gone by etc … all right there in the course file space. Sure, disk space is cheap but it’s just bad practice, rather like throwing the dirty dishes in the backyard instead of washing them up. Kind of.

Print Friendly

We use PebblePad here at City but have also been looking at Mahara as a possible ePortfolio solution. What about WordPress though? What are the requirements for an ePortfolio solution anyway? Mahara seems overly complicated to me.

WordPress.com is quick to setup, easy to use and can (at the very least) be used as a reflective journal. You can make it private, invite people to view and comment, add media etc … seems to tick many boxes. And it is yours, to take with you, no institutional lock-ins or migrations needed. By using WordPress.com together with YouTube, Flickr etc it’s a kind of ePortfolio mashup.

This blog by Helen Barrett is a bit old but still of interest:

Create an Electronic Portfolio with WordPress

Print Friendly

I work at City University as project manager for the Strategic Learning Environment (SLE). This covers quite a few things but mostly means I am responsible for our virtual learning environment (VLE) which is currently Moodle 1.9. I’ve been working at City already for the last 2 years as a contractor, first as a Moodle developer, then when we employed our full-time developer as development manager. This involved liaising between the schools and Information Systems and making sure Moodle was meeting everyone’s needs.

Moodle, the dominant player in our strategy, is joined by a host of other systems such as Turnitin, Adobe Connect & Presenter, PebblePad and WordPress (soon?) as well as the usual university systems for student records, registry, timetabling, library catalogs etc. Integrating and harmonising these systems  is a major objective of the SLE vision. Of course, as well as the software, there is also our physical space and the SLE remit includes learning spaces, lecture capture, infrastructure and our final most precious resource … people! More of all this as I progress with the blog.

Finally, why blog? Mainly as a personal space where I can reflect on the challenges and achievements of my job and to document some of the work we do here at City. I’ll be blogging about user group meetings, conferences, meetings and also about technical stuff – how we did things like get Moodle2 running.

Print Friendly
I am Mike Hughes, the opinions expressed on this blog are my own and not those of my employer ... do I really need to say this?