I needed to make a little freetagging form to allow users to tag content as they view it - here's how I did it:

Set up a freetagging vocabulary using taxonomy.module and assign it to your content type as usual. Note the vid (vocabulary id) of your freetagging vocabulary (you can find it in the URL when editing the vocabulary). In a custom module, create a new form like so:

// form for adding tags to nodes 
function MY_CUSTOM_MODULE_tag_form($nid = 0) {
  $form = array();
  $form['nid'] = array(
    '#type' => 'hidden',
    '#value' => $nid,
    );
  $form['tag'] = array(
    '#type' => 'textfield',
    '#title' => 'add tag',
    );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('+'),
  );
  return $form;
}

This form simply contains a textfield for the users to enter freetags and a submit button. The hidden 'nid' field will pass the node id of the node where the form appears.

Also add a submit function for the form:

function MY_CUSTOM_MODULE_tag_form_submit($form_id, $form_values) {
  $nid = $form_values['nid'];
  $node = node_load($nid);
  $terms = array();
  foreach($node->taxonomy as $tax) {
    $tags .= $tax->name .', ';
  }
  $tags .= $form_values['tag'];
  $terms['tags'] = array(****NUM**** => $tags); //replace ****NUM**** with the vid of your vocabulary
  taxonomy_node_save($nid, $terms);
  drupal_set_message(t('Your tag has been added.'));
}

The submit function adds the new tags to the node's existing tags and uses taxonomy's taxonomy_node_save function to make it all happen. Be sure to replace ****NUM**** with the numeric vid (vocabulary id) of your freetagging vocabulary. Also note that this code will need adjustment if your content type uses multiple vocabularies.

You can place your form on your nodes directly in your node template by adding
<?php print drupal_get_form('MY_CUSTOM_MODULE_tag_form', $node->nid); ?>
(Note: unless you're in the penile enhancement business you'll want to wrap that in a conditional access statement.)

Only local images are allowed.