diff --git a/bin/nodejs/callback.h b/bin/nodejs/callback.h
index 5feaf731fde8b2b7f6233af8276b0a1890dd22a1..749d887c70f7764a9960c3bc8c55c34f9d352efc 100644
--- a/bin/nodejs/callback.h
+++ b/bin/nodejs/callback.h
@@ -43,6 +43,7 @@ Persistent<Function> conferenceChangedCb;
 Persistent<Function> conferenceRemovedCb;
 Persistent<Function> onConferenceInfosUpdatedCb;
 Persistent<Function> conversationPreferencesUpdatedCb;
+Persistent<Function> messageSendCb;
 
 std::queue<std::function<void()>> pendingSignals;
 std::mutex pendingSignalsLock;
@@ -120,6 +121,8 @@ getPresistentCb(std::string_view signal)
         return &onConferenceInfosUpdatedCb;
     else if (signal == "ConversationPreferencesUpdated")
         return &conversationPreferencesUpdatedCb;
+    else if (signal == "LogMessage")
+        return &messageSendCb;
     else
         return nullptr;
 }
@@ -843,3 +846,18 @@ conversationPreferencesUpdated(const std::string& accountId,
     });
     uv_async_send(&signalAsync);
 }
+
+void
+logMessage(const std::string& message)
+{
+    std::lock_guard<std::mutex> lock(pendingSignalsLock);
+    pendingSignals.emplace([message]() {
+        Local<Function> func = Local<Function>::New(Isolate::GetCurrent(),
+                                                    messageSendCb);
+        if (!func.IsEmpty()) {
+            SWIGV8_VALUE callback_args[] = {V8_STRING_NEW_LOCAL(message)};
+            func->Call(SWIGV8_CURRENT_CONTEXT(), SWIGV8_NULL(), 1, callback_args);
+        }
+    });
+    uv_async_send(&signalAsync);
+}
diff --git a/bin/nodejs/configurationmanager.i b/bin/nodejs/configurationmanager.i
index 2b8656fb86ceac0d487ea1ff1a015b34ad2c7e91..94b9f3ce5238913adfcb2a98e8f29da94e39aefe 100644
--- a/bin/nodejs/configurationmanager.i
+++ b/bin/nodejs/configurationmanager.i
@@ -62,6 +62,7 @@ public:
     virtual void hardwareEncodingChanged(bool /*state*/){}
 
     virtual void audioMeter(const std::string& /*id*/, float /*level*/){}
+    virtual void messageSend(const std::string& /*message*/){}
 };
 %}
 
@@ -260,5 +261,5 @@ public:
     virtual void hardwareEncodingChanged(bool /*state*/){}
 
     virtual void audioMeter(const std::string& /*id*/, float /*level*/){}
-    //virtual void messageSend(const std::string& /*message*/){}
+    virtual void messageSend(const std::string& /*message*/){}
 };
diff --git a/bin/nodejs/nodejs_interface.i b/bin/nodejs/nodejs_interface.i
index fb4a2c9a030e535e396e9773edbaa230db878a18..bacb5dddb7cc805402541fb567a7abd88fef3f9f 100644
--- a/bin/nodejs/nodejs_interface.i
+++ b/bin/nodejs/nodejs_interface.i
@@ -141,6 +141,7 @@ void init(const SWIGV8_VALUE& funcMap){
         exportable_callback<ConfigurationSignal::KnownDevicesChanged>(bind(&knownDevicesChanged, _1, _2 )),
         exportable_callback<ConfigurationSignal::IncomingAccountMessage>(bind(&incomingAccountMessage, _1, _2, _3, _4 )),
         exportable_callback<ConfigurationSignal::AccountMessageStatusChanged>(bind(&accountMessageStatusChanged, _1, _2, _3, _4, _5 )),
+        exportable_callback<ConfigurationSignal::MessageSend>(bind(&logMessage, _1 )),
         //exportable_callback<ConfigurationSignal::ProfileReceived>(bind(&profileReceived, _1, _2, _3, _4 )),
         //exportable_callback<ConfigurationSignal::IncomingTrustRequest>(bind(&incomingTrustRequest, _1, _2, _3, _4, _5 )),
     };