diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php
index 8dfbb94c41436ba12f7077d0703f9b89e1224242..d3424f3e41c6b986bc46a553e444a2882f390dae 100644
--- a/include/class.dynamic_forms.php
+++ b/include/class.dynamic_forms.php
@@ -243,6 +243,12 @@ Filter::addSupportedMatches('User Data', function() {
         if (!$f->hasData())
             continue;
         $matches['field.'.$f->get('id')] = 'User / '.$f->getLabel();
+        if (($fi = $f->getImpl()) instanceof SelectionField) {
+            foreach ($fi->getList()->getProperties() as $p) {
+                $matches['field.'.$f->get('id').'.'.$p->get('id')]
+                    = 'User / '.$f->getLabel().' / '.$p->getLabel();
+            }
+        }
     }
     return $matches;
 }, 20);
@@ -327,6 +333,12 @@ Filter::addSupportedMatches('Ticket Data', function() {
         if (!$f->hasData())
             continue;
         $matches['field.'.$f->get('id')] = 'Ticket / '.$f->getLabel();
+        if (($fi = $f->getImpl()) instanceof SelectionField) {
+            foreach ($fi->getList()->getProperties() as $p) {
+                $matches['field.'.$f->get('id').'.'.$p->get('id')]
+                    = 'Ticket / '.$f->getLabel().' / '.$p->getLabel();
+            }
+        }
     }
     return $matches;
 }, 30);
@@ -612,6 +624,39 @@ class DynamicFormEntry extends VerySimpleModel {
         return $this->_clean;
     }
 
+    /**
+     * Compile a list of data used by the filtering system to match dynamic
+     * content in this entry. This returs an array of `field.<id>` =>
+     * <value> pairs where the <id> is the field id and the <value> is the
+     * toString() value for the entered data.
+     *
+     * If the field returns an array for its ::getFilterData() method, the
+     * data will be added in the array with the keys prefixed with
+     * `field.<id>`. This is useful for properties on custom lists, for
+     * instance, which can contain properties usefule for matching and
+     * filtering.
+     */
+    function getFilterData() {
+        $vars = array();
+        foreach ($this->getFields() as $f) {
+            $tag = 'field.'.$f->get('id');
+            if ($d = $f->getFilterData()) {
+                if (is_array($d)) {
+                    foreach ($d as $k=>$v) {
+                        if (is_string($k))
+                            $vars["$tag$k"] = $v;
+                        else
+                            $vars[$tag] = $v;
+                    }
+                }
+                else {
+                    $vars[$tag] = $d;
+                }
+            }
+        }
+        return $vars;
+    }
+
     function forTicket($ticket_id, $force=false) {
         static $entries = array();
         if (!isset($entries[$ticket_id]) || $force)
@@ -918,6 +963,12 @@ class DynamicList extends VerySimpleModel {
         return $this->_form;
     }
 
+    function getProperties() {
+        if ($f = $this->getForm())
+            return $f->getFields();
+        return array();
+    }
+
     function getForm() {
         return $this->getConfigurationForm();
     }
@@ -1022,6 +1073,17 @@ class DynamicListItem extends VerySimpleModel {
         return $this->_config;
     }
 
+    function getFilterData() {
+        $raw = $this->getConfiguration();
+        $props = array();
+        foreach ($this->getConfigurationForm()->getFields() as $field) {
+            $tag = $field->get('id');
+            if (isset($raw[$tag]))
+                $props[".$tag"] = $field->toString($raw[$tag]);
+        }
+        return $props;
+    }
+
     function setConfiguration(&$errors=array()) {
         $config = array();
         foreach ($this->getConfigurationForm()->getFields() as $field) {
@@ -1166,6 +1228,14 @@ class SelectionField extends FormField {
             return $item->toString();
         return $value;
     }
+
+    function getFilterData() {
+        $data = array(parent::getFilterData());
+        if (($v = $this->getClean()) instanceof DynamicListItem) {
+            $data = array_merge($data, $v->getFilterData());
+        }
+        return $data;
+    }
 }
 
 class SelectionWidget extends ChoicesWidget {
diff --git a/include/class.forms.php b/include/class.forms.php
index 61e0ce0fea3d186fa02fb10ea8b9016920b5cf22..d1f394868d5364615f6125d8d5e9bf7dabd2941a 100644
--- a/include/class.forms.php
+++ b/include/class.forms.php
@@ -322,6 +322,14 @@ class FormField {
         return $this->toString($value);
     }
 
+    /**
+     * Convert the field data to something matchable by filtering. The
+     * primary use of this is for ticket filtering.
+     */
+    function getFilterData() {
+        return $this->toString($this->getClean());
+    }
+
     function getLabel() { return $this->get('label'); }
 
     /**
diff --git a/include/class.organization.php b/include/class.organization.php
index 9e11b212f6037623d1d17fbb12ab40771330624b..3a8a11b0260828402e7ff7b8f6d07dfcd8cd2cfe 100644
--- a/include/class.organization.php
+++ b/include/class.organization.php
@@ -202,8 +202,7 @@ class Organization extends OrganizationModel {
         foreach ($this->getDynamicData() as $entry) {
             if ($entry->getForm()->get('type') != 'O')
                 continue;
-            foreach ($entry->getFields() as $f)
-                $vars['field.'.$f->get('id')] = $f->toString($f->getClean());
+            $vars += $entry->getFilterData();
             // Add special `name` field
             $f = $entry->getForm()->getField('name');
             $vars['field.'.$f->get('id')] = $this->getName();
@@ -431,6 +430,12 @@ Filter::addSupportedMatches('Organization Data', function() {
         if (!$f->hasData())
             continue;
         $matches['field.'.$f->get('id')] = 'Organization / '.$f->getLabel();
+        if (($fi = $f->getImpl()) instanceof SelectionField) {
+            foreach ($fi->getList()->getProperties() as $p) {
+                $matches['field.'.$f->get('id').'.'.$p->get('id')]
+                    = 'Organization / '.$f->getLabel().' / '.$p->getLabel();
+            }
+        }
     }
     return $matches;
 },40);
diff --git a/include/class.ticket.php b/include/class.ticket.php
index 5e8fde62f4459c32d36bddf69c7b37f28c908e37..57a8077e5d6361ba5ee048e42be7f8242960c912 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -2227,8 +2227,7 @@ class Ticket {
             $errors += $form->errors();
 
         // Unpack dynamic variables into $vars for filter application
-        foreach ($form->getFields() as $f)
-            $vars['field.'.$f->get('id')] = $f->toString($f->getClean());
+        $vars += $form->getFilterData();
 
         // Unpack the basic user information
         if ($vars['uid'] && ($user = User::lookup($vars['uid']))) {
diff --git a/include/class.user.php b/include/class.user.php
index eaa6af0bd034e337476fc8943fed1b8114103fc3..b137d49ee8e0de97d63db576baab32569a92cfbb 100644
--- a/include/class.user.php
+++ b/include/class.user.php
@@ -298,8 +298,7 @@ class User extends UserModel {
         foreach ($this->getDynamicData() as $entry) {
             if ($entry->getForm()->get('type') != 'U')
                 continue;
-            foreach ($entry->getFields() as $f)
-                $vars['field.'.$f->get('id')] = $f->toString($f->getClean());
+            $vars += $entry->getFilterData();
             // Add in special `name` and `email` fields
             foreach (array('name', 'email') as $name) {
                 if ($f = $entry->getForm()->getField($name))