diff --git a/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp b/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp
index b20d6f504644b67f49836b8a5c35b78265510b32..76f82431e1b61e588cca8a341ea3736102975d54 100644
--- a/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp
+++ b/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp
@@ -105,8 +105,12 @@ namespace armarx::viz
         selection = new SoSelection;
         selection->addSelectionCallback(&selectionCallback, this);
         selection->addDeselectionCallback(&deselectionCallback, this);
+        selection->setUserData(this);
 
         selection->addChild(root);
+
+        // Preallocate some space for layers
+        layers.data.reserve(32);
     }
 
     CoinVisualizer::~CoinVisualizer()
@@ -144,24 +148,6 @@ namespace armarx::viz
         state = CoinVisualizerState::STOPPED;
     }
 
-    static void removeElementsIfNotUpdated(CoinLayer* layer)
-    {
-        for (auto iter = layer->elements.begin(); iter != layer->elements.end();)
-        {
-            coin::ElementVisualization& elementVisu = *iter->visu;
-            if (elementVisu.wasUpdated)
-            {
-                elementVisu.wasUpdated = false;
-                ++iter;
-            }
-            else
-            {
-                layer->node->removeChild(elementVisu.separator);
-                iter = layer->elements.erase(iter);
-            }
-        }
-    }
-
     CoinVisualizer_ApplyTiming CoinVisualizer::apply(data::LayerUpdate const& update)
     {
         IceUtil::Time time_start = IceUtil::Time::now();
@@ -205,6 +191,7 @@ namespace armarx::viz
             root->addChild(coinNode);
 
             layerIt = layers.data.insert(layerIt, CoinLayer(layerID, coinNode));
+            layerIt->elements.reserve(64);
         }
 
         return *layerIt;
@@ -256,6 +243,37 @@ namespace armarx::viz
 
                 if (updated)
                 {
+                    // Has an interaction been added?
+                    viz::data::InteractionDescription& oldInteraction = oldElement->data->interaction;
+                    viz::data::InteractionDescription& newInteraction = updatedElementPtr->interaction;
+                    if (newInteraction.enableFlags != oldInteraction.enableFlags
+                            || oldInteraction.contextMenuOptions != newInteraction.contextMenuOptions)
+                    {
+                        // Lookup the interaction entry
+                        ElementInteractionData* foundInteraction = nullptr;
+                        for (auto& interaction : elementInteractions)
+                        {
+                            if (interaction->layer == layer->id
+                                    && interaction->element == updatedElement.id)
+                            {
+                                foundInteraction = interaction.get();
+                            }
+                        }
+                        if (foundInteraction == nullptr)
+                        {
+                            // Need to add a new entry
+                            foundInteraction = elementInteractions.emplace_back(
+                                                   new ElementInteractionData).get();
+                        }
+                        foundInteraction->layer = layer->id;
+                        foundInteraction->element = updatedElement.id;
+                        foundInteraction->interaction = newInteraction;
+
+                        // Add user data to Coin node
+                        oldElement->visu->separator->setUserData(foundInteraction);
+                        oldElement->visu->separator->setName("InteractiveNode");
+                    }
+
                     oldElement->data = updatedElementPtr;
                     continue;
                 }
@@ -269,6 +287,35 @@ namespace armarx::viz
             auto elementVisu = visualizer->create(updatedElement);
             if (elementVisu->separator)
             {
+                // Has the new element interactions?
+                viz::data::InteractionDescription& newInteraction = updatedElementPtr->interaction;
+                if (newInteraction.enableFlags != 0)
+                {
+                    // Lookup the interaction entry
+                    ElementInteractionData* foundInteraction = nullptr;
+                    for (auto& interaction : elementInteractions)
+                    {
+                        if (interaction->layer == layer->id
+                                && interaction->element == updatedElement.id)
+                        {
+                            foundInteraction = interaction.get();
+                        }
+                    }
+                    if (foundInteraction == nullptr)
+                    {
+                        // Need to add a new entry
+                        foundInteraction = elementInteractions.emplace_back(
+                                               new ElementInteractionData).get();
+                    }
+                    foundInteraction->layer = layer->id;
+                    foundInteraction->element = updatedElement.id;
+                    foundInteraction->interaction = newInteraction;
+
+                    // Add user data to Coin node
+                    elementVisu->separator->setUserData(foundInteraction);
+                    elementVisu->separator->setName("InteractiveNode");
+                }
+
                 layer->node->addChild(elementVisu->separator);
                 if (oldElement)
                 {
@@ -291,6 +338,35 @@ namespace armarx::viz
         }
     }
 
+    void CoinVisualizer::removeElementsIfNotUpdated(CoinLayer* layer)
+    {
+        for (auto iter = layer->elements.begin(); iter != layer->elements.end();)
+        {
+            coin::ElementVisualization& elementVisu = *iter->visu;
+            if (elementVisu.wasUpdated)
+            {
+                elementVisu.wasUpdated = false;
+                ++iter;
+            }
+            else
+            {
+                void* userData = elementVisu.separator->getUserData();
+                if (userData)
+                {
+                    // Remove interaction entry if element has been removed
+                    auto removedInteraction = std::find_if(elementInteractions.begin(), elementInteractions.end(),
+                                                           [userData](std::unique_ptr<ElementInteractionData> const& entry)
+                    {
+                        return entry.get() == userData;
+                    });
+                    elementInteractions.erase(removedInteraction);
+                }
+                layer->node->removeChild(elementVisu.separator);
+                iter = layer->elements.erase(iter);
+            }
+        }
+    }
+
     void CoinVisualizer::update()
     {
         {
@@ -473,11 +549,24 @@ namespace armarx::viz
 
     void CoinVisualizer::onSelection(SoPath* path)
     {
-        SoNode* tailNode = path->getTail();
+        // Search for user data in the path
+        // We stored ElementInteractionData into the user data of the parent SoSeparator
+        void* userData = nullptr;
+        int pathLength = path->getLength();
+        for (int i = 0; i < pathLength; ++i)
+        {
+            SoNode* node = path->getNode(i);
+            const char* name = node->getName().getString();
+            if (strcmp(name, "InteractiveNode") == 0)
+            {
+                userData = node->getUserData();
+                if (userData != nullptr)
+                {
+                    break;
+                }
+            }
+        }
 
-        // TODO: Store CoinElementID into user data if interaction is enabled!
-        // Search for user data
-        void* userData = tailNode->getUserData();
         if (userData == nullptr)
         {
             // In this case, we want to deselect all objects in the scene,
@@ -485,10 +574,10 @@ namespace armarx::viz
             selection->deselectAll();
 
             // TODO: Remove logging, this is not an error, but expected
-            ARMARX_INFO << "Selected: " << tailNode->getClassTypeId().getName().getString()
-                        << "\nBut no user data attached!";
+            ARMARX_INFO << "Selected something. But no user data attached!";
+            return;
         }
-        CoinElementID* id = static_cast<CoinElementID*>(userData);
+        ElementInteractionData* id = static_cast<ElementInteractionData*>(userData);
 
         CoinLayer* layer = layers.findLayer(id->layer);
         if (layer == nullptr)
diff --git a/source/RobotAPI/components/ArViz/Coin/Visualizer.h b/source/RobotAPI/components/ArViz/Coin/Visualizer.h
index 6ae911753b17d72059a7e809fd770339dc9c1360..cbb5dca4eba853422fe20bf9a3c5b7bd3d92036e 100644
--- a/source/RobotAPI/components/ArViz/Coin/Visualizer.h
+++ b/source/RobotAPI/components/ArViz/Coin/Visualizer.h
@@ -186,10 +186,11 @@ namespace armarx::viz
 
     struct CoinVisualizerWrapper;
 
-    struct CoinElementID
+    struct ElementInteractionData
     {
         CoinLayerID layer;
         std::string element;
+        viz::data::InteractionDescription interaction;
     };
 
     class CoinVisualizer
@@ -229,6 +230,7 @@ namespace armarx::viz
 
         CoinLayer& findOrAddLayer(CoinLayerID const& layerID);
         void addOrUpdateElements(CoinLayer* layer, data::LayerUpdate const& update);
+        void removeElementsIfNotUpdated(CoinLayer* layer);
 
         std::vector<CoinLayerID> getLayerIDs();
         void emitLayersChanged(std::vector<CoinLayerID> const& layerIDs);
@@ -239,7 +241,7 @@ namespace armarx::viz
         // These are selectable element IDs and need to be persistent in memory.
         // We store a raw pointer to these into the SoSeperator objects of Coin.
         // Later, we can retrieve the element ID from this pointer, if it has been selected.
-        std::vector<std::unique_ptr<CoinElementID>> selectableElementIDs;
+        std::vector<std::unique_ptr<ElementInteractionData>> elementInteractions;
 
         void onUpdateSuccess(data::LayerUpdates const& updates);
         void onUpdateFailure(Ice::Exception const& ex);