Tag is a basic functional unit in ITL — Interchange Tag Language. It is to Interchange what HTML tags are to a HTML page, or binary executables to an Unix shell.

As tags and their usage are explained under the ITL glossary entry, we are going to explain usertag inclusion in the Interchange server and usertag programming here.

Usertag inclusion

Usertag programming

Place of definition

Tags have traditionally been defined in lib/Vend/ file in the Interchange source tree. While some of the crucial tags are still defined there (search for ^sub tag_ in the file) to solve the chicken-or-egg problem, new tags should be created as standalone files within the code/ directory in the Interchange source. This makes them more manageable and allows you to easily "deactivate" unused tags and decrease IC;'s memory footprint (as explained above).

Tag types

Even though all Interchange tags are generally called tags or usertags, there are actually three types of tags: system tags, user tags and UI tags. There's no functional difference between them, but we've decided to introduce a rough distinction.

  • System tags (or core tags) are defined in lib/Vend/ and code/SystemTag/ in Interchange source. They are used by core Interchange modules (lib/Vend/*.pm files) and are required for a functional installation. Some files have the extension .coretag, and some have the usual .tag, but there's no difference. (.tag is preferred for your custom tags).

  • User tags are defined in code/UserTag/ directory and form a collection of commonly used Interchange tags. This is the most common type and directly intended for custom catalog programming.

  • UI (User Interface) tags are defined in code/UI_Tag/ directory and form a collection of extra tags used by our Admin UI interface.

A catalog that is not running the Admin UI should, theoretically, be able to do without the whole code/UI_Tag/ directory. However, as very useful tags are found within all three types, the AccumulateCode approach is preferred over this crude directory-based selection.

Tag restrictions and global code

Global usertags (defined at the Interchange server level) run directly under Interchange server permissions, without restrictions.

Catalog usertags (defined at the catalog level), however, run under safe restrictions to maximize security.

You should run all your custom tags at catalog-level and eventually let some of the restrictions loose using SafeUntrap configuration directive. Run global usertags only when there is no other option, and make sure your code is as resilient to arbitrary user input as possible.

Location for custom usertags

Usertags are defined using the UserTag config directive so, obviously, they have to be defined in interchange.cfg or catalog.cfg, or files included by those basic configuration files.

While you could add your own tags to the default Interchange directories (within the code/ directory, as explained) or even define them in interchange.cfg or catalog.cfg directly, it's generally best if you create a usertag/ directory (at a catalog or global level), put your custom tags there, and include them in the running configuration with the include usertag/*.tag configuration directive.

Basic usertag file

Here's a classic hello world usertag example, containing all the relevant structural elements:

# Licensed under the GNU GPL v2. See file LICENSE for details.
# $Id: usertag,v 1.4 2007-11-14 12:38:08 racke Exp $

UserTag hello-world Order     name
UserTag hello-world addAttr
UserTag hello-world Version   $Revision: 1.4 $
UserTag hello-world Routine   <<EOR
sub {
  my ($name, $opt) = @_;
  my $ret;

  $name ||= "world";
  $name = ucfirst $name;

  if ( $_ = $opt->{surname} ) {
    $_ = ucfirst;
    $name .= " $_";

  $ret = "Hello, $name!";

  return $ret;

After you install the usertag (as explained above), you can test it by using this sample HTML code:

  The default name: [hello-world]

  Name "John": [hello-world john]

  Name "John", surname "Doe": [hello-world name=john surname=doe]

As you can see, each usertag is defined through a series of UserTag lines. All possible UserTag options are explained in the following section.

Usertag options

Recognized usertag options are defined as a Perl hash named %tagCanon in file lib/Vend/

  • Group

  • ActionMap

  • ArrayCode

  • HashCode

  • CoreTag

  • SearchOp

  • Filter

  • FormAction

  • OrderCheck

  • UserTag

  • SystemTag

  • Widget

  • Alias — another name, an alias, for the tag.

    UserTag time Version $Revision: 1.4 $
    UserTag date Alias   time

  • addAttr — pass a hash reference with all user-supplied tag attributes as last argument to the tag handling subroutine.

    UserTag NAME addAttr [VALUE]
    UserTag benchmark addAttr     (implies Yes)
    UserTag benchmark addAttr 1
    UserTag benchmark addAttr 0

  • attrAlias — another name, an alias, for a tag's attribute.

    UserTag meta-info Order     table column key
    UserTag meta-info attrAlias col column

  • attrDefault

  • canNest

  • Description — embedded, one-line tag description.

    UserTag NAME Description TEXT
    UserTag uninstall_feature Description Uninstall feature installed with 'Feature' config directive.
    UserTag uninstall_feature Description <<EOD
    Uninstall feature installed with
    'Feature' config directive.

  • Override

  • Visibility

  • Help

  • Documentation — embedded tag documentation. This can be any free-form text, but sometimes it's handy to write the documentation in Perl POD syntax, as it allows the use of convenient pod2text and related commands to read the documentation.

    UserTag NAME Documentation TEXT
    UserTag tabbed-display Documentation <<EOD
    tabbed-display -- DHTML tabbed display

  • ExtraMeta

  • Gobble

  • hasEndTag — the tag has an end tag. In other words, the tag is a container.

    UserTag NAME hasEndTag [VALUE]
    UserTag widget hasEndTag     (implies Yes)
    UserTag widget hasEndTag 1
    UserTag widget hasEndTag 0

  • Implicit

  • Interpolate — interpolate tag data. Due to a poor naming choice, this option behaves differently for non-container and container tags.

    For non-container tags, it specifies whether tag output should be reparsed for more Interchange tags.

    For container tags, it specifies whether tag body should be interpolated before being passed to the tag. Another option, NoReparse then controls whether final tag output should be reparsed for more Interchange tags.

    Interpolation is turned off by default.

    UserTag NAME Interpolate [VALUE]
    UserTag table-organize Interpolate     (implies Yes)
    UserTag table-organize Interpolate 1
    UserTag table-organize Interpolate 0

  • InvalidateCache

  • isEndAnchor

  • noRearrange

  • Order

  • PosNumber — number of positional tag parameters. This option is not required as the number is automatically calculated from the Order option.

    UserTag NAME PosNumber COUNT
    UserTag test Order     opt1 opt2 opt3
    UserTag test PosNumber 3

  • PosRoutine

  • MapRoutine

  • NoReparse — do not reparse output from container tags for more Interchange tags. This option has no effect on non-container tags.

    Reparsing is turned on by default (NoReparse 0).

    UserTag NAME NoReparse [VALUE]
    UserTag either NoReparse     (implies Yes)
    UserTag either NoReparse 1
    UserTag either NoReparse 0

  • JavaScriptCheck

  • Required

  • Routine

  • Version

DocBook! Interchange!