YesGraph’s invite widget uses OAuth 2.0 to get your users’ contacts from each contact importing service (I will use Google for the examples here). This authorization method requires a Redirect URL to be saved ahead of time on the Google Developer Console, and that URL must exactly match the domain initiating the authorization flow.

Trouble arises if you’d like to use the flow on a dynamic subdomain (e.g., foo.mywebsite.com, bar.mywebsite.com, etc.), because wildcard subdomains (e.g., *.mywebsite.com) are not supported on the Google Developer Console.

Here I’ll walk you through a workaround solution for initiating the auth flow from a dynamic subdomain. Let’s get started:

YesGraph’s invite widget will handle everything from that point, so you’re done!

Using Multiple Auth Providers

If you’re importing contacts from additional services (e.g., Outlook, Yahoo, etc.), you’ll only have to do this once–the flow is the same for all of them. The only thing to be aware of is that some providers will return the data not in hash parameters but in traditional url parameters (e.g., www.mywebsite.com?state=foo…), so your redirect page should be able to handle that. The code snippet included below will work for both.

Example Redirect Page

Your redirect page can be very simple–users won’t be staying there long. The code here shows how to get the information you need from the URL, and redirect to the right place.

As always, feel free to drop us a line if you have any questions!

<html>
<head>
    <title>My Redirect Page</title>
</head>
<body>

    <h1>Redirecting...</h1>

    <script type="text/javascript">
    // Get the target destination from the "state" parameter
    var targetUrl = getUrlParam(location.href, "state");

    if (targetUrl) {
        if (targetUrl.indexOf("//") === -1) { targetUrl = "//" + targetUrl; }
        // Add the hash & url params to the target url
        var extra = [];
        if (location.search) {
            extra.push(location.search.slice(1));
        }
        if (location.hash) {
            extra.push(location.hash.slice(1));
        }
        if (extra.length > 0) {
            targetUrl += "#" + extra.join("&");
        }
        // Redirect to the target destination
        location.href = targetUrl;
    } else {
        // This 'else' clause will likely never be used,
        // but it makes sense to have a sane default.
        location.href = location.origin + location.hash;
    }

    function getUrlParam(url, key) {
        // Get a value from the url query parameters, or from the hash
        var key = key.replace(new RegExp("/[[]/"), "\[").replace(new RegExp("/[]]/"), "\]");
        var regexS = "[\?&#]" + key + "=([^&#]*)";
        var regex = new RegExp(regexS);
        var results = regex.exec(url);
        if (results == null)
            return "";
        else
            return fullyDecode(results[1]);
    }

    function fullyDecode(str) {
        // Recursively decode a URI component until it's fully decoded
        var decoded = decodeURIComponent(str);
        return decoded == str ? str: fullyDecode(decoded);
    }
    </script>
</body>
</html>