Geolocated currency with MaxMind

#Vue

Once again, here we have Samuel Snopko! You might know him from his tip of the Vue.js Tip Overload 😉

He’s a creative FrontEnd Knight & DesignOps enthusiast with a passion for web, VueJS an NuxtJS. Co-creator of DX Meetup Basel and co-organizer of Frontend Meetup Freiburg.

Let’s move on to the tip!


Sometimes you need to integrate a geolocated content on your website. In this little tip I will show you how easy could it be using VueJS, MaxMind GeoIP and Autonumeric. This sample is written in NuxtJS for the special case of a geolocated currency, but the same principles apply on the vanilla VueJS applications.

The geolocated currency means, that even if you have a page only in the one language you want to show a different currency according to the country of the visitor. The visitor from the USA will see the dollar sign $10,000 and the visitor from the Germany would see in the same sentence Euro sign 10.000€. You could also notice the different punctuation in these two cases.

Ok, I assume your content is reachable trough some API of headless CMS like Storyblok, like in my case. Remember, the currency could be use in any string. That’s why I defined unique pattern that could be used in any string to mark the geolocated currency. I used this pattern #{number}#, which means that string Price: #{10000}# will be replaced in the USA with string Price: $10,000 and in the Germany with Price: 10.000€.

// API returns:
{
  description: "Price: #{10000}#";
}

First you have to find and transform your patterns into HTML tags. I wanted to do it using the global filter, but then I found out that the filter is forbidden in v-html and v-text. So, I did it with the global mixin, which will transform string #{number}# into string <span data-currency>number</span>.

// mixins.js
import Vue from "vue";
// Adds global currency method to transfor #{}# string to span
Vue.mixin({
  methods: {
    extractCurrency(string) {
      if (!string.includes("#{")) {
        return string;
      }
      const openTag = `<span data-currency>`;
      const closeTag = `</span>`;
      const openRegex = /#{/g;
      const closeRegex = /}#/g;
      string = string.replace(openRegex, openTag);
      string = string.replace(closeRegex, closeTag);
      return string;
    }
  }
});

As this is the global mixin you can use the function extractCurrency in every component. Eg.

// component.vue
<template>
  <p v-html="extractCurrency(description)" />
</template>

If you will generate static page using nuxt generate as I did, you will end with a static page containing this:

<!-- static-page.html -->
<p>Price: <span data-currency>10000</span></p>

Now you have to find out the country of the visitor using GeoIP of the MaxMind and then call Autonumeric function to add correct currency. You will do this in the mounted() life cycle of the VueJS as this should be run only at the client side. The best place to do this in the NuxtJS is in your layout file.

// layouts/default.vue
export default {
  mounted() {
    geoip2.country(
      success => {
        const currencyType =
          success.country.iso_code === "US" ? "NorthAmerican" : "French";
        AutoNumeric.multiple(
          "[data-currency]",
          AutoNumeric.getPredefinedOptions()[currencyType]
        );
      },
      error => {
        console.warn("Error occured by getting geolocation.");
      }
    );
  }
};

If the GeoIP is not working or taking to long time to return location, you can show the number without the currency or show the default currency using CSS :before pseudo-element.

// fallback for currency
span[data-currency]:not([value]) {
  &::after {
    content: " €";
  }
}

Don’t forget that you could use also the global event bus in the NuxtJS to trigger method on component according to the geolocation. You would add this line this.$nuxt.$emit("geolocationFound", success.country.iso_code) into your mounted cycle.

Pretty easy or?

That’s it for this week! Remember you can read this tip online (with copy/pasteable code).

It’d be helpful if you also share VueDose with your colleagues, so they also know about these tips!

See you next week.

Start saving time and get a tip about the Vue ecosystem every week, right in your inbox.