UJG / Editor's Draft /
GitHub
Table of Contents
  • 1Overview
  • 2Terminology
  • 3PainPoint
  • 4Normative Artifacts
    • 4.1Ontology
    • 4.2JSON-LD Context
    • 4.3Validation
  • 5Examples
    • 5.1Combined Example
W3C Community Group Draft Report

Experience Annotation

draft

Status of this Document

This report was published by the User Journal Graph Community Group . It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups .

Last Update
2026-07-15
Editors
  • Seva Dolgopolov
Group
User Journal Graph Community Group
Repository
View Source
License
W3C-Software-and-Document

1. Overview

This optional module defines qualitative annotations over the intended experience. Its first standardized annotation is a PainPoint. Experience Annotation does not add Graph traversal, Runtime ordering, or Mapping behavior.

Documents using this module compose the Phase context with https://ujg.specs.openuji.org/ed/ns/experience-annotation.context.jsonld.

2. Terminology

PainPoint is a qualitative UX issue experienced by a user.

3. PainPoint

A PainPoint is a named issue or friction hypothesis attached to one or more Phase Steps.

  1. A PainPoint MUST be identified by an IRI.

  2. A PainPoint MUST declare one or more painpointStepRefs values.

  3. Every painpointStepRefs value MUST resolve to a Step.

  4. A PainPoint MAY declare at most one severity in the inclusive range 0 through 1.

  5. A PainPoint MAY declare at most one description.

  6. A PainPoint MUST NOT change Graph traversal or assert Runtime occurrence.

classDiagram
  class Step
  class PainPoint {
    id
    painpointStepRefs
    severity
    description
  }
  PainPoint --> "1..*" Step : painpointStepRefs

Example JSON node:

json
{
  "@type": "PainPoint",
  "@id": "urn:ujg:pain:address-validation",
  "painpointStepRefs": ["urn:ujg:step:shipping"],
  "severity": 0.7,
  "description": "Address correction interrupts checkout."
}
{
  "@type": "PainPoint",
  "@id": "urn:ujg:pain:address-validation",
  "painpointStepRefs": ["urn:ujg:step:shipping"],
  "severity": 0.7,
  "description": "Address correction interrupts checkout."
}

4. Normative Artifacts

4.1. Ontology

turtle
@prefix ujg: <https://ujg.specs.openuji.org/ed/ns/core#> .
@prefix ujgphase: <https://ujg.specs.openuji.org/ed/ns/phase#> .
@prefix ujgexperienceannotation: <https://ujg.specs.openuji.org/ed/ns/experience-annotation#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix dct: <http://purl.org/dc/terms/> .

<https://ujg.specs.openuji.org/ed/ns/experience-annotation#> a owl:Ontology ;
  rdfs:label "UJG Experience Annotation Editor's Draft Vocabulary"@en ;
  dct:description "UJG Experience Annotation ontology declaration" .

ujgexperienceannotation:PainPoint a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgexperienceannotation:painpointStepRefs a owl:ObjectProperty ;
  rdfs:domain ujgexperienceannotation:PainPoint ;
  rdfs:range ujgphase:Step .

ujgexperienceannotation:severity a owl:DatatypeProperty ;
  rdfs:domain ujgexperienceannotation:PainPoint ;
  rdfs:range xsd:decimal .

ujgexperienceannotation:description a owl:DatatypeProperty ;
  rdfs:domain ujgexperienceannotation:PainPoint ;
  rdfs:range xsd:string .
@prefix ujg: <https://ujg.specs.openuji.org/ed/ns/core#> .
@prefix ujgphase: <https://ujg.specs.openuji.org/ed/ns/phase#> .
@prefix ujgexperienceannotation: <https://ujg.specs.openuji.org/ed/ns/experience-annotation#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix dct: <http://purl.org/dc/terms/> .

<https://ujg.specs.openuji.org/ed/ns/experience-annotation#> a owl:Ontology ;
  rdfs:label "UJG Experience Annotation Editor's Draft Vocabulary"@en ;
  dct:description "UJG Experience Annotation ontology declaration" .

ujgexperienceannotation:PainPoint a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgexperienceannotation:painpointStepRefs a owl:ObjectProperty ;
  rdfs:domain ujgexperienceannotation:PainPoint ;
  rdfs:range ujgphase:Step .

ujgexperienceannotation:severity a owl:DatatypeProperty ;
  rdfs:domain ujgexperienceannotation:PainPoint ;
  rdfs:range xsd:decimal .

ujgexperienceannotation:description a owl:DatatypeProperty ;
  rdfs:domain ujgexperienceannotation:PainPoint ;
  rdfs:range xsd:string .

4.2. JSON-LD Context

json-ld
{
  "@context": {
    "@version": 1.1,
    "ujgexperienceannotation": "https://ujg.specs.openuji.org/ed/ns/experience-annotation#",
    "xsd": "http://www.w3.org/2001/XMLSchema#",
    "PainPoint": "ujgexperienceannotation:PainPoint",
    "painpointStepRefs": {
      "@id": "ujgexperienceannotation:painpointStepRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "severity": {
      "@id": "ujgexperienceannotation:severity",
      "@type": "xsd:decimal"
    },
    "description": "ujgexperienceannotation:description"
  }
}
{
  "@context": {
    "@version": 1.1,
    "ujgexperienceannotation": "https://ujg.specs.openuji.org/ed/ns/experience-annotation#",
    "xsd": "http://www.w3.org/2001/XMLSchema#",
    "PainPoint": "ujgexperienceannotation:PainPoint",
    "painpointStepRefs": {
      "@id": "ujgexperienceannotation:painpointStepRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "severity": {
      "@id": "ujgexperienceannotation:severity",
      "@type": "xsd:decimal"
    },
    "description": "ujgexperienceannotation:description"
  }
}

4.3. Validation

turtle
@prefix ujgexperienceannotation: <https://ujg.specs.openuji.org/ed/ns/experience-annotation#> .
@prefix ujgphase: <https://ujg.specs.openuji.org/ed/ns/phase#> .
@prefix ujgexperienceannotationshape: <https://ujg.specs.openuji.org/ed/ns/experience-annotation.shape#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

ujgexperienceannotationshape:PainPointShape a sh:NodeShape ;
  sh:targetClass ujgexperienceannotation:PainPoint ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgexperienceannotation:painpointStepRefs ;
    sh:class ujgphase:Step ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
  ] ;

  sh:property [
    sh:path ujgexperienceannotation:severity ;
    sh:datatype xsd:decimal ;
    sh:minInclusive 0 ;
    sh:maxInclusive 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgexperienceannotation:description ;
    sh:datatype xsd:string ;
    sh:maxCount 1 ;
  ] .
@prefix ujgexperienceannotation: <https://ujg.specs.openuji.org/ed/ns/experience-annotation#> .
@prefix ujgphase: <https://ujg.specs.openuji.org/ed/ns/phase#> .
@prefix ujgexperienceannotationshape: <https://ujg.specs.openuji.org/ed/ns/experience-annotation.shape#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

ujgexperienceannotationshape:PainPointShape a sh:NodeShape ;
  sh:targetClass ujgexperienceannotation:PainPoint ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgexperienceannotation:painpointStepRefs ;
    sh:class ujgphase:Step ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
  ] ;

  sh:property [
    sh:path ujgexperienceannotation:severity ;
    sh:datatype xsd:decimal ;
    sh:minInclusive 0 ;
    sh:maxInclusive 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgexperienceannotation:description ;
    sh:datatype xsd:string ;
    sh:maxCount 1 ;
  ] .

5. Examples

5.1. Combined Example

json
{
  "@context": [
    "https://ujg.specs.openuji.org/ed/ns/context.jsonld",
    "https://ujg.specs.openuji.org/ed/ns/phase.context.jsonld",
    "https://ujg.specs.openuji.org/ed/ns/experience-annotation.context.jsonld"
  ],
  "@id": "https://example.com/ujg/experience-annotation/checkout.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@type": "CompositeState",
      "@id": "urn:ujg:state:shipping-segment",
      "label": "Shipping segment",
      "subjourneyId": "urn:ujg:journey:shipping-segment"
    },
    {
      "@type": "Journey",
      "@id": "urn:ujg:journey:shipping-segment",
      "defaultEntryRef": "urn:ujg:entry:shipping-default",
      "entryRefs": ["urn:ujg:entry:shipping-default"],
      "stateRefs": ["urn:ujg:state:shipping-form"]
    },
    {
      "@type": "JourneyEntry",
      "@id": "urn:ujg:entry:shipping-default",
      "stateRef": "urn:ujg:state:shipping-form"
    },
    {
      "@type": "State",
      "@id": "urn:ujg:state:shipping-form",
      "label": "Shipping form"
    },
    {
      "@type": "Step",
      "@id": "urn:ujg:step:shipping",
      "compositeStateRef": "urn:ujg:state:shipping-segment"
    },
    {
      "@type": "PainPoint",
      "@id": "urn:ujg:pain:address-validation",
      "painpointStepRefs": ["urn:ujg:step:shipping"],
      "severity": 0.7,
      "description": "Address correction interrupts checkout."
    }
  ]
}
{
  "@context": [
    "https://ujg.specs.openuji.org/ed/ns/context.jsonld",
    "https://ujg.specs.openuji.org/ed/ns/phase.context.jsonld",
    "https://ujg.specs.openuji.org/ed/ns/experience-annotation.context.jsonld"
  ],
  "@id": "https://example.com/ujg/experience-annotation/checkout.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@type": "CompositeState",
      "@id": "urn:ujg:state:shipping-segment",
      "label": "Shipping segment",
      "subjourneyId": "urn:ujg:journey:shipping-segment"
    },
    {
      "@type": "Journey",
      "@id": "urn:ujg:journey:shipping-segment",
      "defaultEntryRef": "urn:ujg:entry:shipping-default",
      "entryRefs": ["urn:ujg:entry:shipping-default"],
      "stateRefs": ["urn:ujg:state:shipping-form"]
    },
    {
      "@type": "JourneyEntry",
      "@id": "urn:ujg:entry:shipping-default",
      "stateRef": "urn:ujg:state:shipping-form"
    },
    {
      "@type": "State",
      "@id": "urn:ujg:state:shipping-form",
      "label": "Shipping form"
    },
    {
      "@type": "Step",
      "@id": "urn:ujg:step:shipping",
      "compositeStateRef": "urn:ujg:state:shipping-segment"
    },
    {
      "@type": "PainPoint",
      "@id": "urn:ujg:pain:address-validation",
      "painpointStepRefs": ["urn:ujg:step:shipping"],
      "severity": 0.7,
      "description": "Address correction interrupts checkout."
    }
  ]
}

Copyright © 2026 the Contributors to the ujg/modules/experience-annotation, published by the User Journal Graph Community Group under the W3C Community Contributor License Agreement (CLA) . A human-readable summary is available.

generated by Speculator