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
attributesscope - Return values through
callerscope - Execution modes: start, end, inactive
Custom Tags vs CFCs
Custom TagsBest for: UI output, HTML generation, legacy code
Invocation:
Organization: Flat file structure
Invocation:
<cf_tag> syntaxOrganization: Flat file structure
CFCsBest for: Business logic, data access, APIs, services
Invocation: Object methods, component functions
Organization: Object-oriented with methods and properties
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 Example
D:\shared\customtagsLinux Example
/var/www/shared/customtagsSearch 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}/CustomTagsPurposeBuilt-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
varscope 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.executionModeto 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