Web Case Study: Fulfilling the Need for a Unique Approach to College Recruitment

Getgoingtoday.org was designed as a platform for Drexel University’s new brand voice

  • Share on Google
  • Share on Stumbleupon

Creative Approach

Getgoingtoday.org was designed as a platform for Drexel University’s new brand voice: a voice that embodies rebellion, authenticity and inspiration. The challenge was to capture the attention of prospective students in a manner that didn’t come across as just another heavy-handed marketing campaign. It had to feel entirely authentic; not just to potential students, but it had to carry its relatable, believable voice through to all human beings in general. It needed to be real.

In need of a place to start, we did quite a bit of web sur?ng and investigated what positive messaging and media is currently being shared across the popular social channels. We noticed—and were interested in—a higher-than-average occurrence of users sharing inspirational quotes with each other: to be funny, to be uplifting, to be friendly...the phenomenon seemed to carry just as much weight digitally as it did in a literary sense, which was in turn, inspiring. From here, we decided to try and push things further and create a large amount of independent, sharable assets formatted for all populate social media channels that could also collectively live as one highly sensory story.

  • The storytelling had to shine with minimal distractions, meaning that as the user you shouldn’t have to think about where you’re going next. The UX element of the site is completely open and organic in its approach, as the overall goal for the experience was simple: let user explore, relate and reflect. With that being said, we made it a point to make any necessary UI elements extremely simple...almost transparent. This visual downplay of the UI helped us reinforce the notion that it (the site) needed to be completely secondary to the content; it needed to be dead simple. Awesome, sure...but the site almost needed to use itself while the user was left to get deep.

  • Content Creation

    Inspired by animated gifs and cinema graphs we storyboarded “loop-able” video compositions that visually reinforced the new Drexel University brand message. Our approach relied on subtlety for the atmospherics and vulnerability for the student video portraits. Both needed to feel raw, relatable, and ultimately believable. All of the video was shot using a Canon 7D with a handful of appropriate lens and simple manual motion control setups—pretty straightforward—and the shots were taken all throughout Northern California.

    Development Approach

    Developmentally speaking, we wanted to create an experience that went hand in hand with the overall storytelling vibe for the site. This meant that wherever possible, we tried to avoid distracting things like page refreshes...but in a way that still allowed for an organic and free-form randomization of grids, deep-linked content, and—of course—shareability.

    We leveraged Backbone.js pretty heavily, as it it offered just the right cross-section of framework and flexibility for our needs. All aspects of the site were built using client-side javascript views, and the various grid layouts are driven via a core base of HTML templates that were kept very concise and reused as aggressively as possible.

    The randomizing grid sections presented a special challenge, as we needed to both shuffle the contents of the grid in addition to the grid layouts themselves. As content was being developed in parallel with the site framework (and was therefore variable, to a degree), we opted for a purely ‘weird’ url system that was essentially a concatenation of the grid type + ‘-’ + each content piece that was represented in that particular view. A custom shuffle iterator plugin handled the randomization, and we ran all of that through a nice and slick HTML5 history pushState that gracefully falls back to hashChange.

    Random content. No refreshes. Storytelling.

    Speaking of storytelling, the looping videos themselves presented their own challenges. Precisely because we were running a site with no hard refreshes, we needed to construct a system where video is only loaded when inserted into the view. We essentially had to learn how to build the tags dynamically to avoid web browsers from downloading hidden video tags (which they inexplicably do). Likewise, videos are removed when the route changes to avoid simultaneous downloads and prevent memory leaks in the browser. It’s the little things.

    Finally—and this was sort of the whole point—we needed to resolve the notion of a deeply interactive, inherently video-based website being highly shareable across the social web...sort of an apples to oranges type of problem. The end solution ended up being equal parts design, development, and cleverness: each of the 16 looping video segments was rendered into a still graphic (with and without inspirational text overlay) and saved in the various formats used by Facebook and Pinterest. We then created a share JS module that changes the share url/image (based on the current section...all run through the above-mentioned Backbone routing system), which effectively made for unique share paths for all pageviews across the site.

    Technical Highlights

    Backbone.js views and routing system

    • · Client-side javascript views for all aspects of the site.
    • · Smaller JS views for buttons and overlays are used to keep things modular + decoupled.
    • · Content views are populated via HTML templates, and reused whenever possible.
    • · Routing uses HTML5 history pushState and falls back to hashChange (for less modern browsers).
    • · Site-wide events system uses Backbone.Events to broadcast messages across various views.

    Here’s a good example of how we defined our grids/templates as javascript views.

    // --------------------------------------------------
    // Drexel grids and view templates.
    // --------------------------------------------------
    define(function (require) {
    // dependencies
    var _ = require('underscore');
    return {
    // --------------------------------------------------
    // grid rectangles - numbers in percentage
    // rect( x, y, width, height )
    //
     grids: {
    // vertical split
    "a": [
     rect(50, 0, 51, 100),
     rect(0, 0, 51, 100)
     ],
    // horizontal split
    "e": [
     rect(0, 50, 100, 51),
     rect(0, 0, 100, 51)
     ],
    // three columns
    "i": [
     rect(66.6, 0, 33.5, 100),
     rect(33.3, 0, 33.5, 100),
     rect(0, 0, 33.5, 100)
     ],
    // combo split right
    "o": [
     rect(50, 0, 51, 51),
     rect(50, 50, 51, 51),
     rect(0, 0, 51, 100)
     ],
    // combo split left
    "u": [
     rect(50, 0, 51, 100),
     rect(0, 50, 51, 51),
     rect(0, 0, 51, 51)
     ]
     },
    // --------------------------------------------------
    // article url IDs mapped to views + templates
    //
     articles: {
    'beyond': {
     view: require('base/article'),
     template: require('text!templates/beyond.html')
     },
    'magic': {
     view: require('base/article'),
     template: require('text!templates/magic.html')
     },
    'contrary': {
     view: require('base/article'),
     template: require('text!templates/contrary.html')
     },
    'through': {
     view: require('base/article'),
     template: require('text!templates/through.html')
     },
    'enjoy': {
     view: require('base/article'),
     template: require('text!templates/enjoy.html')
     },
    'wild': {
     view: require('base/article'),
     template: require('text!templates/wild.html')
     },
    'nights': {
     view: require('base/article'),
     template: require('text!templates/nights.html')
     },
    'better': {
     view: require('base/article'),
     template: require('text!templates/better.html')
     },
    'struggle': {
     view: require('base/article'),
     template: require('text!templates/struggle.html')
     },
    'curious': {
     view: require('base/article'),
     template: require('text!templates/curious.html')
     },
    'jump': {
     view: require('base/article'),
     template: require('text!templates/jump.html')
     },
    'impossible': {
     view: require('base/article'),
     template: require('text!templates/impossible.html')
     },
    'dream': {
     view: require('base/article'),
     template: require('text!templates/dream.html')
     },
    'jenny': {
     view: require('base/article'),
     template: require('text!templates/jenny.html')
     },
    'sally': {
     view: require('base/article'),
     template: require('text!templates/sally.html')
     },
    'ryan': {
     view: require('base/article'),
     template: require('text!templates/ryan.html')
     },
    'justin': {
     view: require('base/article'),
     template: require('text!templates/justin.html')
     }
     },
    // --------------------------------------------------
    // List of custom cursors to be used for the grid
    //
     cursors: ['cur1', 'cur2', 'cur3']
     };
    // --------------------------------------------------
    // utils
    function rect(x, y, w, h) {
    var args = _.map(arguments, function (arg) {
    return arg === 0 ? arg : arg + '%';
     });
    return { x: args[0], y: args[1], width: args[2], height: args[3] };
     }
    });
    

    URL system - Random shuffle

    Randomization is based on a custom shuffle iterator plugin (source included below). Each piece of the grid layout is shuffled using this iterator, as well as the individual grid sections themselves. The URL is divided using the "-" separator and the names + letter keys are combined to make things "extra weird". Here’s the source for our custom iterator/shuffle module.

    example.js

    var slots = iterator([80, 60, 50, 40, 20, 10], { shufe: true, pool: 2 });
    var result = slots.next();
    

    iterator.js

    // --------------------------------------------------
    // Iterator with shufe support
    // --------------------------------------------------
    define(function (require) {
    // dependencies
    var _ = require('underscore');
    // default options
    var defaults = {
     repeat: true,
     shufe: false,
     unique: true,
     pool: 1
     };
    // iterator module function
    function iterator(collection, options) {// validate params
     collection = _.toArray(collection);
     options = _.extend({}, defaults, options);
    if (options.pool < 1) options.pool = 1;
    if (collection.length < options.pool) {
    throw new Error('iterator: collection must be larger than pool.');
     }
    // expose instance methods
    var instance = {
     list: [],
     reset: function () {
    var rest = this.list.slice();
    this.list = rest.concat(collection);
    return this;
     },
     skip: function (item) {
    this.list = _.without(this.list, item);
    this.validate();
    return this;
     },
     validate: function () {
    if (options.repeat && this.list.length < options.pool) this.reset();
     },
     hasNext: function () {
    return this.list.length > 0;
     },
     next: function () {
    var result = this.list.shift();
    this.validate();
    return result;
     }
     };// override instance methods for shufe
     options.shufe && _.extend(instance, {
     reset: function () {
    var rest = this.list.slice();
    if (options.unique) {
    this.list = rest.concat(_.diference(_.shufe(collection), rest));
     } else {
    this.list = rest.concat(_.shufe(collection));
     }
    return this;
     }
     });
    // return instance with new list
    return instance.reset();
     }
    // return module (function)
    return iterator;
    });

    Dynamic HTML5 video templates

    • Video only loads when inserted, we learned to build the video tags dynamically to avoid web browsers from downloading a hidden video tag.
    • Videos are removed when the route changes to avoid simultaneous downloads and prevent memory leaks in the browser.
    Here's the removeMedia() function we used to clean up the audio / video tags.

    // remove audio + video + stop all the downloadin’
    // assumes $video and $audio are jQuery selectors for 

    In Closing

    Getgoingtoday.org was a perfect opportunity for BKWLD to create a highly sharable sensory storytelling experience all the while contributing and pushing whats currently being developed on the web.

    CREDITS

    • Agency: BKWLD
    • Development Direction: Dan Rogers
    • Technical Direction: Justin Jewett
    • Creative Direction: Jeff Toll

Awwwards

By Jeff Toll

I'm a digital family man working as the Creative Director for the digital agency BKWLD.

bkwld.com

1 ... 4 5 6