Setup for a Large CiviCRM intake form

Jump to: navigation, search

I'm working on a project that involves case management, CiviCRM, and a large (approximately 300 question) intake form. After trying a few different recipies, here is what finally worked the best. The screenshots come from my development CiviCRM instance.

First, we need an activity type for our Intake form. I called mine "Intake B". Here's how the activity is configured. Note that it's a "Case" activity.


Next we need a case type. I called mine "Test foreclosure", since the work involves foreclosure support. One of the Case Activites is "Intake B", which is our intake form.


Our intake form needs fields. I spread these fields over five custom fieldsets (so, 60 questions per fieldset). Why do this? Under the hood, CiviCRM creates a database table for each fieldset. Given enough fields, there are two issue you can run into

  • The size of your record might exceed the maximum database record size. With MariaDB/XtraDB, this is 64k. If you run into this limit, you'll have to use different fieldsets.
  • UI. If you put too many fields in a custom fieldset, Civi's Custom
  • Fieldset UI (Customize Data and Screens > YOUR FIELDSET NAME > view and edit custom fields) becomes very unresponsive. Simply refreshing the page caused my browser (Firefox or Chromium) to peg a CPU for several seconds at a time. A javascript profiler tells me the CPU time is being spent in jquery.min.js. If I had more bandwidth, I'd try to understand what civicrm/admin/custom/group/field is doing with jquery. Lacking bandwidth, I'll use fewer fields per fieldset. 60--75 fields gives acceptable performance.

Here's the configuration for one of my custom fieldsets. Note that the fieldset is used for Activities of type "Intake B". I used the same setup for each of the five custom fieldsets.


The real version will have a more descriptive name than "Custom Fieldset 1".

We've spread our intake form across five different fieldsets, and under the hood, CiviCRM has spread these across five different database tables. In the database world, we call this process `denormalization'. In the final version, I'll try to denormalize by form section, so that each major sections goes into a separate table.

CiviCRM custom value tables have an `entity_id' column, which in our case, will be an activity ID. When Civi needs to reassemble one of our Intake B activity records, it'll essentially be joining columns on their activity id.

To wrap up, we have some webform/webform_civicrm things to configure. There's a contact (the case client)


There's a case


And there's an activity


The webform is configured to

  • Use a progress bar,
  • enable "Save Draft",
  • and automatically save drafts between pages

There's a page break every 15 questions or so. That's a lot of pages, but I think this will provide a decent amount of protection against data loss.

Webform warned me that my 300 question form (with some extra field for contacts) used 1200+ form fields. To accomodate this, I had to make a small addition to php.ini

 max_input_vars = 2000

This could be lower; 2000 gives us headroom, in case anyone wants to add more fields to the form.

How does one create 300 fields to test a large form? CiviCRM's CustomField API works very nicely. If you understand REST, Help > Developer > API Explorer provides all the details you need.