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 extras when: Data is only consumed by your internal pipeline, does not alter the fundamental rendering behavior, and does not require schema validation.
  • Use extensions when: You need formal JSON schema validation, fallback behavior, or cross-pipeline interoperability (such as prefixing with a vendor tag like VENDOR_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 userData property on the generated Object3D or Material (e.g., mesh.userData.tag).
  • Babylon.js: Exposes metadata through metadata on the abstract mesh or node (e.g., node.metadata.gltf.extras).
  • Custom Parsers: Read the JSON property nodes[i].extras directly during scene graph construction.

Best Practices

  1. 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 .bin buffer views.
  2. 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).
  3. Strip Sensitive Data: Remove internal paths, author credentials, or proprietary tool paths from extras prior to publishing assets to public client builds.