Blog

Drupal development, project updates, occasional knee / head slappers

Feb 15, 2011

The goal of this post is twofold: To thank everyone who reached out during this campaign, and to summarize and pass on techniques I learned in the process.

A thank you from me

It was really inspiring to have so many people respond to the campaign. There was great feedback from artists, lots of tweeting and re-tweeting, blogging and even financial contributions to a bounty to the person the generated the lead that would land Joseph his dream job. So a big thank you to everyone who stepped up, you are all very awesome. There's a lot of need out there, and it's hard to not feel so overwhelmed by it that doing anything feels too small, too insignificant. Whenever I see people overcome this and do small things for others, it moves me and helps me to get over the inertia of doing something myself.

I wanted to specifically thank a number of people:

Suzy Tennison - For being so generous and enthusiastic about the project
Glen Hilton - For lending enthusiasm, tweeting to his massive following, and passing on some good Twitter tips
Chris Dunmire - For posting the best writeup we got on his blog, and mentioning the project in his Creativity Portal e-zine
Patrick Lee - For supplying a great lead, giving us the best quote of the campaign, and being an all around enthusiastic guy
Steve Goad - An awesome artist who gave some excellent advice on navigating the freelance art world, and wrote up a nice post
Scott Morton - For giving some tips on navigating the video game industry
TheFinalHikari- For contributing a nice, Save Joseph-inspired poem
Josh Brauer - For offering some really good thoughts on the campaign as a whole
Laura Boergadine Sapp - For some great artist-to-artist advice

If I'm missing anyone, please let me know and I'll add them in.

A thank you from the Joseph

Joseph wanted to post a thank you to everyone that lent their resources to the campaign. I believe he's putting it in his blog, but I wanted to re-post here for folks following via my blog:

About a week and a half ago I was talking with a friend about my current job situation, and how it was about to to effect my life dramatically, a classic struggle between passion and stability in my professional life. Chris wanted to help in any way possible, andn asked me if I would be interested in doing a "little experiment" with him, to try to create a buzz, around my artistic and creative abilities, let my current plight be known , and in doing so, see if he could generate some job opportunities for me. I agreed, and without another word Chris went to work on the project with an explosion of energy and enthusiasm, exploring every conceivable avenue to get me exposure, including reaching out to anyone who heard my story to come back with suggestions of there own. The feedback was amazing, everyone took time out of there busy lives to review my work, and point me in directions of possible job opportunities! Every ones effort was overwhelming, especially on Chris' part, who devoted many tireless hours to the project! I don't have a job in the art field as of yet, but the project has generated some exciting prospects, and it has opened many doors of opportunity. I just want to give a heart felt thank you to everyone involved, for reaching out to help.

Regards,
Joseph Cowman 

A wrapup of techniques

I spent 4-6 hours a day for a week or so working on the campaign and leveraged it as a great excuse to really assess what I know about marketing, about social networking, and use it as a catalyst for generating some new ideas and techniques. My hope was that taking the machine-gun approach would help me land on something viral that would really take off. Nothing quite did that, but the efforts generated about 600 unique visitors over the course of a week. This is by no means viral, but it's respectable. For a newer artist, getting your work in front of 600 people can take some doing using traditional means. Also, there will be a long tail of visitors from here on out from the links and coverage out there on the web that will probably double that number in the next couple of months.

For those are are contemplating embarking on a similar venture, here's a pretty much exhaustive list of everything I tried over the course of the 10-day campaign:

  • Registered a unique domain name (savejoseph.org) and pointed it to a blog page on my personal blog. The idea was that the campaign could have some branding, but some time could be saved in leveraging an existing site with a good commenting system instead of spinning up a new site. The plan was that if there was time, a single-page site would be built in its stead. I'm curious if this had any negative effect on the campaign, seeing the savejoseph.org page branded as my personal blog. I only got one bit of feedback from someone who noticed, but if people were turned off, they might not have said anything.
  • Created a countdown image that could be added to a web site in support of the campaign - I have no idea if anyone used this besides me, but it was a fun project
  • Added a ChipIn to allow people to donate small amounts to a bounty that would go out to the person who generated the lead leading to a job. Only to people donated (and I was one), but it seems like if I had tweeted more about this, I would have gotten a better idea of how many people would have used this.
  • I wrote a press release and had a virtual assistant in India put together a list of publications that might want to feature the story. One of the ones they found was Creativity Portal, the author of which did post an article which has been driving a little bit of traffic to the campaign.
  • I submitted the press release to the Idaho Statesman and the Boise Weekly, but did not receive a response.
  • I had my virtual assistant put together a list of sites where you could do a press release for free, but I didn't get that done before the campaign ended.
  • I submitted the story to Mashable, but I don't think they covered it.
  • I submitted a request to Malcom Gladwell asking for advice (hey, you have to try!). I got a funny little response that could possibly have been automated in some way (probably his virtual assistant).
  • I posted a request for advice on http://www.deviantart.com/, which didn't get many responses. I kind of got sucked into the site and commissioned a couple pieces of art based on the campaign (to seed the idea of getting other artists to donate small, derivative works in support of the campaign), and ended up having a great conversation with an artist that had some great advice and an inspiring attitude. I would have liked to have connected with more people this way.
  • I posted questions on Mahalo and Yahoo Answers requesting suggestions for the campaign. The idea here was to garner advice, but with the thought that the people who answer questions on those sites may have seen questions about people looking for artists. Also, I was thinking that the people who read the question might become curious about the campaign. I didn't get any responses, and it's hard to track if people came to the campaign from those sources, so I'm not sure what the sum result was.
  • I spent several hours doing a video interview with Joseph, with the idea that if people could get a better feel for his personality and the neat things he's done, it would make him more real. I would have made several short videos and posted them to a blog, YouTube and Blip. However, at the end of the interview my computer ran out of batteries and shut down, corrupting the video file, so it got lost forever. It was such a time-consuming process that we weren't able to find the time to do it again.

Leveraging Twitter

  • Created a dedicated twitter account and tweeted throughout the campaign - This didn't seem nearly as effective as leveraging existing accounts, but seemed like an important thing to do
  • Tweeted regularly from my account, and had these tweets sent to Facebook - Being able to tweet to Twitter and have it update my Facebook status was a nice little time saver. Actually, what I would do was create a message in Evernote, give it a twitter tag, and it would post to my blog, which would then post to Twitter and Facebook, so I was able to tweet very rapidly across multiple social networks.
  • I asked several influential friends to give me advice on the campaign, which allowed them to assess weather the campaign was newsworthy enough to cover themselves without having to say 'um, I don't write about this kind of thing'. Plus, I got a lot of great feedback from going that route.
  • On a suggestion from a friend, I started adding Plz RT at the end of a post to encourage people to spread the word, and that seemed to work well.

Summary and brief contemplation on measuring success

In order for this story to have become viral, I think we would have needed to do something a little more outrageous. I stuck to more conventional channels because I wanted to make sure we had a good framework for launching other efforts. Also, outrageous requires a lot more creative thinking and potentially time. If I had to do this again, I would start with a brainstorming session on creative, silly, wild things we could potentially do to create buzz and see what direction that took. Setting the foundation will generate a nice long-tail of visits, and help to consolidate any sort of marketing Joseph does in the future, so I think ultimately it was a good place to start.

The Save Joseph campaign was a perfect proof that in general the path is just as important as the goal. Over the course of the Campaign, I learned a ton about social networking, met a lot of great people, saw strangers stepping up to do what they could to help, extended what I knew about how artists generate jobs and interest around their work, and in the course of all this helped to generate several leads that may well prove to achieve the end goal of the campaign - to find Joseph a job in the art world.


Now, I did realize from the outset that there was no way I could know if this venture would be ultimately successful if judged by that end goal. I'm confident that there's work out there, but not certain about how much I could accomplish as an outsider. However, I did know that if judged by the measure of learning and pushing the bounds of what I know I had a lot of control over the success of the project. On those grounds, my hopes were high and I was not disappointed.

Feb 15, 2011

What does a monthly archive block achieve?

I'm not sure how many people actually visit archive links for blogs. It seems like there are more natural groupings of posts, either by tag or the basic pagination, so I think it's likely not a terribly useful browsing pattern. However, there's three things do like about them:

  1. It makes it easier for other people to track your posting frequency
  2. It makes it easier to track your own posting frequency
  3. It helps distributes internal link juice in a permanent way

From what I've heard - and almost all my SEO knowledge comes second-hand - one commonly overlooked method of improving the ranking of a page is using internal links well. Google sees each URL as its own entity, so in addition to garnering incoming links to boost the PageRank of a page, you can also use internal PageRank and it works the same way.

The idea is that each page has a bucket of rank to pass out. If you pass that rank around internally, you can get a nice boost in overall ranking. But, it's important that the links stay constant on a page, since Google tracks the age of links. So while taxonomy pages do a good job of passing out links, the links on their pages may change if they're sorting from newest to oldest.

Archive pages, on the other hand, will always have the same links on each page, so if this internal linking theory is valid, it's a good method to use.

How to set up the archive blog and pages with Views - The easy way

After I put together this blog post, a reader mentioned that there is an archive view that comes bundled with Views. I gave it a test run and it had enough of the same properties of my archive view that I'm pretty sure I must have just cloned it a year or two ago. So, if you want to go the easy way, just enable that and configure it to your liking. If you're wondering how it works or want to set it up manually, read on.

How to set up the archive blog and pages with Views - The manual way

Even though Drupal doesn't come bundled with an archive view like Wordpress, it's pretty easy to set one up with Views.

First, create a new view and add a Block display. 

Set the display to show a high number of items. I want all months to display, so I have it set to 30 for now. The screenshot is from Views 3 Alpha:

Set the filters to match whatever is showing up in your blog. In my case, it's just nodes that are a blog content type.

Next, we need to add an argument for year and month. So, click on the plus sign next to the argument box and select Node: Created year + month:

Next, we just need to select Summary, sorted ascending under Action to take if argument is not present:

You could also select Summary, sorted descending if you wanted the most recent month to display at the top.

By default, the list of months will display as a list with the number of posts per month. This is how I have mine set, and with a little styling it looks like this:

There are a few other options which you can explore by clicking on the link next to Style, which will be List by default and taking a look at the options:

The Jump Menu option sounds neat, but I couldn't get it to work with Views 3 Alpha.

Setting up the archive page

First, add a Page display.

Give the page display a URL:

From what I can tell - and it's been a while since I set this up - the only difference with the Page view is that I've set a title in the argument settings. So, click the override button to make sure this change doesn't apply to the defaults, and then click the edit link for Node: Created year + month and set %1 for the title.

You can test out this page view as long as you have some blog items already. In the Live preview section, add an argument in the YYYYMM format, like so:

In the example above, you would see a list of nodes for July, 2010.

Save the view and then set the block to display using either the block admin page (/admin/build/block) or Context (definitely check out the Context module if you haven't yet for block display settings, it makes SO much more sense). 

That's it, you should be good to go!

Jul 30, 2010

This tutorial is sponsored by the Save Joseph campaign. Only 6 more days to save one man from a roomful of teeth. http://savejoseph.org.

I've recently been using the Evernote module to blog, which has made my life surprisingly more rich. After building the module, I started using it right away and found it was the missing piece in creating a workflow that would encourage quality, rapid posting - something I've always wanted to be able to do. Now that its set up, I feel like I can write with virtually no overhead, and using images - kind of tricky when using webforms and wysiwyg - is about as easy as it can get. Even adding annotations is super simple with Skitch (writeup for a workflow with Skitch is imminent).

The ease with which I can create content made me wonder if maybe I could run an entire Drupal site's content off of Evernote. So I gave it a shot when setting up http://josephcowman.com, and it worked like a charm!

What I've done is set up four separate feeds in the Evernote module, three of which correspond to different content types, and a third which imports unpublished blog nodes with instructions for using and administering the site:

The Gallery feed expects notes with a single image. This image is added to an imagefield and is displayed in a gallery fashion on pages like http://josephcowman.com/gallery and http://josephcowman.com/gallery/untitled. The author can put the image anywhere in the post and it will be stripped out using the HTML input filter.

The Blog and Pages feeds, on the other hand, pulls any number of images in and replaces them with local copies of the images, so they would end up looking something like this blog post.

The idea in setting up the site this way is to make management of the content extremely easy. Since Evernote has a desktop application, all the site admin has to do is create or edit a page in Evernote on their computer (even offline), and any changes get pulled into the site on a cron run. So, no log-ins, no working with web forms, it's just working directly with the content without having to deal with the middle man.

I'd love to see more people experimenting with this kind of integration. It makes for a pretty tight workflow. I even take this a little further with my blog (a more detailed article will be forthcoming) by automatically Tweeting and sending my post to Facebook through Evernote as well.

Jul 29, 2010

This tutorial is sponsored by the Save Joseph campaign, a grassroots effort to find a good friend, stellar artist and all around amazing person a satisfying, creative job in the next 8 days. I know the Drupal community could use this kind of talent. Learn more about the effort at savejoseph.org. If you have any ideas on how I can get the word out about this, let me know!

My use case was that I wanted to be able to use social media icons for menu items so that we could re-arrage, add or remove items directly from the menu management interface:. The result is what you see below:

To use images for menu items in Drupal, the first step is to create an override theme function for theme_menu_item_link() in your theme's template.php file. The idea is to first run your image handling bit to switch out text for images, and then hand it over to the parent theme to do the rest. In my case, I'm using the Zen theme.

/**
 * Implements theme_menu_item_link()
 */
function yourtheme_menu_item_link($link) {
  // Allows for images as menu items. Just supply the path to the image as the title
  if (strpos($link['title'], '.png') !== false || strpos($link['title'], '.jpg') !== false || strpos($link['title'], '.gif') !== false) {
    $link['title'] = '<img alt="'. $link['description'] .'" title="'. $link['description'] .'" src="'. url($link['title']) .'" />';
    $link['localized_options']['html'] = TRUE;
  }
  return zen_menu_item_link($link); // Let Zen take over from here.
}

Be sure to change the yourtheme in the function to the name of your theme. Also note that this only checks for .png files. If you want to use a jpeg or a gif, you will need to modify the code slightly.

Next, clear the theme registry (CTFC).

Now, you can use image paths instead of text for the image, as seen below:

Jul 26, 2010

This tutorial is sponsored by the Save Joseph campaign, a grassroots effort to find a good friend and stellar artist a satisfying, creative job in the next 10 days. I know someone in the Drupal community could use this kind of talent. Learn more about the effort at savejoseph.org.

I have 10 days to find my friend a job, and as part of this effort, I wanted to create an image people could use on their web sites that would dynamically change each day. My first thought was that imagecache would be great for this, but there are two issues that make dynamic text in imagecache tricky:

  1. Imagecahce images are... well... cached. Once they're made, they don't get re-made until you flush the cache.
  2. Browsers cache images too, so even if the image was refreshed on the server, the client-side image wouldn't change from one day to the next.

I was able to work around these using a couple of interesting techniques. The end result is something that looks like this:

Before you start, you'll need to download the Imagecache Actions module to add the ability to overlay text on an image.

The first step was to create the background image. I created the image in Photoshop with an empty space where the countdown was supposed to go:

Next, I created a new imagecache preset to overlay text. It's down there at the bottom:

I changed the following settings:

  • Font size: 9
  • X-offset: center
  • Y-offset: top+40
  • HEX: #FFFFFF

And for the text, I checked the Evaluate text as PHP code box, and used the following code:

$interval = strtotime('August 5, 2010') - time();
$interval = ucwords(format_interval($interval, 2) . ' left');
return $interval;

August 5th is my deadline, and what this code does is use the awesome format_interval function to create a string based on a time difference in seconds. I've set the granularity to 2 so that right now it will say 1 Week, 2 Days but in a few days it will say 6 days, 4 hours.

Next, I uploaded the background picture to the theme directory of my site. Then, I used the imagecache theme function to load up the image with the overlay:

theme('imagecache', 'save_joseph_box', path_to_theme() . '/images/save-joseph.png');

Then, I put this in a page preprocessing function in template.php and assigned it to a variable that I could use in my theme. This is really temporary code so that I can copy the output, so it could have gone anywhere.

function jc_preprocess_page(&$vars, $node) {
  $vars['save_joseph'] = theme('imagecache', 'save_joseph_box', path_to_theme() . '/images/save-joseph.png';
}

Then, I just added a print statement in my page.tpl.php page so I could see the image. Embedding this in the page template temporarily allowed me to play with the imagecache settings until I got the font size and positioning right while seeing a preview:

  <?php print $save_joseph; ?>

Okay, now we have a functioning text overlay that at least is current as of this moment. But, tomorrow, the image will be out of date. So, we need to flush this imagechange to get a re-rendering of the image whenever the text changes. Here's the strategy I used:

  1. Set up a hook_cron function
  2. In the function, use the same code above to create a textual output of the date.
  3. Load a variable that has the last textual output saved (the first time, this will be blank)
  4. Check if the new time and the previous time are different
  5. If so, clear the iimagecache
  6. Save the new text string to the variable we used before

And here's the code to do it:

function common_misc_cron() {
  $interval = strtotime('August 5, 2010') - time();
  $interval = ucwords(format_interval($interval, 2) . ' left');
  $last_time = variable_get('jc_save_time', 0);
  if ($interval != $last_time) {
    imagecache_preset_flush(array('presetid' => 'save_joseph_box'));
    variable_set('jc_save_time', $interval);
  }
}

Now we'll have an up-to-date image all the time. Except that browsers will cache images for a while, so we need a way to make the browser think it's a unique image every time to pull it fresh from the server. The way we do this is by adding a dynamic query string to the end of the image URL that will change randomly on every page load.

My goal was to make it really easy to put this image on a web page, so I needed a way to bundle this dynamic-ness with the image. So, using PHP to generate this string was out of the question. The way do to it was to use JavaScript to add the query string to the src of the image tag:

<script type="text/javascript">document.getElementById("save_joseph").src = 
document.getElementById("save_joseph").src + "?unique=" + new Date().valueOf();</script>

For folks that can't use JavaScript (in Facebook and MySpace, for example), I also provided an image that just had the end date on it, so it could be static. Not as cool, but at least functional:

Finally, I added the script with the HTML image output, copied it, and put in in a blog entry so that people could copy and paste the code to use on their sites.

Feb 16, 2011

Galleries and potential employers

You can contact Joseph directly through his contact form, or contact me through mine.

The story

In 10 days, an amazingly talented artist and friend, Joseph Cowman, will be forced to choose between a full time position building false teeth factory-style for the financial security it will bring has family OR possibly lose his current part-time position, straining his family but opening up the possibility of spending more time on creative work.

I think there's a third choice, but it will require a grassroots effort to make happen. I'm certain that there are positions available out there that will allow someone as skilled as Joseph to practice art and be creative but still earn a good livelihood. So, I'm tapping into my network and cashing in favors to see if I can find Joseph a job where he can really flex his skills.

If you want to learn a bit more about Joseph, keep reading. Or, you could jump straight to how you can help. This a grassroots effort, and there's something YOU can do!

Links

A few examples of Joseph Cowman's work

A referral

Joseph is probably the most capable person I know, and I think the only two reasons he hasn't landed a fulfilling position is that 1) he lives in a small town, which makes networking in the art world difficult and time-consuming and 2) between work, family, and practicing his art, doesn't have much time to get his work out there. For years I (and most people who know Joseph) have felt like there's this huge talent going to waste, like the world is just a little lamer because Joseph is building teeth instead of really pushing the boundaries of what he can do.

Anyone who has ever hired Joseph has loved working with him, and from knowing him on a personal level, I can understand why. In addition to being able to pick up anything, figure it out and then push it beyond what most people would, he's incredibly patient and empathetic, making him sensitive to other people and what they need. It's an interesting combination, one I don't run across very often.

The dream job

After talking with Joseph for a bit to figure out what kind of position he's looking for, he said anything that would be artistically challenging that has good variation. He said doing character work or design for games would be perfect, and he's also capable of working in a variety of styles. The bottom line is that he wants to leverage his work time to help hone his craft and improve his skills as an artist. Challenge and variety are key.

Joseph has been building false teeth for the last 7 years, and I anticipate him really exploding into whatever work that he takes on next. If it's artistic, he's going to do a fantastic job because he'll be so enthusiastic about it.

How YOU can help

Here's what you can do to help:

  1. Follow the campaign on Twitter
  2. If you know of any job opportunities along these lines, send them to me or directly to Joseph through his web site.
  3. Pass this story on to anyone you know who might be able to help with this effort. Anyone in any art-related industry, artists, empathetic people, sneezers, anyone. This is grassroots, and every root counts.
  4. Tweet about the campaign, and re-tweet!
  5. Give us any ideas you have on how we can improve the campaign, techniques we can use, tactics we can exploit
  6. Add the image countdown code to pull in the countdown box you see below to your web site, MySpace or Facebook page.
  7. Add comments to this post about interesting things that you know Joseph has done, any praise, whatever. If you take a look at his art and like it, mention it.
  8. Refer us to any artists you know who might have ideas on how to break into the biz
  9. Add a small amount to the Save Joseph Bounty that will be be awarded to the individual that provides the lead that lands Joseph a job

The Save Joseph countdown box 

To add the countdown image below to your web site, use the following code:

<a href="http://savejoseph.org"><img id="save_joseph" title="" alt="" src="http://josephcowman.impliedbydesign.com/sites/josephcowman.impliedbydesign.com/files/imagecache/save_joseph_box/sites/josephcowman.impliedbydesign.com/themes/jc/images/save-joseph.png"></a>

<script type="text/javascript">document.getElementById("save_joseph").src = document.getElementById("save_joseph").src + "?unique=" + new Date().valueOf();</script>

Note that even though the image will work in sites like Facebook and MySpace, the little script that's added to it which refreshes the image regularly to reflect the countdown change won't work. In those cases, you can use the static image which doesn't use a countdown:

<a href="http://savejoseph.org"><img id="save_joseph" title="" alt="" src="http://josephcowman.impliedbydesign.com/sites/josephcowman.impliedbydesign.com/themes/jc/images/save-joseph-static.png"></a>

Some of the interesting things Joseph has done outside of fine art.

Joseph has focused a lot on his artwork the last several years, but his creative prowess extends in a lot of other directions. He's the kind of guy I am always telling other people about because the interesting things he's done. I'd like to get these a lot more coverage, and I'll add pictures as I get them, but here are just a few of the ones that have impressed me the most:

  • When I met Joseph, he was 17. One of the first things he did was show me a fully functioning robotic arm he had built entirely out of scrap wood, hypodermic needles and IV tubing. No metal, no batteries, the whole thing ran off of the hydraulic pressure between two needs hooked up with the tubing. It was one of the coolest things I had ever seen.
  • The next thing he showed me was a robotic hand, complete with 3 fingers and an opposable thumb, that connected to a glove you could put on your own hand to move the robot hand. It used bike cables as tendons. It was made out of a box of old random parts that his family had laying around. Also one of the coolest things I've seen.
  • Then, he showed me a graphics program he had programmed on his computer in order to create graphics for a video game he wanted to make. It was more functional than any of the graphics-oritented programs I had on my computer.
  • He built a series of didgeridoos out of driftwood with awesome artwork around it. He had to use a drill to hollow out the entire thing, using old tools. They're the prettiest didges I've ever seen.
  • Back in the day when cool looking Oakley sunglasses were beyond his ability to purchase, he and a friend made their own pairs from thick aluminum sheet metal and cut their own lenses. At the time, they were really impressive.
  • Every Halloween Joseph puts together a stellar costume. Stuff that could win prizes. Last year he built a realistic ogre head out of cardboard and vinyl. The year before, he built a costume that made him look like he was riding a dinosaur. It was really effective.
  • Joseph and his wife completely renovated their entire home. When you walk through the house you can see the creative touch, and it looks beautiful.

Art inspired by the Save Joseph campaign

Save Joseph 

by TheFinalHikari

A man of great talent
Creativity abound
The kind heart of a father
The spirit of a dear friend
The mind and skill of an artist
Seeking new opportunity

Dreams and aspirations
Decorate every canvas of life

Skillful and trained hands
An eye for perfection

Please do not depart
Before you have seen it all
For every picture tells a story
A flowing rhapsody of inspiration
Communicating wordlessly
Feelings from you to me
Captured in the eternal beauty of art

Every single helping hand
Is welcomed to reach out

The choice is now yours
The request is simple
He needs your help, whatever you can do
Help him build a new future
To enrich the world with art

Within every masterful piece of art
There is a world to witness
They say a picture is worth one thousand words
But his art is clearly worth so much more

The choice is left to you
And until then,
Everyday
We shall pray
“Save Joseph…”

Jul 24, 2010

It's my 6th day outsourcing, and I've assigned a few tasks and gotten responses. Here's a summary of the results:

Task 1: "Spend 30 minutes to an hour brainstorming any other ideas for increasing the number of readers to my blog"

This task was a good one because it brings up a good question: Is it worth outsourcing question that you can find decent answers for with a quick Google search

After 2 days, I was sent a report that includes 26 ideas with headings and short paragraphs. No sources were sited, so I did a search on a few sentences from the report to see if I could find them. The result was a compilation of 2 articles that show up near the top of Google for a search for Ways to increase blog readership. I actually ended up liking the article at the top a little better, an article not referenced in the report.

To complete this same task myself took me a couple minutes, and I found results that were better suited to where I am.

Would it have been worth it to clarify the task, and give some background about who I am, about what I know already? What would I say? What bits of knowledge that would give someone else the ability to predict what kind of information I would have appreciated for this particular task? I'm not sure I know. My guess is that attempting to articulate it would have taken longer than completing the task myself.

Task 2: Trip ideas to Canada

My wife and I want to hone our Canadian accents but we don't really know Canada, and my wife's extensive searches online weren't turning up any compelling results. I decided that maybe having someone else narrow down some choices could help. So, I sent this to my VA:

I need to plan a trip with my wife in mid-August, leaving a Friday morning and returning a Monday evening. We would like to go somewhere in Canada, but have a limited budget. We'd like to find a few options of places that aren't too expensive to travel to, but that are nice, ideally on the coast. Can you come up with 4 or 5 ideas for places that meet this criteria with the least expensive cost of a plane trip from Boise, Idaho? When you send me details, please send links to the airfairs online as well as any information you gathered about the locations.

I got a report back 12 hours later (not bad) with a list of 7 different places in Canada, with screenshots of possible Orbitz flight itineraries for each one. Tickets were understandably a little high (up to $600 per person), but what got me was that several of the destinations were 400km from the nearest airport. How can this person be so disconnected from the task that they don't recognize that two 8 hour plane trips plus two 8 hour drives aren't practical for a 4 day vacation?

Was my fault that I was not specific enough? Or that I haven't established enough of a relationship yet with these folks to have them care enough about the tasks that they apply a certain level of reasoning to them?

Or, is an 8 year old kid in some VA sweatshop performing these tasks?

Now, this company got great reviews on Elance, with lots of feedback, so I know that they're capable of good stuff. It's just a matter of figuring out how to get that good stuff.

The state-side VA

I hired a state-side VA, but she is on a family vacation until Friday. It makes me realize that if I become dependent on a VA, I would need backup if I went with a single person.

Summary of emotional state

So far, this hasn't been a superb experience, but I also know that I'm still learning the ropes. I recognize that part of this might be that I just am not coming up with the right kind of task. But, they're tasks that were intended to build my confidence in the process so that I could leap in with more important stuff.

Another issue is that I wonder if my current life structure is possibly not suited for outsourcing. I've simplified what I do down to a handful of areas that are all things that I want to be doing. What I do for work I want to do myself. At home, the only things I would want to outsource are the dishes, laundry and mowing, all tricky tasks for a VA. Research seems like the only thing that comes to mind, and so far it looks like Google will give me better, more varied answers. I have a finely tuned set of tools for managing information and reminders, so I don't need someone to keep me abreast of what's coming down the pikes.

Now that I'm looking at it from this angle, my life is actually really simple. Almost anything that's on my list of things to do are things that I actually want to do because of the experience. That, or it's home repair and maintenance. If I was running a multi-person company, if I was doing extensive research on some subject, if I had a flood of e-mails to deal with, I could see the value of a VA. But what can I outsource right now and get a positive net gain?

One thought is that by knowing I have a VA waiting in the wings, maybe I will be more willing to take on things that would normally add complexity to my life, things that would be perfect for a VA.

I'm going to hang in there for a while and give myself time to really internalize the idea of relying on a VA. If the tasks are little banal, I think that's okay because I'm practicing and the hope is that eventually I would learn how to offload more significant tasks.

Jul 29, 2010

Up until a month ago, I hadn't had very good experiences managing commenting on Drupal blogs. Even with the hoops that commenters had to go through to write a post (i.e. long and frustratingly ambiguous captchas), tons of spam still got though, and the whole administration process was rather unwieldy. The e-mail notification modules available at the time were a little too in-depth, sending e-mails on new comments as well as new or updated nodes. Also, because of the spam, I'd set comments to only be published on approval, adding additional lag time to the discussion. It was a poor experience, and even I loathed posting comments on my own blog!

In setting up a blog for my Drupal training companyBlue How-To (currently a coming soon page), I decided to get things right. The installation was also going to be core to a multi-site that would include several other sites as well, so I'd be able to leverage the techniques across multiple sites. 

What I wanted in particular was:

I scanned through the Drupal modules matching the phrase comments and found a few gems, did the same in Google, and got started.

The modules you'll need

Spam
Comment Notify
Rules
Ajax Comments
Comments Bonus API (dependency for Ajax Comments)

Dealing with comment spam

The first step was figuring out how to deal with spam. I was using image captchas from the Captcha module. I had given Mollom a try on other sites, and while it will be my fall back if I end up needing captcah, I've gotten a lot of false positives in the mode where they show a captcha only if your content looks spammy (particularly on groups.drupal.org).

In my searching, I came a across a couple of easy-to-apply techniques using hook_form_alter(). The first is to add a text input that is hidden via CSS on forms so your users don't see it, but any bots will. Using a validation function, you check to see if the input is filled out, and if it is you throw an error and don't submit the form. I was familiar with this technique from way back and even used it in my first custom-made CMS, but it had slipped through the mental cracks.

Here's the code I use for this, which is slightly modified from the original. I was having issues on node forms, so I set it to not display there. I would also suggest changing the name of the input so as to not make this too predictable:

$form['#validate'][] = 'common_misc_honeytrap_check';    
if (strpos($form_id, 'node_form') === false) {
  $form['comment_body_two'] = array(
    '#type' => 'textfield',
    '#weight' => 0,
    '#required' => false,
    '#default_value' => '',
    '#attributes' => array('class' => 'honeypot'),
  );
}

We need to add a validation function to do the final check, and here it is:

function common_misc_honeytrap_check(&$form, &$form_state) {
  if (!empty($form_state['values']['comment_body_two'] ) ) {
    watchdog('notice', 'SPAM attempt at '
.$form['form_id']['#value'].' form', NULL, WATCHDOG_NOTICE);
    form_set_error('comment_body_2', 'Oops, you probably didn\'t mean to do that');
  }
}

So, if there's anything in this particular input, it will trigger the error.

The second thing we can do is set a timer on the form. Using this technique, we will add a hidden input with the current time to the form, and in a validation function make sure that it has taken the user more than a few seconds to fill out the form and throw an error if the submission un-humanly quick:

if ($form_id == 'comment_form') {
  $form['timegate'] = array(
    '#type' => 'value',
    '#title' => 'Timegate',
    '#weight' => 5,
    '#required' => false,
    '#default_value' => time(),
  );
}

I added the validation to the validation function above. Note I've set this to 10 seconds, but you can set it lower or higher.

if (time() < ($form_state['values']['timegate'] + 10 ) ) {
  form_set_error('comment_body_two', 'We KNOW you can\'t be THAT fast.');
}

Because I personally submit some forms faster than 10 seconds, I wrapped a check for an administrator role around both validations so that I wouldn't trigger the errors.

Setting up the spam module

These two techniques seem to work really well to stop automated spam. For spam that is produced by spam sweatshop laborers, I installed the Spam module. I enabled all of the included modules, but after a problem with one post triggering the Bayesian filter by beginning with the word "Thanks", I turned that one off. In the Custom filter, I added a regular expression so that I can add spammy words to as I discover them. Notice the <code>\b</code> around a word that could legitimately be part of some other word:

(bad_word|another_bad_word|\bword_that_could_be_in_some_other_word_but_is_still_bad\b)

So far, I've just had a couple of spam comments that could have been caught with the custom filter. It's a huge improvement, and there's no captcha to get in the way for real users.

Integrating simple notifications 

In a previous iteration of this blog, I used the watcher module, which had some nice features. I did some heavy CSS styling on it to match up the look, but I always kind of felt like there might be a better way.

I started by installing the Notifications module and attempting to chisel down it's many features to particular one I was looking for, which was customizable comment notifications. Ultimately I got the feeling that there had to be something more suited to this particular need. 

I finally landed on the Comment Notify module, which is what I'm using now to provide the nice "Notify me when comments are posted" feature:

The default e-mail that goes out for notifications is pretty heavy, so I trimmed the text a bit. You can find this setting at /admin/settings/comment_notify:

Hi !name,

!commname has commented on: "!node_title"

You can view the comment here: !comment_url

Below is the text of the comment:
!commtext

You can stop receiving emails when someone replies to this post,
by going to !link1

You can set up auto-following feature for all future posts
by creating your own user with a few clicks here !uri/user/register

Thanks!
Chris

So far, I've had a lot more repeat participation on my blog.

A special e-mail notice to administrators with some additional information 

Comment Notify is good, but it would require an administrator to manually sign up for each post. In addition, spam that got added but not published wouldn't send out any notification. As an administrator, I also wanted more information about the user that posted the comment, so I used the Rules module to set up an e-mail that got sent out whenever a comment was created.

In the first step, I set up my rule to be triggered when a new comment was saved:

Next, I set up a condition to check that the user doesn't have the administrator role, to make sure I don't get alerts for my own comments. Then, I added an action to send an e-mail to an arbitrary address:

Below is the text of the e-mail I'm sending out to myself:

Node title: <?php echo $node->title;?>


URL to comment: <?php echo url( 'node/'. $node->nid, array('fragment' => 'comment-'. 
   $comment->cid, 'absolute' => true));?>


User info: <?php echo $comment->name . '  '. $comment->mail . '  '. $comment->homepage;?>


<?php echo $comment->comment; ?>

Improving the usability of comments 

The main tool I found for really making the commenting process a more pleasant experience was the AJAX Comments module. With it, you get a ton of really nice ajax-y features:

  • When a user posts a comment, it loads it into the body via AJAX
  • You can administer comments via AJAX (to change the author, mark it as spam, etc)
  • Delete a comment via AJAX, with a key combination that will allow you to bypass the javascript approval dialog if you need to delete a bunch of comments.

It's really nice, and makes commenting and administering comments very fast. Working with comments is actually a pleasure now instead of a chore due chiefly to this module.

There's a couple of caveats, though:

  • AJAX Comments doesn't integrate well with Captcha or Mollum. The initial Captcha will show, but after that, no dice.
  • The comment Preview feature doesn't work
  • If the comment triggers the spam module, the user will get a not-so-helpful error dialog box instead of a useful inline error.
Jul 22, 2010

I finally got a chance to install the Managing News Drupal distribution the other day, and it's pretty slick. The idea behind it is to aggregate news feeds and allow multiple users to collaborate on organizing, commenting and sharing the items with others. After hearing what some people are doing with it, it made me really excited to use it on my own projects.

Below is a walkthrough of installing and working through the default features of Managing News, documented as I went through the process myself.

Installing Managing News

Download the distribution from http://managingnews.com/.

As with any Drupal installation, you'll need to:

  • Create a database
  • Have a domain or folder in a domain to work with
  • Copy the default.settings.php file in /sites/default to a new file called settings.php

Once you're ready to install, go to the folder and select "Managing News" installation profile and click "Save and Continue"

Fill out the database information, click next.

Fill out the user account information, click next.

You should now see the main Managing News screen:

Adding feeds

It sounds like the first think I need is a Feed, so I click on the Feeds button and type my blog's RSS feed into the Feed URL field and click "Preview." This is what I get:

Okay, looks like the preview features doesn't work, so I click Save.

Looks like it imported, here's what I see now:

Sharing

Now it's time to explore some of the features. I'm going to take a look at the Share feature.

Nice, I can share via Twitter, Facebook, MySpace or E-mail. My first thought is that there should be an Evernote link here, too, since I use that as a funnel to the other channels.

When I click the Twitter link, it takes me directly to Twitter, where I have to log in. After I'm logged in, I click the Twitter link again, and Managing News pre-populates my status box, including a shortened URL, nice!

When I click on the Facebook link, it gives me the option of posting a "share" on Facebook, with a couple other options, including connecting up a status update or sending the share as an e-mail. I'm not familiar with the Share feature, so I had to look up. Here's a bit about the Share feature for Facebook developers. Here's what the screen looks like:

When I click on the E-mail link, it populates an e-mail, complete with shortened url, like so:

Okay, this is nice and very straightforward.

When I click the Trash button, the item collapses in a nice, ajax-y fashion.

Editing tags for the posts is nice, too:

  • Click the edit button
  • Start typing tags, separated with commas
  • When you press Enter or click away from the tags, it will save the tags and make them clickable links, which will then direct you to a listing of all items that match that tag.

Getting a map error?

There was an error in the map rendering on the home page which made me want the mapping features even more:

So I added Development Seed's rss feed, figuring that if anyone had geolocation data in their feed it would be them. And sure enough, here's what the map looked like afterwards: 

That's sweet.

Viewing options

Up near the top of the page are some different viewing options, so I thought I should explore those:

When I click on the map, I get a larger rendering of the same map I saw above:

It took me a minute to figure out what the difference was between the News and List view (you can hover over the icons to see what they are), but I think it's just that the List view doesn't have snippets, only titles, so the output is a bit more concise.

Embedding Managing News Widgets

I got pretty excited when I saw the Embed link in the lower right hand corner of the page. When you click that, you get a preview of the widget plus embed code that you can then copy and paste into a web page. You can embed a preview map by going to the map view and clicking Embed, or a list view by going to News or List and clicking Embed. Here's what it looks like when you click on the Embed ink in the News view.

I tested it out by creating a dummy, pure HTML page and pasting the code in. It works! Here's what the Map preview looks like on an HTML page with nothing else on it:

So, this could be a very cool way to let other people share your aggregations.

Map layers

In the upper-right corner of the Map view, there's a cute little button that looks like a stack of papers. If you click that, you'll get some options on what layers you'd like to see on the map:

The OSM Maplink layer shows country names, and when you zoom in you can see roads and other borders as well:

In the lower right-hand corner, next to the embed options, is an account link. If you click that, you'll see some settings for your account:

Searching and saving searches

The Search view leverages Drupal's search infrastructure to search, so the first time you go to the search page, you probably won't be able to see much. Drupal's search compiles the index on cron runs, so eventually you'd want to set up cron to run on your site. However, you should be able to update the index manually by clicking the Update now link in the search index box:

I clicked the button twice and got the follow error, but that's because only one instance of cron can run at a time:

When I do a search for Great, I see a couple nice things. First, the instances of the text are highlighted, and second there is a Save this search button:

Clicking the button adds the search to the side Saved searches box:

Creating a channel

Okay, on to Channels. When I click the Channels link, here's what I get:

I click on the Example channel item, and it gives me some instructions:

I click edit, and add the test tag to the channel, which I've already added to a couple of articles. I run into a funny little visual error, where the submit buttons are hidden, but if I keep scrolling down they re-appear:

When I've submitted the form, I get a listing that renders pretty much the same as the Search or News listing, but contains matches for the tags I've set.

Between the Search and Channel features, I felt like there was some common ground. If you could do a search based on 1) keywords, 2) tags and 3) specific feeds, the channels would be the saved searches.

Subscribing to RSS feeds

Managing News generates RSS feeds for any News, Tags, Search or Channels. Just navigate to the page you'd want to subscribe to and click the RSS Feed button:

Printing

Clicking the Print button above lets you print a nicely formatted list of feeds so you can read them later on:

This looks pretty slick, but would be more practical to me if could print out the entire body of the post.

Help

Clicking the ? icon in the upper right-hand corner of the screen will give you contextual help. If you click it on the home page, you'll get something like:

The is some basic help for all of the main tabs above, but none for saved searches or tags.

Additional notes

Nice input descriptions

I really like the conditional display of help text for inputs. It keeps the clutter way down. Here's an example:

The help text only shows when you are filling out or hovering over an input. Nice! I'd like to know if there's a module for that, or if it's theme based.

Modules used

To find the modules used by Managing News, you can go to /profiles/managingnews/. There are three folders there, and here are the contents of each:

contrib:

custom:

features:

Syndicate content Syndicate content Syndicate content Syndicate content Syndicate content