Extensions - Custom Tag Paths

Configure paths where ColdFusion searches for custom CFML tags

Overview

Custom Tag Paths define directories where ColdFusion searches for custom CFML tags that can be invoked using <cf_tagname> syntax. These paths allow you to organize reusable tag libraries and share them across multiple applications without using <cfmodule>with explicit paths.

Modern Alternatives: While custom tags are still supported, modern ColdFusion development typically uses CFC components for reusable logic. Consider using CFCs with component mappings for new projects as they offer better structure, encapsulation, and IDE support.

Understanding Custom Tags

Custom tags are CFML templates that can be invoked like built-in ColdFusion tags.

What are Custom Tags?

PurposeReusable CFML templates invoked as tags
Syntax<cf_myTag attribute="value">
File NamingTag name corresponds to filename (e.g., myTag.cfm)
Use CasesUI components, formatted output, data processing, legacy code
Key Features:
  • Support both start and end tags with body content
  • Access attributes via attributes scope
  • Return values through caller scope
  • Execution modes: start, end, inactive

Custom Tags vs CFCs

Custom TagsBest for: UI output, HTML generation, legacy code
Invocation: <cf_tag> syntax
Organization: Flat file structure
CFCsBest for: Business logic, data access, APIs, services
Invocation: Object methods, component functions
Organization: Object-oriented with methods and properties
Recommendation: Use CFCs for new development. Custom tags are primarily maintained for backward compatibility and simple UI components where tag-like syntax is preferred.

Configuring Custom Tag Paths

Define directories where ColdFusion searches for custom tags.

Adding Custom Tag Paths

Path FormatAbsolute file system paths or relative to ColdFusion root
Windows ExampleD:\shared\customtags
Linux Example/var/www/shared/customtags
Search OrderCurrent directory → configured paths (top to bottom) → web root
Path Priority: ColdFusion searches for custom tags in this order:
  • 1. Current template's directory
  • 2. Custom tag paths (in the order listed)
  • 3. Web root customtags directory
  • 4. ColdFusion installation customtags directory

Default Custom Tag Directory

Location{cf-root}/CustomTags
PurposeBuilt-in directory always searched for custom tags
RecommendationUse for server-wide shared tags, but prefer application-specific paths

Multiple Path Management

Order MattersTags are found in first matching directory
Best PracticePlace most frequently used paths first for better performance
Name Conflicts: If multiple directories contain tags with the same name, only the first one found will be used. Organize tags carefully to avoid unexpected behavior.

Creating Custom Tags

Example custom tag implementation showing common patterns:

Custom Tag Examples
<!--- formatPrice.cfm - Simple custom tag --->
<!--- Usage: <cf_formatPrice amount="19.99" currency="USD"> --->

<cfparam name="attributes.amount" type="numeric">
<cfparam name="attributes.currency" default="USD">

<cfswitch expression="#attributes.currency#">
  <cfcase value="USD">
    <cfset symbol = "$">
  </cfcase>
  <cfcase value="EUR">
    <cfset symbol = "€">
  </cfcase>
  <cfcase value="GBP">
    <cfset symbol = "£">
  </cfcase>
  <cfdefaultcase>
    <cfset symbol = attributes.currency>
  </cfdefaultcase>
</cfswitch>

<cfoutput>#symbol##numberFormat(attributes.amount, "0.00")#</cfoutput>
<!--- panel.cfm - Tag with body content --->
<!--- Usage:
<cf_panel title="Settings" type="info">
  <p>Panel content here</p>
</cf_panel>
--->

<cfparam name="attributes.title" type="string">
<cfparam name="attributes.type" default="default">

<cfif thisTag.executionMode eq "start">
  <!--- Start tag: output opening HTML --->
  <cfoutput>
    <div class="panel panel-#attributes.type#">
      <div class="panel-heading">
        <h3 class="panel-title">#attributes.title#</h3>
      </div>
      <div class="panel-body">
  </cfoutput>
<cfelse>
  <!--- End tag: output closing HTML --->
  <cfoutput>
      </div>
    </div>
  </cfoutput>
</cfif>
<!--- queryToArray.cfm - Tag that returns data --->
<!--- Usage:
<cf_queryToArray query="#myQuery#" returnVar="resultArray">
<cfoutput>#arrayLen(resultArray)#</cfoutput>
--->

<cfparam name="attributes.query" type="query">
<cfparam name="attributes.returnVar" type="string">

<cfscript>
  // Convert query to array of structs
  result = [];

  for (row in attributes.query) {
    arrayAppend(result, {
      id: row.id,
      name: row.name,
      email: row.email
    });
  }

  // Return data to caller scope
  caller[attributes.returnVar] = result;
</cfscript>

Invoking Custom Tags

Different methods for calling custom tags:

Custom Tag Invocation Methods
<!--- Direct invocation using cf_ prefix --->
<cf_formatPrice amount="29.99" currency="USD">

<!--- Tag with body content --->
<cf_panel title="User Info" type="info">
  <p>User information goes here</p>
</cf_panel>

<!--- Self-closing tag --->
<cf_formatPrice amount="19.99" />
<!--- Using cfmodule with relative path --->
<cfmodule template="../customtags/formatPrice.cfm"
  amount="29.99"
  currency="USD">

<!--- Using cfmodule with name (searches custom tag paths) --->
<cfmodule name="formatPrice"
  amount="29.99"
  currency="USD">

<!--- cfmodule with body --->
<cfmodule template="panel.cfm" title="Settings">
  <p>Panel content</p>
</cfmodule>
<!--- Import custom tag with prefix --->
<cfimport prefix="ui" taglib="/customtags/ui">

<!--- Use imported tag with prefix --->
<ui:panel title="Dashboard" type="primary">
  <p>Dashboard content</p>
</ui:panel>

<ui:formatPrice amount="99.99" currency="EUR">

Best Practices

Organization & Structure

Best Practices:
  • Logical Grouping: Organize tags into subdirectories by functionality (ui, formatting, data)
  • Naming Conventions: Use descriptive names that indicate purpose (formatCurrency.cfm, not fmt.cfm)
  • Documentation: Include usage examples and parameter descriptions in tag comments
  • Versioning: Keep custom tag libraries under version control
  • Testing: Create test harnesses for custom tags

Performance Optimization

Tips:
  • Path Order: Place frequently used paths first in the search order
  • Minimize Paths: Fewer configured paths means faster tag resolution
  • Trusted Cache: Enable trusted cache in production to avoid repeated file checks
  • Avoid Deep Nesting: Don't call custom tags from within custom tags excessively
  • Cache Output: Cache custom tag output when content doesn't change frequently

Security Considerations

Security:
  • Validate Attributes: Always use <cfparam> to validate required attributes
  • Escape Output: Use encodeForHTML() for user-supplied content
  • File Permissions: Restrict write access to custom tag directories
  • Sandbox Consideration: Custom tags respect ColdFusion sandbox security
  • Input Validation: Validate and sanitize all attribute values

Development Guidelines

Code Quality:
  • Single Responsibility: Each tag should do one thing well
  • Reusability: Design tags to be generic and reusable
  • Error Handling: Use <cftry> to handle errors gracefully
  • Scope Management: Use var scope for local variables
  • Documentation: Document attributes, return values, and usage examples

Common Issues & Solutions

Custom Tag Not Found

Symptom: Error "Could not find the ColdFusion component or interface" when invoking tag
Solutions:
  • Verify tag filename matches invocation name (case-sensitive on Linux)
  • Check that custom tag path is configured correctly in Administrator
  • Ensure file has .cfm extension
  • Verify file permissions allow ColdFusion to read the file
  • Check that path doesn't contain typos
  • Try using <cfmodule> with absolute path to verify tag works

Wrong Tag Version Executing

Symptom: Old version of custom tag executes after updating file
Solutions:
  • Clear template cache (Administrator → Caching → Clear Template Cache)
  • If trusted cache is enabled, restart ColdFusion
  • Check for duplicate tag files in other custom tag paths
  • Verify you updated the correct file (check search order)
  • Add <!--- Updated: #now()# ---> to verify correct file loads

Attribute Errors

Symptom: Errors about missing or invalid attributes
Solutions:
  • Use <cfparam> to define required attributes with proper types
  • Provide default values for optional attributes
  • Document required vs optional attributes clearly
  • Check attribute name spelling (case-insensitive but must match)
  • Validate attribute data types match expectations

Execution Mode Issues

Symptom: Tag body not processing correctly or duplicate output
Solutions:
  • Check thisTag.executionMode to handle start/end properly
  • Use <cfexit method="exittag"> for self-closing behavior
  • Verify logic handles both start and end modes appropriately
  • Test with both self-closing and body content invocations
  • Access body content via thisTag.generatedContent

Related Resources