Pushing Podio

Fun Experiments pushing Citrix Podio to the limit so you can get more done.
... with a little help from GlobiFlow, ProcFu, and other friends ...

Website Custom Content using Google Login

- Posted in Uncategorized by

Do you have customers coming to your website? Do you want to be able to identify them and show them custom content? Then this post is for you.

What we're trying to achieve here, is to let visitors to your website sign in using Google, and then show them custom content from Podio once they're authenticated.

A page on your website could look something like this:

And after the person logs in, they can see specific content like:

We're going to make this all happen using ProcFu and a bit of javascript on your website.

The Podio Setup

The first thing we'll need, is an app in Podio that controls who can log in. For this example, we have a simple app with a single line text field for their email address, and a multi-line text field for the content we want to show:

Where my personal record has this content:

We'll need the following info from this app (all available in the developer section of the app config):

  • App ID
  • Email field ID
  • Page content field ID

Google API

We're going to need a Google API client to use for authentication.

Go to the Google Developer API Console and create a new API key. Make note of the Client ID and Client Secret.

Also make sure that under the Authorized redirect URIs you add:

https://procfu.com/authgen2.php

On the Library tab, add the Google+ API to your project:

Next, in ProcFu, add this API client on the Conf page:

For easier copy pasting, here are:

  • Authorize URL: https://accounts.google.com/o/oauth2/v2/auth
  • Scopes: https://www.googleapis.com/auth/userinfo.email
  • Access Token URL: https://www.googleapis.com/oauth2/v4/token
  • Resource Owner Details URL: https://www.googleapis.com/plus/v1/people/me

The ProcFu Widget

In ProcFu, create a new Custom Code Block, and also a new HTML Website Widget to use this code block. Make note of the Widget ID as we will need this again later.

The code block source code can be found in it's entirety here.

Let's run through it bit by bit to help explain what's happening.

This is just the configuration, and the comments should be explanation enough of what each variable is for:

/* google login
 * will do the following:
 *  - allow visitors to authenticate using Google+
 *  - show custom content from Podio once logged in
 */

// configuration
$api_service = "PFdemoG"; // the name you gave your podio integration on the Account page under "API Services"
$customers_app_id = 1234567; // App in Podio to search for customers Google email address
$email_field_id = "google-email-address"; // field in above app that has the email address
$content_field_id = "page-content"; // multi-line text field in above app to show to customer when logged in
$public_page_url = "http://globi.ca/ppdemo_login_google.php"; // url of page on your website that's calling this widget
// end configuration

Next, we decode the payload, and set some default values:

$data = @json_decode($pf_payload, true);
$pfsessid = false;
$userEmail = false;

The first check is for if we're coming back from Google's login authentication. If so, we need to get the user info of the logged in user:

// are we coming back from authentication?
if ( isset($data['GET']) && isset($data['GET']['ok']) && isset($data['GET']['session_id']) ) { 
    if ( $data['GET']['ok'] != 1 ) return "Authentication Failed";
    if ( empty($data['GET']['session_id']) ) return "No Session ID";
    $pfsessid = $data['GET']['session_id'];
    pf_session_start($pfsessid);
    $session = [];
    $user = @json_decode(urldecode($data['GET']['data']), true);
    if ( $user === false ) return "unknown user";
    //$session['userEmail'] = $user['user']['mail']; // Podio
    $session['userEmail'] = $user['emails'][0]['value']; // Google Plus
    pf_session_set($session);
    $url = $public_page_url . "?pfsessid=" . $pfsessid;
    return('<script>document.location.href="' . ($url) . '";</script>');
}

Next, we start the session. Since there are no server-side sessions in PF (each call is sandboxed and unique), we use PF's baked-in functions and rely on our javascript to provide the session ID (not to worry - the ID's are unique over IP addresses and PF customer accounts):

// make sure we have a valid session ID
if ( ! isset($data['GET']) || ! isset($data['GET']['pfsessid']) ) return "Bad Session ID";
$pfsessid = $data['GET']['pfsessid'];
pf_session_start($pfsessid);
$session = pf_session_get();

Next, we need to check if we're logged in according to the session, and if not, provide the login button for the visitor to click on:

// check if we're logged in
if ( ! isset($session['userEmail']) ) {
    $url = call_pf_script("api_login_ident.pf", ["api_service" => $api_service, "widget_id" => $data['widget_id'], "session_id" => $pfsessid]);
    $html = '<h3>Login Required</h3>';
    $html .= '<p>Please login using the button below.</p>';
    $html .= '<p><a href="' . $url . '"><img src="https://developers.google.com/identity/images/btn_google_signin_dark_normal_web.png"></a></p>';
    return $html;
} 

// OK - we're logged in
$userEmail = $session['userEmail'];

Now that we know that the person is logged in, we need to verify that they have a record in our Podio app:

// Do we have an authorized record
if ( ! isset($session['userRecord']) ) {
    $customers = @json_decode(call_pf_script("podio_search_app.pf", ["app_id" => $customers_app_id, "field_id" => $email_field_id, "search_val" => $userEmail, "condition" => "E", "max_results" => 1]), true);
    if ( $customers === null || sizeof($customers) == 0 ) {
        // no customer record for this email address
        $html = '<h3>Ooops!</h3><p>It seems that ' . $userEmail . ' does not have access to this page.<p>';
        $html .= '<p><i>{perhaps offer a link to a webform to request access here}</i></p>';
        return $html;
    }
    $session['userRecord'] = $customers[0];
    pf_session_set($session);
}

And now that we know that they're logged in and have a valid record, display the multi-line text field of the record to them (this is where you can use your imagination to do just about anything - we're just displaying some content here to keep things simple for this example):

// OK - we're logged in and have a user record
// so show the multi-line text field on the user record to the user
$html = '<h3>Hello ' . $userEmail . '</h3>';;
foreach ( $session['userRecord']['fields'] as $field ) {
    if ( $field['external_id'] == $content_field_id ) {
        $html .= $field['values'][0]['value'];
    }
}
return $html;

And that's it for the custom code block. With just this small amount of code, you can authenticate users and interact with Podio based on the logged in customer.

On your Website

Note that since Google doesn't allow framing, we can't run this HTML Widget in an iframe. Instead we'll use jQuery to fetch the content and update a div on the site.

Firstly, make sure that you're loading jQuery on your site somewhere. The line in your HTML should look something like:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

The version is not terribly important, but it must be there.

Next, add a div to your page where you want the Podio content to be displayed, and give it a unique ID:

    <div id="pfcontent">
        <img src="/img/progress-bar.gif">
    </div>

And lastly, add a piece of JavaScript to fetch the widget and populate your div. This is a little more complex than the previous example because we need sessions, but it's still pretty straight forward.

Basically we generate a random session ID if one doesn't already exist, and use modern browser session storage to keep this id. Then we just make sure it's always sent to the HTML Widget for ProcFu to use:

<script>
var pfwidgeturl = "https://procfu.com/widgets/html/yqp3pCpaNfkL";
$(function() {
    if ( ! sessionStorage ) {
        $("#pfcontent").html('<h1>Error</h1><p>Your browser does not support session storage. Please use a modern browser</p>');
        return false;
    }
    var pfsessid = sessionStorage.getItem("pfsessid");
    if ( pfsessid == undefined ) {
        pfsessid = (new Date().getTime()).toString(16) + Math.random().toString(16).substring(2, 15);
        sessionStorage.setItem("pfsessid", pfsessid);
    }
    var params = window.location.search;
    params = new URLSearchParams(window.location.search);
    if ( ! params.has("pfsessid") ) params.append("pfsessid", pfsessid);
    console.log(params.toString());
    $("#pfcontent").load(pfwidgeturl+"?"+params, function(){
    });
});

The Result

That's all there's to it. Customers can now log into your website and see specific content from Podio.

Comments