Adventures in WooCommerce: rounding

Here’s another fun thing I found recently. It’s definitely a bug, and I do have a solution, but I don’t know if it’s a good one. I’ve been told that these rounding errors are common in e-commerce systems, so there’s got to be a more general solution.

Here’s the setup: a product worth $29.95; a coupon taking 10% off the cart amount; number of decimal places set to 2.

Add one product and the coupon, and here’s what you end up with: a $26.96 cart total, with a $3.00 discount amount. The database has the correct amounts for the line items ($26.955 and $2.995 respectively) but because of how rounding works, you don’t get to see that. PHP by default rounds to the closest value, and .5 will always round up. Even if I set it to always round up or down, the values would still be off by $0.01.

Here’s my solution: adding a function to action ‘woocommerce_after_calculate_totals’. If there are percentage-type discounts, check if the subtotal and total discount discount amount are off. If they are, adjust one of the percentage discounts (if there are more than one). It works, but I’m not happy with it. It seems there should be something better…

WooCommerce customer list report

I’ve been playing around with WooCommerce a lot lately, and twigged on something that I think is a little design flaw.

It all started when I created a duplicate of one of the built-in reports (the Customer List report), with a few bits of different logic which aren’t really important right now. (Incidentally, creating a report is dead easy with just a few action hooks like woocommerce_admin_reports and wc_admin_reports_path, and can be done right in your theme). This new report keeps the same columns as Customer List, including:

  • Orders, the total number of orders for that customer
  • Money Spent, the total money spent by that customer
  • Last Order (date and link to the customer’s last order)

But while testing my report I noticed that some of these numbers weren’t quite right; they weren’t right in the Customer List report as well. What was happening is that some of this client’s customers had submitted orders using their account email but without logging in. This meant that those orders did not get counted against their account totals, even though I think they should have because they have to be the same person.

Here’s how WooCommerce links orders to accounts: if the user is logged in, the order gets a piece of meta data with key ‘_customer_user’, and the value is the user ID. So far so good. But if the order was submitted anonymously, then the best we have is the billing email (meta key ‘_billing_email’). To display the relevant data, the Customer List report uses two built-in functions, wc_get_customer_total_spent() and wc_get_customer_order_count(), defined in file woocommerce/includes/wc-user-functions.php. Both take a user ID as parameter, and run similar SQL queries. For example:

global $wpdb;
$spent = $wpdb->get_var( "SELECT SUM(meta2.meta_value)
  FROM $wpdb->posts as posts

  LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
  LEFT JOIN {$wpdb->postmeta} AS meta2 ON posts.ID = meta2.post_id

  WHERE   meta.meta_key       = '_customer_user'
  AND     meta.meta_value     = $user_id
  AND     posts.post_type     IN ('" . implode( "','", wc_get_order_types( 'reports' ) ) . "')
  AND     posts.post_status   IN ( 'wc-completed', 'wc-processing' )
  AND     meta2.meta_key      = '_order_total'
" );

The logic to get the latest order is defined in woocommerce/includes/admin/reports/class-wc-report-customer-list.php and uses get_posts() with a meta query on key ‘_customer_user’, like so:

$order_ids = get_posts( array(
	'posts_per_page' => 1,
	'post_type'      => 'shop_order',
	'orderby'        => 'date',
	'order'          => 'desc',
	'post_status'    => array( 'wc-completed', 'wc-processing' ),
	'meta_query' => array(
		array(
			'key'     => '_customer_user',
			'value'   => $user->ID
		)
	),
	'fields' => 'ids'
) );

So my solution is simply to tweak those three queries. The meta query part should change to:

'meta_query' => array(
  'relation' => 'OR',
  array(
    'key'     => '_customer_user',
    'value'   => $user->ID
  ),
  array(
    'key'     => '_billing_email',
    'value'   => $user->user_email
  )
),

Both functions wc_get_customer_total_spent() and wc_get_customer_order_count() will need to load the user object, so that we can get the email. So the queries should look like:

$user    = get_user_by( 'id', $user_id );
global $wpdb;
$spent = $wpdb->get_var( "SELECT SUM(meta2.meta_value)
  FROM $wpdb->posts as posts

  LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
  LEFT JOIN {$wpdb->postmeta} AS meta2 ON posts.ID = meta2.post_id

  WHERE   (
    (meta.meta_key = '_customer_user' AND meta_value = $user_id)
      OR 
    (meta.meta_key = '_billing_email' AND meta_value = '{$user->user_email}')
  )
  AND posts.post_type     IN ('" . implode( "','", wc_get_order_types( 'reports' ) ) . "')
  AND     posts.post_status   IN ( 'wc-completed', 'wc-processing' )
  AND meta2.meta_key      = '_order_total'
" );

WordCamp Vancouver 2014

It was time for Vancouver’s annual WordCamp extravaganza, this time a Developer Edition (the first since 2011)! Good timing, too: last year’s came smack in the middle of the Queer Film Fest and I had to miss one of the shows!

Opening remarks

Nothing too special here: a lot of thanking all the attendants, our fabulous sponsors and equally fabulous volunteers, but one thing did stand out: the organisers mentioned the “WordPress Rangers,” volunteers dressed in distinctive t-shirts, that would circulate around the Camp and how attendees could come to them with any questions or concerns, including if they were being harassed.

A few people laughed, and that was the interesting part. Was it because it came up out of the blue? Or because they didn’t think that could ever be an issue at a WordCamp, or in Vancouver? I don’t know, but I think it’s great that the conference has a code of conduct that explicitly forbids harassment and discrimination, and that the organisers went out of their way to let people know about it.

Now, on to the talks:

Curtis McHale: Getting Started With Unit testing

Curtis McHale stepped us through the theory and practice of test-driven development, focusing specifically on PHPUnit. I have to admit it’s something I sorely need to work on. Some of the tools and tips were WordPress-specific, (e.g.: turning on WP_DEBUG, using WP_UnitTestCase), but most could be applied to any development project. Good stuff.

Mel Karlik: How to Build a Custom Widget

Mel Karlik gave us a quick how-to on creating a widget as a plugin. I’d already tried my hand at this before, but it was nice to get a refresher course. Plus, I learned about Genericons! I thought they were the same icon font as the 3.9 admin dashboard uses but no, that’s Dashicons. Still, same idea.

Ben Lobaugh: Securing your plugin / theme

On the bright side, Ben says, even the pros introduce security flaws in their work. When it happens, the thing to do is own up to it and push an update.

This talk contained a million tips on writing secure code: follow the coding guidelines in the Codex; enable WP_DEBUG to ensure you don’t miss anything like deprecated hooks; don’t trust your users; sanitise everything; use the API, it’ll keep your code simple and do the heavy lifting for you; check user permissions; and so on and so forth. Great stuff, I just need to sit down and be mindful of it when I’m doing my coding.

Morten Rand-Hendriksen: Future Responsive Today

Morten’s talk was in two parts: one on the HTML5 <picture> element, which is intended to replace the tag, and Flexbox, which is pure awesomesauce magic to let you lay out elements in far more flexible ways than we ever thought possible.

<picture> was new to me though flexbox wasn’t; still, I loved the demos and seeing all that it could do.

(Slides here: http://mor10.com/presentations/flexbox/)

Merrill Mayer: Advanced Custom Fields: Beyond the Basics

In the first of 4 lightning talks, Merrill Mayer walked us through her solution to a particular client problem: they needed a custom date field for a custom post type, along with custom “previous post” and “next post” functionality (getting links from this field, not the usual post date), and some customising of the dashboard post list. You can see it in action at bbrc.net/speakers. It was a neat exercise, using a variety of tools (custom wp_query, filters for the links, more filters for the dashboard, etc…)

Tanner Moushey: Introduction to the command line

Second lightning talk: Tanner Moushey introduced us to command-line tools, and why on earth we’d ever need them. Except for mentioning WP-CLI it was very general: Git, ssh, scripts, and vim. Nothing really new to me, but again it’s good to bring it all together.

Christine Rondeau: Responsive web development made easy with CSS and the mobble plugin

Third lightning talk: Christine Rondeau talking about a few tools for responsive design. The first technique is to hide ¬†or reveal content at certain breakpoints, using CSS. It’s simple but effective and flexible; however, the HTML content is still being downloaded, which is an issue. It’s good for small bits of code, but nothing too big.

That’s where mobble comes in: the plugin provides conditional functions for detecting a variety of mobile devices. Good stuff.

Robert Dall: How to create your own robot

Or, how to connect Github with Asana. How do you work with Github when your team is physically somewhere else? One solution is to have your commits show up in Asana.

(Slides and blog post here)

Zack Tollman: Cowboy coding

What’s cowboy coding? Zack explains that it’s risky coding, without testing or staging or any safety net whatsoever. It’s unpredictable and there’s bound to always be collateral damage. So he walked us through some tools to automate deployment and server update processes, to reduce the chances of human error bringing down whole sites or servers.

Tools to test updates locally (Vagrant, MAMP/WAMP); provisioning tools; deployment tools. And my first thought was that I never had to manage a server, but I have installed updates on live servers without proper backup plans. I need to avoid that in the future!

(Slides can be found here)

Luke Woodward: Little-known WP JavaScript helpers

I’ve already used a tiny little bit of the Ajax API, but I figured this talk would be take me to the next level. And it did! I’ll need more time to digest and apply the lessons here, so I won’t bother to summarise the talk. Here are the slides! And here’s his code example!

In conclusion

Success! I learned tons, reconnected with WordPress peeps and met a few new ones. Now I just need to apply everything I learned… and think about doing a talk myself? Hey, why not?

How to display post content via jQuery and the_content()

I solved an interesting little problem I ran across recently; investigating it led me to a fuller understanding of how WordPress does some things.

I solved an interesting little problem I ran across recently; investigating it led me to a fuller understanding of how WordPress does some things.

Here’s the setup: when you click a link, a particular div will have its inner HTML set to a particular post content via jQuery. The code would look something like this:

while ( $loop->have_posts() ) : $loop->the_post();
  $content = get_the_content();
?>
  Link to click
  

Could that be made more efficient? Maybe. I guess you could do it through AJAX, passing in the post ID and returning the content, if only to avoid having a potentially long string in the page source—which in this instance is not an issue. The bottom line is, though, we’re passing in the_content() in .html().

And JavaScript won’t take it. When I try, I get the following error:

Uncaught SyntaxError: Unexpected token ILLEGAL

It seems that the_content() adds an extra character (a newline) at the end, and it’s causing the hiccup. Note that get_the_content(), which returns the unformatted post body, does not cause this error.

My solution was to add a filter to remove that extra character. How? Like this, in my theme’s functions.php

function my_content_filter ($content) {
	return substr($content,0,-1);
}

add_filter( 'the_content', 'my_content_filter', 20);

As you know, this hooks a filter function to the ‘the_content’ action, so that my_content_filter() is applied before being rendered. As you can see all the function does is remove the last character of the content string. The last argument is he priority, and determines in what order the filter functions are applied. Naturally, I assumed that since the default priority is 10, anything greater than that meant that my filter would be applied to the formatted content, having already gone through the default filters—adding <p> tags and educated quotes and that pesky illegal unexpected token.

And it worked! However, I was still curious. I’d never delved into filters before, so it seemed like a good time. Starting with the_content(), defined in wp-includes/post-template.php:

function the_content($more_link_text = null, $stripteaser = false) {
  $content = get_the_content($more_link_text, $stripteaser);
  $content = apply_filters('the_content', $content);
  $content = str_replace(']]>', ']]>', $content);
  echo $content;
}

Pretty straightfoward, right? You retrieve the content, apply any filters, and return it. I’m not sure what str_replace(']]>', ']]>', $content) is supposed to do, though…

As for the default filters, they’re set in wp-includes/default-filters.php

add_filter( 'the_content', 'wptexturize'        );
add_filter( 'the_content', 'convert_smilies'    );
add_filter( 'the_content', 'convert_chars'      );
add_filter( 'the_content', 'wpautop'            );
add_filter( 'the_content', 'shortcode_unautop'  );
add_filter( 'the_content', 'prepend_attachment' );

We can see that the filters are indeed set with the default priority. And, the formats are defined in yet a third file, wp-includes/formatting.php. It’s ‘wpautop’ that interests us. This is the filter that creates <p> and <br /> tags from single- and double-returns. And yes, it does add a “\n” at the very end. So there you go, question answered and problem solved. I know that my solution works, and I know why.

I’m wondering if I could do better, though. Would remove_filter() be useful? But then I’d still have to re-implement something like wpautop—basically, reinventing the wheel. Nah, I won’t worry about it. This is good enough for now.

CSS3 tidbits: background-size and box-sizing

A couple little CSS lessons I learned recently and wanted to pass on…

background-size

I learned about this property a couple of months ago, in a local WordPress meetup. As the name implies, this is used to set the size of background images, as a value or a percentage of the element’s dimensions—and you can set the background height and width separately. There are also a couple of keywords (“contain” and “cover”) to do a couple of extra tricks with the image.

It’s a neat little property that so far I haven’t used myself; but in the example given, the Ridge Meadows Recycling Society, it looks very good. A couple points that were brought up:

  • Apparently, if you’re applying background-size to the entire page, it has to be set for <html>, not <body>. I’m not really sure why that is, though.
  • If you’re using the cover or contain keywords, you need to make sure your background image is at least as big as your element; otherwise it’ll stretch, and obviously not look as good.
  • Not CSS-related, but one of the presenters mentioned working on WordPress templates through text editors + FTP, not through the admin dashboard. That had honestly never occurred to me before, but it makes sense: in the dashboard you can’t roll back your changes since there are no backups, and if you mess up it could take down the whole site (and then you’d have to fix it via FTP anyway).

box-sizing

I needed to set a form field’s width to be exactly as wide as its surrounding div, even counting padding and border, and since I wanted to make the theme responsive I couldn’t set fixed width values. The answer is the box-sizing property. Set its value to “content-box”, and it will draw the element as you’d expect, with the padding and border adding to its width. Set it to “border-box”, and the padding and border will be drawn inside the border box, thus allowing for a snug fit if you write a rule like so:

#sidebar .searchform .s {
  display:block;
  box-sizing:border-box;
  width:100%;
}

box-sizing is supported by most browsers nowadays except Firefox. Not to worry, there are vendor-specific rules you can use (-moz-box-sizing, etc…)

WordCamp 2012

Wow, it’s been almost two weeks since Vancouver WordCamp 2012, the awesome one-day conference on all things WordPress. As last year, the event was divided into Design and Development tracks. And again as last year, I went back and forth between the two. Let’s face it, the line between design and development can pretty thin.

Wow, it’s been almost two weeks since Vancouver WordCamp 2012, the awesome one-day conference on all things WordPress. As last year, the event was divided into Design and Development tracks. And again as last year, I went back and forth between the two. Let’s face it, the line between design and development can pretty thin.

Calm and Simple Code With Purpose

Jeremy Felt from 10up.com gave the audience some pointers on calm, effective and mindful coding. Rushed code means bugs, and you may think you’ll go back and fix them later but there’s always another deadline! Better to do it right the first time. Invest the time to perfect your craft. Dig into the Codex*, read the code, understand how things work and why they work the way they do.

As well, developers need to know what tools are available, when to use them, and when not to. Libraries like jQuery are already there, no need to add it in your plugins! Use caching when you must.**

Finally, we need to be mindful of our audience: developers in our team, or even ourselves six months down the line. Document your code, make it readable, whether you’re solo or part of a team. And if you’re working solo, get involved in community projects!***

*And don’t complain if it’s crap. You’re totally free to improve things!

**Memo to myself: read up on the WordPress Transient API, because I have absolutely no experience in it.

***I totally need to do that.

Documentation

John James Jacoby of Automattic came to talk about PHPDoc, a PHP documentation standard similar to JavaDoc. Documentation standards like that are about not wasting time and brainpower. It’s about (his words) not being an asshole, and not taking time away from other people or even your future self. Because you’ll be able to quickly get to what a particular bit of code is doing and why.*

JJJ also repeated Jeremy’s advice to get on the Codex and improve it if you’ve got something to say. It’s a great place to learn, because wordpress.org has lots of caretakers.

*The why is important. It’s easy to describe what is happening but why is the more interesting question.

S2Members—a membership plugin for WP

Rayhan Abdulmughnee of the Small Business Centre spoke about a S2Members. It was fairly narrow in its focus, which was a bit of a disappointment. Then again, I knew what I was getting into. The main reason I attended this presentation instead of one on a command-line-interface for WordPress, was that I was possibly about to start a WP project heavily dealing with user roles, and I thought this might give me some good ideas. I’m not sure if it did. That project ended up not happening, which was also a bit disappointing; I’ve never dealt with WordPress user management except in the most basic sense. Drupal, sure, I know it forward and back, but I would have liked a chance to dig into it on the WordPress side. Someday soon, I’m sure.

JQuery mistakes and how to avoid them

Back to the development track after lunch, to learn all about jQuery from Automattic’s Andy Peatling. This was an very intense presentation, dishing out all sorts of jQuery tips and tricks which I won’t list here (and honestly, some of which went over my head).

Caching in WordPress: Invalidation schemes

Oh, but the fun doesn’t stop there! Zack Tollman was up to tell us all about caching in WP, and schemes to refresh that cache when it gets obsolete. Cache versioning, transients, and again a lot of this was totally new to me.

How to make your WordPress site mobile-friendly

David Zille started out by giving some general tips on what a mobile theme needs: fast loading, visibility of the important elements, ease of navigation, and accessibility. Then he laid out various schemes to make your site mobile friendly:

  • a third-party service
  • a responsive theme
  • a separate mobile theme

Responsive themes (which I already have some experience in) use CSS and JavaScript behind the scenes, but the downside is that you’re serving your entire content to a phone. Plus, they can be difficult to maintain and build from scratch.

Separate mobile themes (which may come with plugins) avoid most of these pitfalls, but probably have issues of their own. It all comes down to your budget, skill sets, etc…

Food for thought, definitely.

The WordPress community

Vancouver’s own Christine Rondeau wrapped up the day to tell us about the WordPress community. And it’s real: it’s in the meetups and in the forums and the blogs and on IRC, and in events like this one. You participate to learn, to get referrals, make friends and say thanks. You know, Christine’s talk was another kick in the pants for me to get more involved. More than just going to meetups (which I do), I need to actually contribute something. There’s a theme I’ve been hacking away at on and off (based on my current blog theme, actually) I need to polish it up and submit it.

Oh, and I won a Code Poet t-shirt!

There was an afterparty, but I already had plans to ogle hot athletes in underwear at Celebrities, so I had to give that a miss.

VGVA.com redesign: the frontend

Layout-wise, I made a few changes to VGVA.com. First, a much wider default width (from 800 to 1024 pixels) allowed me a second sidebar. After a lot of experimentation and feedback from the VGVA board, I displayed our sponsors in two cycling blocks (thank you, jQuery Cycle Plugin!), plus a separate block for new “official supplier sponsor” volleyballstuff.net. Team sponsors should be pleased, at least; their logos had previously been stuck below the footer.

(Part 2 of my recap of the VGVA.com redesign. Part 1 is here)

Layout-wise, I made a few changes to VGVA.com. First, a much wider default width (from 800 to 1024 pixels) allowed me a second sidebar. After a lot of experimentation and feedback from the VGVA board, I displayed our sponsors in two cycling blocks (thank you, jQuery Cycle Plugin!), plus a separate block for new “official supplier sponsor” volleyballstuff.net. Team sponsors should be pleased, at least; their logos had previously been stuck below the footer.

The left sidebar displays news and matchmaker listings, two things previously confined to a couple pages each, as well as section sub-menus where appropriate, for easier navigation. Speaking of News, I decided to scrap the news archive page from the previous design. I’d gotten the idea from the Out on Screen site, but after a while archiving past events felt pretty useless (especially since almost all these events recur every year). I don’t have the numbers to back up my guts, but it makes for a simpler architecture and nobody’s complained yet, so there you are.

The matchmaker section hasn’t changed much, as far as the user would tell, except I did implement an AJAX-based login/signup process (which falls back to plain synchronous forms if the browser isn’t running JavaScript).

Lastly, I tried my hand at this responsive design thing I’ve heard so much about. Nothing too fancy, just narrowing or removing the width of the left sidebar for smaller screens, plus taking out some stylistic frills (e.g.: rounded corners) for mobile browsers.

So there you have it! This redesign consumed so much of my free time for months, but now I can finally relax a bit…

VGVA.com redesign: the backend

The first and most obvious aspect of this redesign was moving from a few homebrewed PHP scripts to a proper CMS, namely WordPress. The advantages are obvious—revision history, a full text editor, taxonomies, etc… etc…—are obvious. But I needed a lot more than just a basic CMS for this site, and WordPress was ready:

The first and most obvious aspect of this redesign was moving from a few homebrewed PHP scripts to a proper CMS, namely WordPress. The advantages—revision history, a full text editor, taxonomies, etc… etc…—are obvious. But I needed a lot more than just a basic CMS for this site, and WordPress was ready:

Multiple custom post types

I’ve got 2 now, and will be implementing a third in the near future. News display on the front page and the left sidebar, and require not just a start date but an expiry date. Newsletters have no custom fields but are mailed out to our membership upon publication. Last comes Skills, a series of tutorials sent out every couple of weeks by one of the mentors to the intermediate players. Right now they’re only implemented as static pages with hard-coded dates—bit of a rush job, I admit.

Control panel

Some pages, such as tournaments and registration pages, have time-sensitive content. Previously I kept the different versions of these pages in separate files, swapping them out via crontabs. This worked well enough, but it was definitely not friendly to non-techy people. My solution was to keep different versions in separate private sub-pages (tidier that way), with the master (public) page’s content consisting only of a banner and a shortcode.

This shortcode would output the content of one of the sub-pages, based on the current time and whatever deadlines apply.

add_shortcode( 'vgva_summerfling_body', 'vgva_summerfling_body_func' );

function vgva_summerfling_body_func($atts) {
  $now = time();
  $fling_over = get_option('vgva_fling_date') + 86400; //the day after it ends
  if($now < $fling_over) {
    if(($now >= get_option('vgva_fling_upcoming') && $now < get_option('vgva_fling_reg_open')) || get_option('vgva_fling_upcoming') > get_option('vgva_fling_reg_open')) {
      //summer fling upcoming
      $pageId = 788;
    } else {
      //summer fling registration open
      $pageId = 790;
    }
  } else {
    //summer fling inactive/over
    $pageId = 786;
  }
  $page = get_page($pageId);
  return apply_filters('the_content', $page->post_content);
}

How are these deadlines set? Through a “control panel” consisting of several pages, each setting one aspect of the site’s configuration. Registration, board members, tournaments, etc… Basically, if it influences the site’s behaviour, or appears on more than one place on the site, it goes in the control panel.

So, non-techy people can easily update the pages and the configuration. The logic tying everything together is still my domain, but once I’ve ironed out all the bugs that’ll never needs to change unless new features are required.

Speaking of shortcodes, the sub-pages (and hell, almost every page on the site) makes generous use of them. It was a pain to set up, but now I can sit back and relax. No more global search-and-replace to update board membership and contact info (the chair’s name and email, especially, shows up on many different pages.)

add_shortcode( 'vgva_fling_reg_fee', 'vgva_fling_reg_fee_func' );

function vgva_fling_reg_fee_func($atts) {
  setlocale(LC_MONETARY, 'en_US');
  return money_format('%n',get_option('vgva_fling_fee'));
}

One pet peeve I have is that, unlike Drupal, WordPress does not have built-in logic to generate the markup for configuration pages, so not only do I have to do the hard work, there’s no accepted standard. Hmph. Oh well.

The Matchmaker

The matchmaker logic didn’t change a whole lot: I tweaked the data structure here and there, but nothing substantial. The real pain was making custom forms work in WordPress, with the custom templates that feel very… hacky and awkward. Again, Drupal is way easier for heavy custom development. But hey, I knew what I was getting into.

One last thing: all this custom logic (custom post types, matchmaker) was implemented as plugins, not part of the active theme. It’s just common sense, right?

So there you have it, a peek into the back-end development of VGVA.com. It was by far my most involved project, and I enjoyed every minute of it. I learned so much about WordPress’s guts, and got some excellent hands-on experience.

(Next up: a bit about the redesigned front-end)

The VGVA.com redesign

For several months, I’ve been hard at work redesigning the Vancouver Gay Volleyball Association website. Longtime readers will remember previous posts wherein I expressed my insecurities, then my excitement at tackling its redesign in 2008. Now in 2011 comes another redesign, even more extensive.

For several months, I’ve been hard at work redesigning the Vancouver Gay Volleyball Association website. Longtime readers will remember previous posts wherein I expressed my insecurities, then my excitement at tackling its redesign in 2008.

Now in 2011 comes another redesign, even more extensive. I moved the site to WordPress instead of homebrewed PHP scripts, jiggered the layout and structure, and made extensive under-the-hood changes to allow non-techy people to update content, announcements, and time-sensitive information (tournaments, registration) without mucking about with HTML and SQL.

In the next couple of posts I’ll go into more detail about the changes I’ve made, and what I’ve learned along the way.

Northern Voice 2011

And it’s that time of year again. Time to hob-nob with all sorts of bloggers and assorted geeks in UBC’s lovely Life Sciences Centre, with its gorgeous atriums filled with natural light.

And it’s that time of year again. Time to hob-nob with all sorts of bloggers and assorted geeks in UBC’s lovely Life Sciences Centre, with its gorgeous atriums filled with natural light.

Friday Keynote: April Smith

This was different. Both previous keynotes dealt with high-level politics, how social media intersects with mainstream media and corporate power. But April Smith brought us down to earth for a moment with her stories of living in the Downtown Eastside. We learned about her work as a citizen journalist empowering the residents with access to technology—Nokia handphones, specifically. I forget the exact model, and I’ll forgive the constant product placement, especially if it turns out that they’re as easy to use as she claims. Those phones were donated by some Nokia rep, and it’s a hard reminder that this shit ain’t free, and every social movement must depend on the kindness of sicher strangers.

April was clearly nervous and reading from prepared notes—she admitted to being uncomfortable speaking in front of people—but that didn’t matter. Her stories were raw, straight from the heart, and powerfully moving. The short clip of the man whose cat was thrown out of his 5th storey apartment during a breakin. The simple brief connection that stopped a man from killing himself, just because she showed him a bit of kindness and let him see his own photo. If April hadn’t been there, with her phone, that man would now be dead.

That’s what social media means, in the Downtown Eastside. It’s about connecting with people, telling your story, and changing lives for the better.

Drawing on Walls

Okay, that was kind of a bust. I don’t think I got anything out of it, except yet a reminder that my drawing skills suck. I chose this session just to go a little outside the box (and because none of the other ones really appealed to me), but an hour-long workshop wasn’t going to give me any super-creative power. Ah, well. Live and learn.

Your Blog Is Boring and Your Photos Suck

Syx Langemann and Morten Rand-Hendriksen teamed up to give the audience some tools to make their photos suck less and their blogs less boring. Somewhat disappointingly, they mostly covered the technical aspects (Syx: aperture, shutter speed, ISO; Morten: ALT tags, meta tags, SEO, and WordPress-specific tidbits) but not so much ways to make things less boring or sucky. I guess that part is up to each of us. But I did love the sample photos Syx showed us; nothing like the portfolio of a talented photographer to get you inspired!

The Naked Truth: Canadian Science Blogging Scene

A panel consisting of Rosie Redfield, Beth Snow, Eric Michael Johnson and Maryse de la Giroday discussed science, blogging, and all related issues. Does blogging impact your credibility as an academic and researcher? What are the pros and cons of pay-to-read vs. pay-to-publish journals? What place do non-peer-reviewed blogs have in science education and research? What incentive do researchers have to blog about their work if it means the risk of competitors scooping them out (and their funding)? Why would a researcher blog?

Dr. Redfield (who did most of the talking) answered that last question: she likes the idea of a non-scientist stumbling on her writing, it clarified her thinking, serves as a memory aid, and helps her write. Also, it allows her to critique science in the media.

Good stuff, for sure.

Incidentally, I found it interesting that 3 out of the 4 panelists were women. I wouldn’t have expected that kind of breakdown for science bloggers and academics, but there you go.

Also: the following day at lunchtime, Dr. Redfield took a few of us on a short tour of the labs in the building. Behold the power of social media: there was no big announcement, no signs put up, just a couple of calls retweeted back and forth.

MooseCamp: Five Card Flickr

Five Card Flickr is fun. Our small group spent the hour with Alan Levine getting to know the game, choosing pictures, and coming up with a story. Didn’t go anywhere and it had no plot, but man was it fun. I haven’t taken part in this kind of collective storytelling since… what, my D&D days? Ooo, and check out Pecha Flickr.

Communities That Rock

How do you create kick-ass online communities? Arieanna Schweber and Raul Pacheco-Varga give us the lowdown. Some of their advice applied for blogs, others for forums and community sites, but the bottom line is pretty much the same: engage with your audience, have everything (tweets, photos, videos) point back to a single site, have proper internal linking, know how to tell a story. Pretty common-sense stuff, right? Maybe, but it has to be said. Also, keep in mind that this is hard work, and community building doesn’t happen overnight. Finally, avoid becoming isolated. It’s good to be active both offline and online.

Saturday Keynote: Chris Wilson

Chris Wilson took us on a trip down memory lane, reminiscing about NCSA Mosaic (which I also remember fondly from my early days on the WWW), his early work on Web standards—apparently he’s responsible for overlapping <B> and <I> tags—and adventures in social media. Of course, they didn’t call it that. But games like Nethack (through other people’s ghosts) and other applications allowed connections and interaction between people, mediated by technology. And isn’t that what this conference is about?

Wilson cautioned us: There are people that need to learn how to play well with others. What voice should you use? How much should you share? Sharing feels good. It makes you vulnerable, but you create lots of real connections. I guess it’s up to each of us to choose how far to take it. He closed off with a quote from the late, great Douglas Adams

I may not have gone where I intended to go, but I think I have ended up where I needed to be

A Code of Ethics For The Social Web

Morten R-H again, this time discussing our responsibility, as bloggers, to the truth. This applies much more to journalism-style blogging, and reviewers, but everyone can benefit. Really, it boils down to a few simple principles: be honest with yourself and your audience; admit when you may be biased (e.g.: when you get freebies in exchange for reviews), be critical of your own biases and opinions. It is important to have such a code of ethics, and hold each other accountable, because anyone with a big enough audience has a big influence.

Trust relationships—brought up by an audience member who disagreed with Morten’s basic thesis—will only take you so far. It’s all very well to personally be critical of the blogs you follow and if you find they’re unreliable, well, to just stop following them, but (a) that does nothing to discourage unreliable bloggers, and (b) it doesn’t help people who don’t have working bullshit filters. If the Tea Party, 9/11 Truthers and the Huffington Post* have taught us anything, it’s that popularity has very little to do with truth.

(*Seriously, early on in the talk he lumped all three together. Awesome)

And here’s his code of blogging ethics

Looking Through The Lens

Alan Levine again, taking us through some of the ins-and-outs of taking good photos, both from a technical and creative standpoint. It was great stuff, but hard to summarise.

Stop Apologising For Your Online Life

Alexandra Samuel asks: is online life any less real than IRL? Are those three letters themselves a dead giveaway? She argues that no, life online is just as interesting and meaningful as offline. She proposed a new 3-letter term: RLT, meaning Real Life Too. Kinda catchy, though I’m not really feeling it. Still, who knows? It just might catch on.

Online art is just as valid and meaningful as offline art, just because you can’t hang it on a wall or show it off in a gallery. There is amazing stuff being done online, like the It Gets Better Project (and indeed, for a lot of queer youth, online is the only way to connect with other queer people); I’ll just add Pogo’s fantastic remixes.

But you also have a responsibility to your online life, as much as your offline one. Don’t be passive, invest real attention; give back, and commit to creating something real. Likewise, don’t just friend any Tom, Dick and Harry on Facebook. Friendship means something, online as well as off-. Only connect with people you feel a relationship with, not just faces that’ll increase your friend count.

Conclusion

I left early on Saturday, because I was still feeling a bit under the weather, but I’m so glad I went. Looking forward to next year’s Moose!