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 ...

Making Partial Connected Webforms for Podio (Advanced)

- Posted in Uncategorized by

Podio has webforms built in, which allows easy creation of items. The problem arises when you want a specific person to provide some data. Having a form create a new item (a) doesn't allow editing of existing data, and (b) doesn't allow for an easy mechanism to identify who filled in the form.

There be some advanced code ahead. For a really simple way to build a portal on your website, see this post instead.

I've seen many attempts to work around this by giving people a new form to fill in which requests the needed data, including email address. Then there are a bunch of GlobiFlow flows that try to find the original customer record by email address, hoping that this person used the same address on the form, and that there are no duplicates in the system.

There is a better way ...

Simple Connected Forms

What we want is a mechanism to send a form to someone to fill out that:

  • is already an item in Podio
  • is already identified
  • allows the person to edit existing data
  • allows you to choose which fields they can see & edit
  • prevents them from changing important ID data

Basically we want a mechanism that sends the person an email similar to:

And the resulting page lets them edit certain fields only, while preserving existing data:

The Setup

First thing we need is an app in Podio to store users. For this demo, we're just using a single app that has everything:

The "Action" category field is going to act like a button to initiate the process. The fields for Question 1 to 3 are fields we want the contact to fill in. The "Internal Use Password" field is to add some security to our form so people can't willy-nilly edit any item in the app.

The Widget

We're going to need a ProcFu HTML widget to serve the form content. The code is pretty straight forward and well commented and should be easy to follow:

// configuration $survey_app_id = 1234567; $password_field = "internal-use-password"; // decode the payload: expecting ?item=1234&pass=abcdef $data = @json_decode($pf_payload, true); if ( ! isset($data['GET']['item']) ) return "<h3>Ooops</h3><p>This link appears invalid (1)</p>"; if ( ! isset($data['GET']['pass']) ) return "<h3>Ooops</h3><p>This link appears invalid (2)</p>"; // get the item from podio $podio_item_id = intval($data['GET']['item']); $item = @json_decode(call_pf_script("podio_item_get_raw.pf", ["podio_item_id" => $podio_item_id]), true); if ( $item === null ) return "<h3>Ooops</h3><p>This link appears invalid (3)</p>"; // make sure the password on the item matches what we were given $fields = pf_podio_item_as_field_array($item); if ( ! isset($fields[$password_field]) || $fields[$password_field] != $data['GET']['pass'] ) return "<h3>Ooops</h3><p>This link appears invalid (4)</p>"; // get the app from Podio $app = @json_decode(call_pf_script("podio_app_get_raw.pf", ["app_id" => $survey_app_id]), true); if ( $app === null ) return "<h3>Ooops</h3><p>An unexpected error has occured</p>"; // we need a session, so just use the password as the id pf_session_start($data['GET']['pass']); // start our html $html = ''; $html .= <<<'EOF' <style> body { font-family:sans-serif;color:#444; } .pf-form { width: 100%; max-width: 900px; } .pf-form .pf-label { display: inline-block; width: 30%; vertical-align: top; padding-top: 2px; } .pf-form .pf-value, .pf-form-row .pf-input { display: inline-block; width: 70%; min-height: 25px; } .pf-form .pf-button { cursor: pointer; min-height: 25px; } </style> EOF; // ui functions need jQuery $html .= '<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>'; // are we returning from filling out the form? if ( isset($data['GET']['complete']) ) { $html .= '<h3>Thank You</h3>'; $html .= '<p>Thank you for submitting the survey. Someone will follow up with you soon.</p>'; return $html; } $html .= '<h3>Survey for ' . $fields['title'] . '</h3>'; $html .= '<p>Please complete the fields below:</p>'; // include the javascript for the UI functions $html .= pf_ui_include_js(); // make the edit widget $ui = new pf_ui_item($app, $item); $ui->setMode("edit"); $ui->setFields(["question-1", "question-2", "question-3"]); $ui->setReadOnly(["title", "email"]); $ui->setSuccessUrl("/widgets/html/" . $data['widget_id'] . "?item=".$podio_item_id."&pass=".$data['GET']['pass']."&complete"); $html .= $ui->render(); return $html;

Basically we're expecting the widget to receive "item" and "pass" in the URL, fetch the item from Podio and make sure that the password matches. If it does, then show the person a form with Questions 1 to 3 and let them edit their content.

The Flows

Next, in GlobiFlow, we need to set up an external link page:

There are some interesting things we're doing here.

The iframe variable creates the html needed to show an iframe where we'll insert our ProcFu widget. We also show an animated gif so the user sees something while waiting for the background magic to happen:

'<p id="loader"><img src="http://www.globiflow.com/images/progressbar.gif"></p><iframe id="iframe" style="width:100%; height: 300px; border: 0">

The css variable creates the html needed to load jQuery and also some CSS styles to make the default GlobiFlow page wider (by default it's pretty narrow):

'<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><style> #wrapper { width: 800px; } </style>'

The java variable creates the javascript code to set the source of the iframe, and on completion of loading, hide the animated gif.

'<script> $(function(){
  $("#iframe").attr("src", "https://procfu.com/widgets/html/123redacted456?item=' . [(Survey) Podio Item ID] . '&pass=' . [(Survey) Internal Use Password] . '");
  $("#iframe").on("load", function(){
}); </script>'

You could easily expand this flow to do other things as you now know that the person clicked on the link they were provided.

The next flow we need is on update of an item to send an email when the "Send" category button is clicked:

This just basically sends an email to ask the person to click on a link, which will show them the external GlobiFlow page with the ProcFu widget content.

The Result

The end result is as follows:

1) You have a user record created somehow (obviously you'll adapt this to your specific requirements, right?)

2) You go to the record and click on the "Send" button

3) The user receives an email

4) The user clicks on the link in the email and gets the form to complete

5) The user updates the fields as needed and saves the form

6) The record in Podio is updated accordingly


This demo is meant to demonstrate the concept of allowing users / customers / contacts / people, to be able to fill in forms that don't represent an entire app, that can have pre-defined data, and that are already linked in Podio, and all without having to make them log in with a password.

You can take this concept and extrapolate it to your specific needs and business setup.