Add a drag-to-rank form to WordPress: a shortcode you can build today

· 5 min read

Most WordPress forms are built around text boxes, checkboxes, and dropdowns. They work well for collecting names and messages. They do not have a native way to let visitors put a list of options into their preferred order, which is what you need when the question is 'rank these from most important to least' rather than 'pick one.'

The usual workaround is to label each option with a numbered dropdown: Rate this feature 1 through 5. It is awkward to fill in, and the results require work to interpret. A drag-to-rank form asks the same question in a way that is intuitive and delivers the answer as a readable ordered list.

A small shortcode handles this without a full form plugin. You add [drag_rank] to any post or page, supply a list of items, and visitors see a vertical list they can reorder by dragging. When they submit, the ranked list arrives in your inbox along with their name and email.

What one build gives you

  • Shortcode [drag_rank] with items, to, subject, and button attributes
  • HTML5 Drag and Drop sorting with no JavaScript library or external dependency
  • Name and email collection from the submitter
  • Email delivery of the ranked list via wp_mail to a configurable address
  • Confirmation message displayed on the same page after submission

What it does not do

  • Database storage of results, one email per submission only
  • Mobile touch-based dragging, HTML5 drag events do not fire on touchscreens
  • Multiple ranking questions combined into a single form submission
  • Aggregated results view or reporting dashboard in wp-admin
  • Integration with Gravity Forms, WPForms, or Contact Form 7

The prompt

Loads into the composer so you can edit it first. Nothing is built, and nothing is charged, until you send it.

Build a WordPress plugin called Drag to Rank Form. Plugin Name: Drag to Rank Form. Description: A [drag_rank] shortcode that lets visitors rank a list of items by dragging them into order and emails the result. Single PHP file. No external CSS or JavaScript libraries. Register a shortcode [drag_rank] with these attributes: items (comma-separated list, required), to (email address string, defaults to get_option('admin_email')), subject (string, defaults to 'Ranking submission'), button (string, defaults to 'Submit your ranking'). At the top of the shortcode function, generate a unique ID with uniqid('drr_') to namespace the list and hidden field so multiple shortcodes on the same page do not conflict. If the current URL contains the query parameter drag_rank_success=1, output a <div style='padding:12px;border-left:4px solid #46b450;background:#ecf7ed;margin-bottom:16px;'> with the text 'Thank you. Your ranking has been submitted.' and return early, showing no form. Otherwise, render a <form method='post' action='<?php echo esc_url(admin_url("admin-post.php")); ?>'>. Include: a hidden input name='action' value='drag_rank_submit'; wp_nonce_field('drag_rank_submit','drag_rank_nonce'); a hidden input name='drag_rank_to' value of the escaped to attribute; a hidden input name='drag_rank_redirect' value of get_permalink() escaped; a hidden input name='drag_rank_order' with an id of the unique id plus '_order'. Render a name field and an email field, each required, with max-width 400px and display block. Render a <ul> with the unique id as its HTML id, list-style none, max-width 480px. For each item from the items attribute (trim each one), output a <li> with draggable='true', a data-value attribute of the item text, inline styles for padding 10px 12px, border 1px solid #ddd, margin-bottom 4px, background white, cursor grab, display flex, align-items center, gap 10px, border-radius 3px. Inside the li, a span with color #aaa showing the hamburger character (&#9776;) as a handle, followed by the item text. Render a submit button styled with background #0073aa, white text, no border, padding 8px 18px, border-radius 3px. Add an inline <script> block wrapped in an IIFE. Select the ul by its unique id and the hidden order input by the unique id plus '_order'. Track a dragging variable. Add event listeners on the ul for dragstart (set dragging to event.target.closest('li')), dragover (preventDefault, highlight the target li with outline 2px dashed #0073aa), dragleave (remove the outline from the target li), and drop (preventDefault, remove outline, reorder by inserting dragging before or after the target li based on whether clientY is above or below the target midpoint). On the form submit event, serialize the current li data-value attributes into the hidden order input as a JSON array; if empty, preventDefault and alert the user to drag items first. Register admin_post_drag_rank_submit and admin_post_nopriv_drag_rank_submit handlers pointing to the same function. In the handler: check_admin_referer('drag_rank_submit','drag_rank_nonce'). Sanitize name, email, and to_address from POST (falling back to admin_email for to_address). json_decode the order field; if not a non-empty array, wp_die. Sanitize each item with sanitize_text_field. Get subject from POST or default to 'Ranking submission'. Build email body with name, email, and numbered ranking list. wp_mail to to_address. add_query_arg drag_rank_success=1 to the redirect URL from POST. wp_safe_redirect and exit. No database writes. No external HTTP requests.

Build this pluginAbout 55 credits · the free plan includes enough for one

When drag-to-rank is the right choice

The form type fits questions where order carries meaning. Feature prioritization surveys, preference exercises, and planning sessions where the group is ranking options rather than selecting one are all good candidates. Any question where the relative order matters is more informative when answered with a ranking than with a scale or a checkbox.

A standard dropdown or radio button forces a single choice and throws away the second and third preferences. A ranking form captures the full picture in one submission: not just what someone wants most, but what they want next.

For a site that needs this on one or two pages, installing a full-stack form builder to access a single field type is more than the job requires. The shortcode approach keeps the dependency surface small: one PHP file, no database tables, no settings screen.

What the shortcode does

The [drag_rank] shortcode renders a vertical sortable list and a submit button. It accepts four attributes: items (a comma-separated list of things to rank), to (the email address for results, defaulting to the site admin address), subject (the email subject line), and button (the label on the submit button).

Visitors enter their name and email in two fields above the list, then reorder the items by dragging each row to the position they want. The drag handle is a text icon at the start of each row. The reordering uses the HTML5 Drag and Drop API: no jQuery, no external library.

On submit, the plugin sends an email to the address in to with the submitter's name, email, and the items listed in the order they left them. The page then shows a confirmation message in place of the form. Nothing is written to the database.

  • Shortcode [drag_rank items='...' to='...' subject='...' button='...']
  • Drag-to-reorder list using the HTML5 Drag and Drop API, no library required
  • Name and email fields for the submitter
  • Email delivery of the ranked list via wp_mail to a configurable address
  • Confirmation message displayed on the same page after submission

What the shortcode does not cover

The plugin does not store submissions. You get one email per response. If you want to aggregate results across many respondents, you need either a spreadsheet workflow or a code change to save submissions as a custom post type.

The HTML5 Drag and Drop API does not fire on touch screens. Visitors on phones and tablets will see the list but cannot reorder it by touch. If most of your respondents are on mobile, ask Steem to replace the drag interface with up and down arrow buttons on each row, which work on all devices.

The shortcode handles one ranking question per form. You can place two [drag_rank] shortcodes on the same page and they will operate independently, but there is no way to combine them into a single multi-question submission.

Adding it to a page

Once the plugin is installed, paste the shortcode into any post, page, or text widget. A typical use looks like this: [drag_rank items='Faster checkout, Better search, More product images, Email order updates' to='research@example.com' subject='Customer priorities survey']

The items attribute is the only required one. If you leave out to, results go to the admin email address set in WordPress Settings. If you leave out subject, the email arrives with the subject 'Ranking submission.'

After running the form for a few weeks, the pattern in the emails tells you what respondents consistently put first. If you want that analysis automated, ask Steem to add a results page in wp-admin that counts how often each item appears in positions 1, 2, and 3 across all submissions.

Questions

The list appears but I cannot drag items on my phone.

The HTML5 Drag and Drop API does not fire on touch screens. Visitors on phones and tablets will see the list but cannot reorder it by dragging. If most of your respondents are on mobile, ask Steem to replace the drag interface with up and down arrow buttons on each list item. Those work on all devices and require no touch event handling.

I submitted the form but the email never arrived.

WordPress sends email through PHP mail() by default, which many shared hosts block or route to spam. Install a free SMTP plugin such as WP Mail SMTP, connect it to a sending service like Gmail or Mailgun, then test the form again. This is the cause in nearly every case where wp_mail appears to fail silently.

Can I see all the submissions in a single report instead of separate emails?

Not with this plugin as built. It sends one email per submission and does not write to the database. Ask Steem to add a custom post type that stores each submission as a post with the ranked items and submitter details as post meta, plus a results table in wp-admin that shows how often each item appears in each position.

Can I put two ranking questions on the same page?

Yes. Place two [drag_rank] shortcodes with different items and subject attributes. Each form submits independently and sends its own email. They do not interfere with each other. Give each a different subject so you can tell the results apart in your inbox.

Is there a way to randomize the item order each time the page loads?

Not out of the box. The plugin renders items in the order you list them in the items attribute. To randomize the starting order on each page load, ask Steem to shuffle the items array in PHP before rendering the list. That removes anchoring bias, where respondents tend to rank the first item higher simply because it appears first.

The prompt

Loads into the composer so you can edit it first. Nothing is built, and nothing is charged, until you send it.

Build a WordPress plugin called Drag to Rank Form. Plugin Name: Drag to Rank Form. Description: A [drag_rank] shortcode that lets visitors rank a list of items by dragging them into order and emails the result. Single PHP file. No external CSS or JavaScript libraries. Register a shortcode [drag_rank] with these attributes: items (comma-separated list, required), to (email address string, defaults to get_option('admin_email')), subject (string, defaults to 'Ranking submission'), button (string, defaults to 'Submit your ranking'). At the top of the shortcode function, generate a unique ID with uniqid('drr_') to namespace the list and hidden field so multiple shortcodes on the same page do not conflict. If the current URL contains the query parameter drag_rank_success=1, output a <div style='padding:12px;border-left:4px solid #46b450;background:#ecf7ed;margin-bottom:16px;'> with the text 'Thank you. Your ranking has been submitted.' and return early, showing no form. Otherwise, render a <form method='post' action='<?php echo esc_url(admin_url("admin-post.php")); ?>'>. Include: a hidden input name='action' value='drag_rank_submit'; wp_nonce_field('drag_rank_submit','drag_rank_nonce'); a hidden input name='drag_rank_to' value of the escaped to attribute; a hidden input name='drag_rank_redirect' value of get_permalink() escaped; a hidden input name='drag_rank_order' with an id of the unique id plus '_order'. Render a name field and an email field, each required, with max-width 400px and display block. Render a <ul> with the unique id as its HTML id, list-style none, max-width 480px. For each item from the items attribute (trim each one), output a <li> with draggable='true', a data-value attribute of the item text, inline styles for padding 10px 12px, border 1px solid #ddd, margin-bottom 4px, background white, cursor grab, display flex, align-items center, gap 10px, border-radius 3px. Inside the li, a span with color #aaa showing the hamburger character (&#9776;) as a handle, followed by the item text. Render a submit button styled with background #0073aa, white text, no border, padding 8px 18px, border-radius 3px. Add an inline <script> block wrapped in an IIFE. Select the ul by its unique id and the hidden order input by the unique id plus '_order'. Track a dragging variable. Add event listeners on the ul for dragstart (set dragging to event.target.closest('li')), dragover (preventDefault, highlight the target li with outline 2px dashed #0073aa), dragleave (remove the outline from the target li), and drop (preventDefault, remove outline, reorder by inserting dragging before or after the target li based on whether clientY is above or below the target midpoint). On the form submit event, serialize the current li data-value attributes into the hidden order input as a JSON array; if empty, preventDefault and alert the user to drag items first. Register admin_post_drag_rank_submit and admin_post_nopriv_drag_rank_submit handlers pointing to the same function. In the handler: check_admin_referer('drag_rank_submit','drag_rank_nonce'). Sanitize name, email, and to_address from POST (falling back to admin_email for to_address). json_decode the order field; if not a non-empty array, wp_die. Sanitize each item with sanitize_text_field. Get subject from POST or default to 'Ranking submission'. Build email body with name, email, and numbered ranking list. wp_mail to to_address. add_query_arg drag_rank_success=1 to the redirect URL from POST. wp_safe_redirect and exit. No database writes. No external HTTP requests.

Build this pluginAbout 55 credits · the free plan includes enough for one

Read next

Other plugins you can build this way

Each loads into the composer, ready to edit.