Growing Venture Solutions - GVS - uc_signup http://growingventuresolutions.com/taxonomy/term/56/0 en Drupalcamp Atlanta and best practices for event websites in Drupal http://growingventuresolutions.com/blog/drupalcamp-atlanta-and-best-practices-event-websites-drupal <p><a href="http://drupalcampatlanta.com/">Drupalcamp Atlanta</a> recently launched their new site for the 2010 Camp. I reviewed some of their features and found it to be a solid site. As the GVS team increases our focus on selling events with Drupal, I wanted to hear more about the backend of the site. So, I got in touch with <a href="http://drupal.org/user/175971">Brent Ratliff</a> who was the lead developer on the site, to find out how the site was built.</p> <h3>Adding Signups and Payment to an Event Site: <a href="http://drupal.org/project/uc_signup">UC Signup</a></h3> <p>In 2009, the site was a standard build relying mostly on Views and content types. For 2010 they needed all of the features from the previous year but also needed to charge an entry fee for the event, for individual sponsorships, as well as the ability to submit and vote on sessions. The Atlanta Drupal Users Group decided to base their 2010 site on the acclaimed 2009 Drupalcamp LA site that was released as a zip file. The LA code, updated with new module releases, handled the voting, some nice Views, helpful theme functions, context, and some of the "attendee logic," but not the e-commerce portion. Brent was familiar with using the <a href="http://drupal.org/project/uc_node_checkout">UC Node Checkout</a> module for building an event site, but ultimately decided to go with the <a href="http://drupal.org/project/uc_signup">Ubercart Signup</a> integration module along with Rules and custom hooks to handle workflow. UC_Signup allows them to collect profile information from users during checkout and helps keep track of attendees using the <a href="http://drupal.org/project/signup">Signup</a> module. They also grant roles to users based on which products they have purchased. </p> <h3>Panels vs. Context? Both</h3> <p>On the topic of Panels vs. Context, Brent said he follows the practice of using both modules. Context is responsible for block placement on the site and changing the active menu item on some pages of the site to give a more consistent feeling as you navigate around. Panels is responsible for the main "content" area in a few parts of the site, allowing the site to pull in Views and other content into complex landing pages without having to write much code. Arguments can also easily be passed from the Panel directly to the Views and the Panels can be exported along with features for version control while remaining theme independent. Panels also allow Skinr styles to be applied to content via the UI and for content editors to easily add or remove relevant components as the camp timeline changes, such as removing session voting and adding a session videos after the camp. One example of this is the <a href="http://drupalcampatlanta.com/sponsors">sponsors page</a> built with four Views embedded into a Panel.</p> <h3>Call to Action on Views for Usability</h3> <p>They are using some PHP in the Views headers and block bodies to present appropriate call-to-action blocks to site visitors. For example, on the sessions view, anonymous users see a suggestion to register for the camp. If you are logged in and registered you'll see a request to "submit a session". The same is true for the voting widgets and any other privileged callouts that require the "attendee" role, triggered by a successful Ubercart checkout. In the LA camp site, as it was a free event, any registered user had these abilities.</p> <h3>Performance and troubles with Pressflow</h3> <p>The Drupalcamp Atlanta site is using Pressflow and Varnish to maintain a fast response time for their visitors. In fact, Brent is giving a presentation on <a href="http://drupalcampatlanta.com/sessions/converting-drupal-site-pressflowmercury">Using Pressflow and Mercury to achieve a super fast site</a>. However, Pressflow caused some problems with the Ubercart shopping cart block so Brent had to use some custom code and the Ajax cart module to let anonymous users see the cart contents.</p> <h3>Schedule of Events: Always a challenge</h3> <p>One area where they want to do more is the Schedule. Currently it's just a Google Spreadsheet embedded into the page, but ideally it could be built based on Views. As part of GVS work on the <a href="http://drupal.org/project/cod">COD - the Conference Organizing Distrubution</a> distribution, we will be releasing a Views+CCK based schedule builder in the next few weeks.</p> <h3>Conference Organizing Distribution vs. Build your own</h3> <p>When I asked Brent about why they didn't use COD he said it was simply a lack of knowledge of COD's availability. He said they based some of the site on the features from Drupalcamp Colorado and just didn't know that they had been packaged up into the <a href="http://drupal.org/project/cod_support">COD_Support</a> features.</p> <p>For the future, though, he said he would definitely base his work on the COD and COD_Support packages since they are a modular, features-based system that make it easy to pick and choose the parts you need and then contribute back enhancements, while maintaining the ability to modify workflow through customization. Brent also feels it's much better using a distribution where you start off with a fresh installation and turning on compartmentalized features as you need them rather than using a database export which may have cruft in it.</p> <p>A few weeks after our conversation, Brent got back in touch with me to say:</p> <blockquote><p>We're running into groups who want one account to set up<br /> multiple attendees. Live and learn. Take it as validation to the COD<br /> approach and uc_signup.</p></blockquote> <p>That was a feature that GVS built into UC Signup from the beginning and which was used on the Drupalcamp Colorado site by several large companies, one of which purchased tickets for their 30 attendees all at once. Brent disabled the feature at the cart level to make their site simpler.</p> <h3>Sharing Events Best Practices</h3> <p>It's great to hear about best practices in building event management sites and to share those ideas with other camp builders.</p> <ul> <li>Last weekend I participated in a call with the fun folks from LA Drupal which is now available: <a href="http://drupal-la.blip.tv/file/4054612">LA Drupal Podcast 8: Rocking Drupal</a> where we discussed the future of camps vs. summits vs. cons and the idea of a distribution like COD.</li> <li>This coming Wednesday, September 8th, GVS will be hosting a <a href="http://groups.drupal.org/node/89214">Free COD support hour</a> in IRC (#drupal-cod) and Skype. This is just the first of what will hopefully be many events where Drupal site builders can get together to share tips and tricks and get support.</li> </ul> http://growingventuresolutions.com/blog/drupalcamp-atlanta-and-best-practices-event-websites-drupal#comments Planet Drupal conference organizing distribution DrupalCamp ubercart uc_signup Thu, 02 Sep 2010 00:58:11 +0000 Greg 1096 at http://growingventuresolutions.com Submitting Protected Forms Programatically with Safe User Impersonation http://growingventuresolutions.com/blog/submitting-protected-forms-programatically-safe-user-impersonation <p>When a form protected by spam prevention measures such as captcha or Mollom is submitted with drupal_execute, validation can fail unless the spam protection is properly suppressed.</p> <p>This blog post describes the background and solution to a bug that previously existed in the Signup Integration for Ubercart module (uc_signup), and explains the techniques used to fix the bug. It is written with developers and aspiring developers in mind, though other people interested in how Drupal works might also find it interesting.</p> <p><a href="http://api.drupal.org/api/function/drupal_execute/6">drupal_execute</a> is a function often used in data imports that allows a developer to take a collection of form values and submit them programatically.<br /> A main reason to use drupal_execute over another technique such as <a href="http://api.drupal.org/api/function/user_save/6">user_save()</a> is that with drupal_execute, Drupal calls the validation and submission functions for the form.</p> <h3>The Context: How uc_signup Uses drupal_execute</h3> <p>In the <a href="http://drupal.org/project/uc_signup">Signup integration for Ubercart</a> module, we sometimes create a new user account and populate the user's profile with data that was submitted on a form separate from the core user profile form. In earlier versions of uc_signup, we created the new account with user_save, however this <a href="http://drupal.org/node/547242">allowed crafty users to leave required fields blank by skipping the form and proceeding to checkout</a>, so we switched to drupal_execute which ensures that the form's validation gets executed.</p> <h3>The Problem</h3> <p>The drupal_execute function is relatively easy to use -- just pass in the form_id and form values you'd like to submit to the form.</p> <p>However, we soon got a <a href="http://drupal.org/node/585760">bug report</a> with one user reporting a validation error at the time that the new user account is saved, with the <a href="http://drupal.org/project/captcha">captcha module</a> enabled for the user registration form.</p> <p><a href="http://en.wikipedia.org/wiki/Captcha">Captchas</a> often take the shape of "those squiggly letters" used to determine whether you are a human being or a computer program that submits spam to websites.</p> <p>Uc_signup can collect profile information for multiple users on a single "attendee contact information" form that is integrated into the Ubercart checkout process.</p> <p><img src="http://img.skitch.com/20090929-pjhwt3sb57yyna8cnnnu3j7rs.png" title="uc_signup attendee contact info form" /><br /> Uc_signup's Attendee Contact Information" form.</p> <p>By design, this form has a unique form_id, so it isn't protected by captchas that protect the user registration form. The required fields on the attendee information form correspond to those on the user registration form -- except that on the attendee information form, there is no captcha. When uc_signup takes user-entered data from this form and submits it into the user registration form, validation on the user registration form fails because this form has a captcha, which was never presented to the user and is therefore not filled in.</p> <h3>Finding a Solution</h3> <p>So, we needed a way to bypass the captcha protection.<br /> Should we unset the form validation function from the captcha element? Should we remove the captcha element from the form altogether?</p> <p>The simplest and least error-prone solution turns out to be to prevent the captcha from ever being added to the user registration form for this specific situation.</p> <p>Both internal spam prevention services (such as captcha and spam.module) and external ones (such as <a href="http://mollom.com/">Mollom</a> and <a href="http://akismet.com/">Akismet</a>) use Drupal's user permissions system to allow certain users to bypass the protection that they add to forms.</p> <p>drupal_execute submits forms with the permissions of whichever user is logged in (or an anonymous user). In most cases, people who are using the attendee information form will not have permission to bypass spam protection site-wide. The solution to our captcha validation problem is to have our module submit the form as if it were a privileged user. That way, the captcha will never be added to the form.</p> <h3>User Impersonation: Not just for Halloween.</h3> <p><img src="http://growingventuresolutions.com/gvsfiles/user_impersonation_small.jpg" /></p> <p>User impersonation is a technique that developers can use to allow a particular section of code to be run as a particular user. In Drupal, the user with UID 1 has all permissions available on a site. In uc_signup, we impersonate User 1 before performing the drupal_execute so that captcha waves protection for the form.</p> <h3>Practicing Safe Impersonation</h3> <p>It's important to follow best practices when performing user impersonation. Not doing so can allow users on your site to gain control over the account being used for the impersonation, resulting in a serious security vulnerability.</p> <p>After calling <code> global $user;</code>, setting the $user variable equal to a different user account will cause the currently logged in user to switch to that account. That is why it is a best practice to use another variable, such as $account, when working with user accounts <strong>without</strong> the intention of impersonating users.</p> <p>You must set <a href="http://drupal.org/node/218104">session_save_session(FALSE)</a>; before switching to the impersonated user. The reason for this is that if your action fails or interrupts the request with a <a href="http://api.drupal.org/api/function/drupal_goto/6">drupal_goto</a> and session saving is enabled, the user will then be logged in as user 1, with all privileges on your site. By setting this value to FALSE and then back to TRUE, we make sure that the impersonation only exists when we're performing the required action, and does not persist if the action fails.</p> <p><a href="http://www.flickr.com/photos/faeryboots/2874160660"><img src="http://growingventuresolutions.com/gvsfiles/impersonation_wrong.png" /></a></p> <p>The code snippet below is a more heavily commented version of the code used in uc_signup. This code snippet impersonates User 1, submits the user registration form with the previously entered values, and then switches the session back to the user who was previously logged in. Note that we have three variables that refer to user accounts:</p> <p><code>global $user</code> - The account of the currently logged in user.<br /> <code>$temp_user</code> - The variable used to store the current user's account while we temporarily switch the session to the privileged user.<br /> <code>$account</code> - The account created as a result of submitting the user registration form.</p> <p>This code actually appears inside of a <code>foreach</code> loop and some conditional logic, so that it if the attendee contact information form collects information for multiple new users, the user registration form is submitted once for each new account.</p> <p>To get the full context of this snippet, you may wish to <a href="http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/uc_signup/uc_signup.module?view=markup">view the full contents of uc_signup.module</a>.</p> <p><div class="codeblock"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">//Load the global $user object that contains the account of the currently&nbsp;&nbsp; logged in user.<br /></span><span style="color: #007700">global </span><span style="color: #0000BB">$user</span><span style="color: #007700">;<br /></span><span style="color: #FF8000">//Preserve this account in the $temp_user variable so that we can switch back to it after impersonating the privileged user.<br /></span><span style="color: #0000BB">$temp_user </span><span style="color: #007700">= </span><span style="color: #0000BB">$user</span><span style="color: #007700">;<br /></span><span style="color: #FF8000">//We must set this to FALSE in case the operation on the following lines fails.<br /></span><span style="color: #0000BB">session_save_session</span><span style="color: #007700">(</span><span style="color: #0000BB">FALSE</span><span style="color: #007700">);<br /></span><span style="color: #FF8000">//Switch the currently logged in user to user 1.<br /></span><span style="color: #0000BB">$user </span><span style="color: #007700">= </span><span style="color: #0000BB">user_load</span><span style="color: #007700">(</span><span style="color: #0000BB">1</span><span style="color: #007700">);<br /></span><span style="color: #FF8000">//Submit the user registration form.<br /></span><span style="color: #0000BB">drupal_execute</span><span style="color: #007700">(</span><span style="color: #DD0000">'user_register'</span><span style="color: #007700">, </span><span style="color: #0000BB">$form_state</span><span style="color: #007700">);<br /></span><span style="color: #FF8000">//Switch back to the account we saved in the $temp_user variable.<br /></span><span style="color: #0000BB">$user </span><span style="color: #007700">= </span><span style="color: #0000BB">$temp_user</span><span style="color: #007700">;<br /></span><span style="color: #FF8000">//Restore session saving.<br /></span><span style="color: #0000BB">session_save_session</span><span style="color: #007700">(</span><span style="color: #0000BB">TRUE</span><span style="color: #007700">);<br /></span><span style="color: #FF8000">//Populate the $account variable with the account created as a result of submitting the user_register form. We later go on to sign up this user to one or more events that are being purchased.<br /></span><span style="color: #0000BB">$account </span><span style="color: #007700">= </span><span style="color: #0000BB">$form_state</span><span style="color: #007700">[</span><span style="color: #DD0000">'user'</span><span style="color: #007700">];<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div></p> <div class="field field-type-nodereference field-field-related-project"> <div class="field-label">Related Project:&nbsp;</div> <div class="field-items"> <div class="field-item odd"> <a href="/portfolio/aussie-australian-united-states-services-education">AUSSIE (Australian United States Services in Education)</a> </div> </div> </div> http://growingventuresolutions.com/blog/submitting-protected-forms-programatically-safe-user-impersonation#comments Planet Drupal captcha mollom security uc_signup user impersonation Wed, 30 Sep 2009 17:45:02 +0000 Ezra 683 at http://growingventuresolutions.com Usability Testing of Ubercart and Uc_signup http://growingventuresolutions.com/blog/usability-testing-ubercart-and-uc-signup <p>Ezra Glidesgame has been writing a module to integrate the <a href="http://drupal.org/project/signup">Signup module</a> for managing event registration with the <a href="http://drupal.org/project/ubercart">Ubercart e-commerce module</a>: <a href="http://drupal.org/project/uc_signup">Signup integration for Ubercart</a> (short name: uc_signup). The uc_signup registration process was designed to support a wide variety of use cases (one user potentially signing up multiple other users for different events, in different quantities) while still being easy to use. We wanted to see what users thought of the preliminary uc_signup registration process, so in June we ran a small usability test here at the Growing Venture Solutions office. The test revealed several subtle and interesting findings that applied to the uc_signup module, the Ubercart checkout process, and specific aspects of the client site's configuration.</p> <h3>First, some background on the project</h3> <p>AUSSIE provides professional development in the field of K-12 education. One of their services is to offer workshops around the country, with registration done through their website. Uc_signup is being written to give AUSSIE more control of the look and administration of their sign-up process, and internalize their events management, which is currently being hosted by <a href="http://www.eventbrite.com/">Eventbrite</a>. The improved Aussie site is scheduled to launch in August.</p> <h3>About our Usability Participants</h3> <p>We recruited 4 participants having the following profile characteristics:</p> <ul> <li>Two men and two women between the ages of 29-36</li> <li>All with general office experience and good computer proficiency</li> <li>All use the internet daily, with a range of 3 to 40 hours per week</li> <li>Internet purchasing comfort level: comfortable to strongly prefer</li> <li>Three of the participants had previously signed up online for classes or workshops</li> </ul> <p>Participants were recruited prior to testing with the assistance of requests to FFF (“Friends of Friend and Family”). Participants were compensated $50 for their time. <a href="http://www.boxesandarrows.com/view/testing-incentives">(Read this article about tester compensation.)</a></p> <p><strong> Where/How</strong><br /> We hosted the tests in our office, running a scaled back development version of the AussiePD site. We used Camtasia Studio for screen and audio/video capture. Present at each session were the moderator (me) and 1 to 2 observers.</p> <p><strong>Collected data:</strong></p> <ul> <li>Participant background information, and their internet usage experience</li> <li>Observation of tasks performed – errors, obstacles, comments</li> <li>Participants’ impression of the sign-up process – in discussion and in writing</li> </ul> <p><strong>Test &amp; Findings:</strong><br /> Participants were asked to sign up and purchase tickets for two fictional workshops. The overall task performance was successful; each participant was able to complete the tasks within the expected time frame. In post-test discussions and surveys, participants all agreed that the sign-up and checkout process were what they expected and typical of what they’ve used in other online purchasing experiences.</p> <p>However, all participants made similar minor errors and/or encountered obstacles, with varying degrees of recovery.</p> <h3>Finding #1- Purchaser not entering atendee e-mail addresses</h3> <p>On the first registration screen users are asked to enter an e-mail address for each person attending the workshop. One user simply entered the attendees' names and because uc_signup was still in relatively early development, the submission went through unchallenged.</p> <p><img src="http://growingventuresolutions.com/gvsfiles/aut-attendee-email.jpg" width="670px" /></p> <p>Suggested fixes:<br /> 1. Change the screen title from “Attendee Information” to “Attendee E-mail Addresses”.<br /> 2. Validate the information entered.<br /> * FIXED: <a href="http://drupal.org/node/525542">http://drupal.org/node/525542</a></p> <h3>Finding #2 - Entering full name in “First Name” profile field</h3> <p>For every email address entered that does not have a corresponding account on the Drupal site, uc_signup allows the purchaser to fill out the configured core Profile fields and create a new account. Without custom theming, the first and last name profile fields appeared on different lines.</p> <p>Three of four participants entered full names in the “First name” field and had to correct themselves after they tabbed down and saw the “Last name” field. Two participants made this error more than once.</p> <p><img src="http://growingventuresolutions.com/gvsfiles/aut-name.jpg" width="670px" /></p> <p>Suggested fix:<br /> We recommended that this page be themed so that the first and last name fields are on the same line. Since these fields are configurable Profile module fields, they are specific to the AUSSIE project.</p> <h3>Finding #3 - "Previous" is the default submit button on the multi-step attendee information form</h3> <p>Next/Previous step buttons appear at the bottom of the 2-step attendee information form. Because the "previous" button was the first in the form, it became the default submit button. That meant that users would enter information, press enter expecting to go to the next step, and get sent to the previous one.</p> <p>Suggested fix:<br /> As a short term fix, we reversed the order of these two buttons. However, that results in an awkward button order for left-to-right readers.</p> <p>A better long term solution exists as part of the issue mentioned below, which proposes making each step of the form appear at its own path.</p> <ul> <li>Posted issue: <a href="http://drupal.org/node/540136">http://drupal.org/node/540136</a></li> </ul> <h3>Finding #4 – Purchaser Confusing “Country” drop-down for “State” drop-down</h3> <p>On the Ubercart's “Delivery Information” pane, three participants mistook the “Country” drop-down box for a “State” drop-down box, inadvertently selecting “Canada” (presumably because they were looking for a word starting with the letter “C” for “Colorado”.)</p> <p><img src="http://growingventuresolutions.com/gvsfiles/aut-country.jpg" width="670px" /></p> <p>Confusion can also be attributed to the fact that it is more typical to find the country selector, if there is one, to be the last line of an address sequence.</p> <p>Suggested fixes:<br /> 1. Since “Country” needs to precede “State/Province” in order to populate states and provinces, we suggest moving the “Country” drop-down out of the address sequence – perhaps before the Attendee name, or<br /> 2. Replace pre-populated City and Country dropdowns with text fields, eliminating the state/province field's dependence on the country field.<br /> * Posted issue: <a href="http://drupal.org/node/529108">http://drupal.org/node/529108</a></p> <p><strong>Finding #5 – Purchaser Unintentionally clicking “Remove” checkbox </strong></p> <p>When viewing their workshop in the shopping cart page, two participants clicked the "Remove" box next to the item, as if to confirm the selection.</p> <p><img src="http://growingventuresolutions.com/gvsfiles/aut-remove.jpg" width="670px" /></p> <p>Suggested fixes:<br /> 1. Move the location of the “Remove” checkbox to the left of the “Qty.” so that it is more visually connected to the idea of quantity, and/or<br /> 2. Perhaps change the word “Remove” to something like: “Remove?” or “Delete?” to make it appear less like a confirmation selection, or<br /> 3. Replace the remove checkbox with a "remove" button, like on Amazon.com.<br /> * Posted issue: <a href="http://drupal.org/node/529110">http://drupal.org/node/529110</a></p> <p><strong>Finding #6 – Ubercart: Purchasers miss the “Saved Addresses” option</strong></p> <p>On the Checkout screen, in the “Delivery Information” pane, two participants repeatedly missed the "Saved Addresses" option and manually re-entered their billing name and address.</p> <p><img src="http://growingventuresolutions.com/gvsfiles/aut-saved.jpg" width="670px" /></p> <p>Suggested fixes:<br /> 1. Add more default styling to highlight the text “Saved addresses”, and/or<br /> 2. Add space underneath that line, thereby drawing attention to it, or<br /> 3. On the checkout page, show the most recently used address (if there is one) and provide a "Change" button that goes to a page showing all the saved addresses, as well as a new address field set, similar to Amazon.com<br /> * Posted issue: <a href="http://drupal.org/node/529130">http://drupal.org/node/529130</a></p> <h3>Usability testing results in surprises and best practices</h3> <p>Overall, the workflow for collecting attendee information proved to be successful. Still, no matter how much you think through a workflow when you're designing it, real-world users will are likely to surprise you by finding potential improvements that you may have missed. In the course of watching participants use the uc_signup module, we learned some other valuable lessons - “rules-of-thumb” that are important to improving the general work flow for all modules and design situations. One example from Greg is to pre-fill data whenever possible. Evelyn was reminded of the importance of label names.</p> <p>This project is a collaboration working with Andy Hieb at <a href="http://dtek.net">Dtek Digital Media</a>, and sponsored by client Australian United States Services in Education (AUSSIE). This is also an example of how community minded clients and companies can collaborate to get better results for their end-users while improving community software for everyone. All of us at GVS, Dtek and AUSSIE are excited to help make a useful new contributed module possible, and do usability testing to seek improvements for the software we share. Uc_signup currently has a stable beta release, and issues found in our usability test have either already been fixed, or are in the queue waiting to be fixed.</p> <div class="field field-type-nodereference field-field-related-project"> <div class="field-label">Related Project:&nbsp;</div> <div class="field-items"> <div class="field-item odd"> <a href="/portfolio/aussie-australian-united-states-services-education">AUSSIE (Australian United States Services in Education)</a> </div> </div> </div> http://growingventuresolutions.com/blog/usability-testing-ubercart-and-uc-signup#comments Planet Drupal event management ubercart uc_signup usability Thu, 06 Aug 2009 01:08:30 +0000 evelyn 564 at http://growingventuresolutions.com