On Friendship

Ned and Jane, high school friends whom I have known for over 30 years now…

Ned and Jane, high school friends whom I have known for over 30 years now…

I was lucky enough to have spent the Australia Day long weekend just gone hanging out and playing music with old friends. Strange to think that aside from 2 people who I only met in 2017 (you know who you are Kendra and Fiona), that most of my closest friends who I would consider in my ‘inner circle’, I have known for more than three decades. Some of them, over four decades!

I guess that is the nature of my personality. I find it hard to actually make friends in the first place, but once I do make friends whom I connect with, I would gladly take a bullet for them and will be friends with them until the end (or they do something to shatter my trust in them). Those in the ‘inner circle’ are as dear to me as family.

I met friends on the weekend that I hadn’t spoken to in over 10 years, but we still took up where we left off as if it was just last week. And that made me think how lapse I have been over the past many years keeping up contact with my old friends. I have just been too caught up with work and other things going on in my life, that the nurturing of old friendships has been left to wallow in the weeds.

To that end, in 2019 I am intending to put a lot more effort into (a) tightening the bonds of friendship with old friends and (b) casting out the line to create some new friendships with like minded people. As an introvert (INFP), I usually find it difficult to reach out and form new friendships, but I am determined to overcome that and end this year with at least one more person in my ‘inner circle’.

This means:

  • Keeping up with our Sunday picnic session on the clifftops at Nightcliff Jetty (as we did all last year)

  • Attending more functions and music festivals with friends

  • Inviting people around to our house for dinner more often

  • Calling friends out of the blue to go out for a coffee or a beer at a pub

I’ll update this post in 12 months to see how I’ve gone with this initiative.

It was so nice to get a handwritten dinner invite last week!

It was so nice to get a handwritten dinner invite last week!

Note that this means less social media. In the past, I have used Facebook etc. as a bit of a crutch and a passive way to keep up with what my friends are doing, but this year, I am actually going to eschew most social media for communication and get back to some old fashioned talking to people and writing letters.

The Folly of 'Unimportant Data'

CR-BG-Computer-Backup-System-Hero-08-16.jpeg

Having been involved in computers for nearly 4 decades now, I have a healthy view towards data backups. Both my Macs are backed up to a local Time Machine drive on my network, PLUS to Amazon Glacier. I also have important development & client files copied to Google Drive and DropBox on a regular basis. Onsite and offsite backup.

I backup nearly all my critical data that I work with daily. However, I also have a ton of data which (I thought) I consider unimportant. This comprises of:

  • Old videos that I have edited and uploaded to Youtube etc.

  • Copies of photos from my wife’s phone

  • Images for all software installers I’ve used while setting up my PCs

  • Interesting videos or lessons that I have downloaded from Youtube over the years

  • Collections of interesting guitar tabs I’ve found online, etc.

Basically, stuff that I thought I could find again later if I really needed them.

Then, this week, the 3TB external drive that I had all this stuff on finally gave up the ghost and died. “No biggie” I thought to myself. “It was nice to have, but I’ll just get a new drive and start accumulating this unimportant stuff again from scratch”.

But then, in that same week:

  • My wife asked about a photo from her old phone that she couldn’t find any longer, and was it in my backup?

  • My son called to ask if I had a raw copy of a video I had edited for him some years ago as he needed another section (that I had edited out in the final render) for an audition he had to do.

  • I found out I had to reinstall an audio plugin for one of my old recordings, and the original publisher no longer had the older version of the plugin (which I needed to match my audio project) available for download on their site any longer.

How coincidental was that? All of a sudden, I needed this “unimportant” data that I thought I could throw away.

So this week, I’ve sent the external drive away to a data recovery service to see what they can do about bringing it back to life. The offer a free inspection to examine the extent of the failure, and quoted my AUD$300 to recover the data if they can. I figure $300 is worth it to me to just have all that data at my fingertips again, and if I do get it back, I will immediately be setting up a Glacier backup for all of it.

The Disconnectivity of Remote Working

Photo by trail on Unsplash

Photo by trail on Unsplash

Throughout the 30+ years of running my own business, I have explored all aspects of teamwork.  From having my own in house team, to having a totally remote team, to a combined mix of the two.

Which do I prefer? Now THAT is an interesting question.

I would consider myself an introvert, and I do prefer working by myself in my own home office a lot of the time.  However, some of my best working memories have been when I have been in an office situation and working alongside others.

There is something about the human connection of being in the same space as others.  A myriad of non verbal cues and communication that goes on, most at a sub conscious level, which lends itself to a better sense of being part of a community which is pulling in the same direction.

Case in point - my current startup is a fully remote setup.  For the past two years, it was really only myself and another co-founder, who worked in a small town literally on the other side of the world.

Now, my co-founder and I had a great working relationship, and we produced a ton of stuff together.  All communication was mainly via Slack and email, and we used to talk on a daily basis PLUS have a weekly web video catch up.

My co-founder left the startup about 2 months ago.  The first week was really challenging, as I directly missed talking to someone while working away on new ideas.

But by the end of the first month, I started to get used to working by myself again.  After all, I had run the startup by myself for about a year before my co-founder joined me.  So it felt basically the same as it did before.

By the end of the second month, I was actually struggling to recall even working with my former co-founder.  This concerned me, as I always considered myself a sensitive person who liked to reminisce about happy memories.  So why was it suddenly so difficult for me to recall any of those good times we had had?  My co-founder's departure was amicable, so this wasn't as a result of any ill feelings.  Rather it just seemed that those experiences and memories were just floating out of reach, and without anything to anchor them too, they just seemed to waft away whenever I tried to recall them.

Even when I would go back through a Slack conversation to find an old screenshot or idea, I would re-read some of our conversations - but I struggled to actually remember the emotions or personality behind those chats.  Re-reading them seemed somehow cold and impersonal and I couldn't tell if I was tired, or angry, excited or happy while typing those paragraphs.

As a direct contrast to that, I can still clearly recall events that happened in my office over 20 years ago when I worked only feet away from the rest of my team.

Tiny things like a shared look, collapsing on the floor laughing at an 'in house' joke, or the casual punch on the shoulder as someone congratulated you while walking past your desk - all those things just added so much to my working experience that I, even as a self confessed 'lone wolf', missed them terribly.

There is something about being around people who are experiencing the highs and lows of their lives (even outside of work) that is strangely enriching and bonding.

To extend this even further - I was looking through my Facebook feed just this week, and I realised that I have become close friends with a vast majority of people that I have worked with face to face over the decades.  Remote workers much less so.  For some reason when a former remote staff member posts about their family or holiday or other life event, I find myself a lot less engaged with their thoughts and feelings.  There is still an element of them being an unknown 'stranger' so that any such intimate details of their lives instills a sense of guilt that I tend to deliberately avoid seeming too familiar or presumptuous when reading their posts.

While my recently departed co-founder and I had discussed an actual company meetup where we (and potential future staff) could meet face to face, it never happened during our working time together.  And now that my co-founder has moved on, I have accepted that we will probably never, ever meet in real life.

I am in the process of building up a whole new remote team now though, and am looking at strategies to try and counter this feeling of disconnection with those that I will figuratively work alongside for the coming years.

Regular company face to face meetups are definitely on the cards.  But I am also thinking that we might need to put something else in place outside of those times.

But what could take the virtual place of those little moments like tossing a paper plane across the office to see whose desk it would land on, or the understanding look that I would share with a colleague across from me after hanging up from a talking to a difficult client, or the good natured group ribbing that would happen when a co-worker brought a delicious smelling lunch into the office?  I have yet to see a web or mobile app that can replicate this sort of interaction.

Perhaps I have to go and invent it?
 

Building a pricing screen which reflects local currency

different-currency-notes-money.jpg

On my morning walks, I have been enjoying listening to SaaS related podcasts, and yesterday morning, I was listening to Jane Portman's "UI Breakfast" podcast in which she was talking to Rob Turlinckx about SaaS Pricing pages.

Now, we have just done a revamp of our own HR Partner pricing page, which actually meets most of the suggestions of what they talked about in the podcast, i.e. offering multiple currencies, showing the user's local currency automatically upon loading, showing monthly vs annual pricing etc.

HRP Pricing Page.png

Our page is quite complex (but thankfully I have a great UX designer on my team who made it as easy to use as possible), but I thought I would expand upon a couple of things that we did on there in order to display pricing in various currencies, and most importantly, how we detected the user's location and showed them the relevant pricing in their own local currency (or else defaulting back to USD if they were in a location outside of our usual pricing).

What I have done is to put together a simple pricing page on Github which you are welcome to explore and dissect.  My aim was to be able to achieve localised pricing with (a) minimal javascript code, (b) doing it all on one page and (c) for absolutely FREE - no calling upon expensive landing page or A/B testing services to generate different pricing pages at all!

This is what it looks like (yep, I'm a coder, not a designer!):

TEST Pricing Page.png

Take a look at it running live here: https://cyberferret.github.io/LocalCurrencyPricing/

Here is a Gist of the actual web page code:

<!DOCTYPE html>
<html lang="en">

  <head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Demonstration of dynamic currency display</title>

    <!-- Bootstrap core CSS -->
    <link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="css/heroic-features.css" rel="stylesheet">

  </head>

  <body>

    <!-- Navigation -->
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
      <div class="container">
        <a class="navbar-brand" href="#">Widgets Inc.</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarResponsive">
          <ul class="navbar-nav ml-auto">
            <li class="nav-item active">
              <a class="nav-link" href="#">Home
                <span class="sr-only">(current)</span>
              </a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">About</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Services</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Contact</a>
            </li>
          </ul>
        </div>
      </div>
    </nav>

    <!-- Page Content -->
    <div class="container">

      <!-- Jumbotron Header -->
      <header class="jumbotron my-4">
        <h1 class="display-3">Hello there!</h1>
        <p class="lead">The pricing shown below should correspond to your location (or default to the US) like the pricing page on our <a href="https://www.hrpartner.io" target="_blank">HR Partner</a> site.</p>
        <a href="https://www.hrpartner.io/pricing.html" class="btn btn-primary btn-lg">See it in action!</a>
      </header>

      <div class="row text-center">
        <div class="col-lg-12 m-2">
          <p>Show me pricing in: </p>
          <div class="btn-group mb-3" role="group" aria-label="Select Currency">
            <button type="button" class="btn btn-secondary" onclick="displayPrice('USD');">USD</button>
            <button type="button" class="btn btn-secondary" onclick="displayPrice('GBP');">GBP</button>
            <button type="button" class="btn btn-secondary" onclick="displayPrice('EUR');">EUR</button>
            <button type="button" class="btn btn-secondary" onclick="displayPrice('AUD');">AUD</button>
          </div>
        </div>
      </div>

      <!-- Page Features -->
      <div class="row text-center">

        <div class="col-lg-3 col-md-6 mb-4">
          <div class="card">
            <div class="card-header">
              <h2 class="text-primary">FREE</h2>
            </div>
            <div class="card-body">
              <h4 class="card-title pricing USD_pricing">USD $0</h4>
              <h4 class="card-title pricing GBP_pricing collapse">GBP &pound;0</h4>
              <h4 class="card-title pricing EUR_pricing collapse">EUR &euro;0</h4>
              <h4 class="card-title pricing AUD_pricing collapse">AUD $0</h4>
              <p class="card-text text-info">Our free plan will suit the Scrooge McDuck's among you.</p>
            </div>
            <div class="card-footer">
              <a href="#" class="btn btn-primary">Find Out More!</a>
            </div>
          </div>
        </div>

        <div class="col-lg-3 col-md-6 mb-4">
          <div class="card">
            <div class="card-header">
              <h2 class="text-primary">Basic</h2>
            </div>
            <div class="card-body">
              <h4 class="card-title pricing USD_pricing">USD $10</h4>
              <h4 class="card-title pricing GBP_pricing collapse">GBP &pound;8</h4>
              <h4 class="card-title pricing EUR_pricing collapse">EUR &euro;9</h4>
              <h4 class="card-title pricing AUD_pricing collapse">AUD $14</h4>
              <p class="card-text text-info">This basic plan should get you kick started.</p>
            </div>
            <div class="card-footer">
              <a href="#" class="btn btn-primary">Find Out More!</a>
            </div>
          </div>
        </div>

        <div class="col-lg-3 col-md-6 mb-4">
          <div class="card">
            <div class="card-header">
              <h2 class="text-primary">Medium</h2>
            </div>
            <div class="card-body">
              <h4 class="card-title pricing USD_pricing">USD $50</h4>
              <h4 class="card-title pricing GBP_pricing collapse">GBP &pound;38</h4>
              <h4 class="card-title pricing EUR_pricing collapse">EUR &euro;42</h4>
              <h4 class="card-title pricing AUD_pricing collapse">AUD $67</h4>
              <p class="card-text text-info">For businesses that really need all the bells and whistles.</p>
            </div>
            <div class="card-footer">
              <a href="#" class="btn btn-primary">Find Out More!</a>
            </div>
          </div>
        </div>

        <div class="col-lg-3 col-md-6 mb-4">
          <div class="card">
            <div class="card-header">
              <h2 class="text-primary">Enterprise</h2>
            </div>
            <div class="card-body">
              <h4 class="card-title pricing USD_pricing">USD $200</h4>
              <h4 class="card-title pricing GBP_pricing collapse">GBP &pound;152</h4>
              <h4 class="card-title pricing EUR_pricing collapse">EUR &euro;171</h4>
              <h4 class="card-title pricing AUD_pricing collapse">AUD $270</h4>
              <p class="card-text text-info">If you have more money than Elon Musk, then this is the plan for you.</p>
            </div>
            <div class="card-footer">
              <a href="#" class="btn btn-primary">Find Out More!</a>
            </div>
          </div>
        </div>


      </div>
      <!-- /.row -->

    </div>
    <!-- /.container -->

    <!-- Footer -->
    <footer class="py-5 bg-dark">
      <div class="container">
        <p class="m-0 text-center text-white">Copyright &copy; Widgets Inc. 2018</p>
      </div>
      <!-- /.container -->
    </footer>

    <!-- Bootstrap core JavaScript -->
    <script src="vendor/jquery/jquery.min.js"></script>
    <script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>

    <script>
      $(document).ready(function () {
        $.get("https://api.ipdata.co?api-key=e1173cbb1676c06b2136abfc7ca95e0c10b8ee98623bfbb0c47b0aaa", function (response) {
          var detectedCurrency = response.currency.code;
          displayPrice(detectedCurrency)
        }, "jsonp");
      });

      displayPrice = function(currency) {
        // First, lets hide all the current pricing
        $(".pricing").hide();
        // Is the currency within the valid range of currencies that we wish to show?
        if (currency !== null || (["USD", "AUD", "GBP", "EUR"].indexOf(currency) > -1)) {
          // If yes, then show the currency
          $("." + currency + "_pricing").show();
        } else {
          // If no, then just show USD pricing
          $(".USD_pricing").show();
        }
      }
    
    </script>

  </body>

</html>

 

If you want the full source code (with the Bootstrap and jQuery libraries etc. so you can test on your own server), then you can clone my code from my Github repository:  https://github.com/CyberFerret/LocalCurrencyPricing

Let's break down the code here.

Firstly, I am using a simple Bootstrap 4 page layout, which has a header block, then 4 columns for the pricing.  If you look at each pricing column though, I have included the 4 currencies that I want to show:

        <div class="col-lg-3 col-md-6 mb-4">
          <div class="card">
            <div class="card-header">
              <h2 class="text-primary">FREE</h2>
            </div>
            <div class="card-body">
              <h4 class="card-title pricing USD_pricing">USD $0</h4>
              <h4 class="card-title pricing GBP_pricing collapse">GBP &pound;0</h4>
              <h4 class="card-title pricing EUR_pricing collapse">EUR &euro;0</h4>
              <h4 class="card-title pricing AUD_pricing collapse">AUD $0</h4>
              <p class="card-text text-info">Our free plan will suit the Scrooge McDuck's among you.</p>
            </div>
            <div class="card-footer">
              <a href="#" class="btn btn-primary">Find Out More!</a>
            </div>
          </div>
        </div>

But have a look at the `collapse` class used in all but the USD pricing in the source code.  What this does is 'collapses' the other currencies so that they are not visible upon page load, instead showing you the USD pricing as a default.

I have also given all the pricing <h4> tags the class of `pricing` and `XXX_pricing` (where XXX is the 3 letter currency code for each locale).  You will see how I use these later to both hide and show the relevant pricing via a simple javascript function.

Now lets look at the javascript code at the bottom of the page.  There are two blocks we need to look at, namely:

      $(document).ready(function () {
        $.get("https://api.ipdata.co?api-key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", function (response) {
          var detectedCurrency = response.currency.code;
          displayPrice(detectedCurrency)
        }, "jsonp");
      });

This bit of code waits until the page is completely loaded, then goes off to the IPData.co free service to query the user's locale information, including the currency code associated with their locale.

This information is contained within the JSON response from the IPData service, and you can get to it via the response.currency.code variable.

Be warned that this call, even though it is done as a background asynchronous AJAX call, can take a few seconds to return a result - which is why we show the default USD pricing initially, rather than no pricing at all.  This can cause a disconcerting flicker upon page load, so you may want to show NO pricing on your own page as a default, which you can do by adding the `collapse` class to ALL pricing lines initially.  It is entirely up to you.

TIP: Just remember to replace the 'xxxxxxxxx' dummy API key above with your free one that you get from IPData.co!

The next bit of javascript is the one that manipulates the page DOM to show or hide the relevant currencies:

      displayPrice = function(currency) {
        // First, lets hide all the current pricing
        $(".pricing").hide();
        // Is the currency within the valid range of currencies that we wish to show?
        if (currency !== null || (["USD", "AUD", "GBP", "EUR"].indexOf(currency) > -1)) {
          // If yes, then show the currency
          $("." + currency + "_pricing").show();
        } else {
          // If no, then just show USD pricing
          $(".USD_pricing").show();
        }
      }

This function takes just one parameter, the 3 letter currency code, and then it:

  1. Hides ALL the pricing lines by default, then
  2. Checks the currency code to see if it is one of the 4 allowed codes on our page, then
  3. If it is allowed, shows the pricing which has the class of `[Currency Code]_pricing`, or
  4. Shows the default USD pricing lines.

 

One last thing - I realise that sometimes users may want to see the pricing in other currencies themselves, rather than in their local currency.  Most often when they want to compare the USD values against other services they use etc., so we should allow them the ability to do so.

Which is why I placed the button group between the header and the pricing boxes which asks for the currency they want to see.  Clicking on any of the buttons will call the `displayPrice()` function to show that locale's currency.

      <div class="row text-center">
        <div class="col-lg-12 m-2">
          <p>Show me pricing in: </p>
          <div class="btn-group mb-3" role="group" aria-label="Select Currency">
            <button type="button" class="btn btn-secondary" onclick="displayPrice('USD');">USD</button>
            <button type="button" class="btn btn-secondary" onclick="displayPrice('GBP');">GBP</button>
            <button type="button" class="btn btn-secondary" onclick="displayPrice('EUR');">EUR</button>
            <button type="button" class="btn btn-secondary" onclick="displayPrice('AUD');">AUD</button>
          </div>
        </div>
      </div>

 

That's it!  Pretty easy (and cheap), isn't it?  No need for a complex content management system, or PHP/Ruby scripting etc.  This can all be done on a free website hosting platform like Amazon S3 (which we use) or Github Pages etc. 

Have fun with it.  For my next post, I might showcase how to use a free foreign currency exchange API to dynamically calculate the other pricing based on that day's exchange rates!