Embedding Custom Metadata and Tags in glTF
Embedding custom user metadata and engine-specific tags natively into
glTF (GL Transmission Format) allows developers to carry custom logic,
gameplay parameters, and pipeline instructions alongside 3D assets
without altering core geometry or rendering data. This is achieved
primarily through the native extras property supported
across virtually all glTF objects, as well as through custom vendor
extensions for more structured implementations. This guide explains how
to define, structure, and extract this custom data efficiently within
standard glTF files.
The Native extras
Property
The primary mechanism for embedding arbitrary user metadata in glTF
2.0 is the extras field. According to the glTF
specification, almost every core object—including scenes, nodes, meshes,
materials, animations, and the root document—can contain an
extras object.
The extras field can store any valid JSON data type,
such as strings, numbers, booleans, arrays, or nested objects.
{
"nodes": [
{
"name": "InteractableDoor",
"mesh": 0,
"extras": {
"tag": "Interactable",
"soundEffect": "door_creak_01.wav",
"locked": true,
"requiredKeyId": 402,
"interactionDistance": 2.5
}
}
]
}Because extras is part of the core glTF schema, standard
loaders will parse the file without throwing validation errors.
Namespacing for Engine-Specific Tags
When targeting multiple runtime engines (e.g., Unity, Unreal Engine,
Godot) or distinct internal tools, structure the extras
field using namespaces. This prevents key collisions and keeps
engine-specific workflows isolated.
{
"extras": {
"engine_unity": {
"layer": "Obstacle",
"static": true,
"navMeshArea": 0
},
"engine_unreal": {
"collisionProfile": "BlockAll",
"mobility": "Static"
},
"gameplay": {
"destructible": false
}
}
}Formal Extensions vs.
extras
While extras is meant for custom application data,
standardizing complex metadata across teams or public tools is better
handled via glTF extensions using the extensions field.
- Use
extraswhen: Data is only consumed by your internal pipeline, does not alter the fundamental rendering behavior, and does not require schema validation. - Use
extensionswhen: You need formal JSON schema validation, fallback behavior, or cross-pipeline interoperability (such as prefixing with a vendor tag likeVENDOR_component_name).
Parsing and Reading Metadata at Runtime
Most modern glTF loaders automatically read the extras
dictionary and bind it to the generated runtime object:
- Three.js: Exposes metadata via the
userDataproperty on the generatedObject3DorMaterial(e.g.,mesh.userData.tag). - Babylon.js: Exposes metadata through
metadataon the abstract mesh or node (e.g.,node.metadata.gltf.extras). - Custom Parsers: Read the JSON property
nodes[i].extrasdirectly during scene graph construction.
Best Practices
- Keep JSON Payloads Light: The glTF JSON chunk must
be parsed quickly. Do not store large datasets (like embedded base64
images or dense point clouds) in
extras. Heavy binary data belongs in dedicated.binbuffer views. - Avoid Type Inconsistencies: If an export pipeline generates a metadata field, ensure its type remains consistent across all exported assets (e.g., avoid writing an ID as a string in one export and an integer in another).
- Strip Sensitive Data: Remove internal paths, author
credentials, or proprietary tool paths from
extrasprior to publishing assets to public client builds.