Skip to content

Store WebSocket Connection

Establishes a real-time WebSocket connection for store chat functionality.

WebSocket URL

ws://localhost:8000/v1/chat/ws/store/?token=<auth_token>
wss://api.luxmart.site/v1/chat/ws/store/?token=<auth_token>

Authentication

Pass the store's authentication token as a query parameter:

?token=<store_auth_token>

Connection Lifecycle

1. Connect

const token = "your_store_token_here";
const ws = new WebSocket(`ws://localhost:8000/v1/chat/ws/store/?token=${encodeURIComponent(token)}`);

2. Connection Events

On Open:

ws.onopen = () => {
  console.log("Connected to chat");
};

On Message:

ws.onmessage = (event) => {
  const payload = JSON.parse(event.data);
  // Handle different event types
};

On Close:

ws.onclose = () => {
  console.log("Disconnected from chat");
  // Implement reconnection logic
};

On Error:

ws.onerror = (error) => {
  console.error("WebSocket error:", error);
};

Event Types

1. Receiving Messages

Event Type: message

Payload:

{
  "type": "message",
  "payload": {
    "message": {
      "id": 123,
      "session_id": 1,
      "sender_type": "admin",
      "content": "Hello! How can I help you?",
      "is_read": false,
      "created_at": "2025-12-16T10:20:00Z"
    }
  }
}

Example Handler:

if (payload.type === "message") {
  const message = payload.payload.message;
  if (message.sender_type === "admin") {
    // Display admin message in chat
    displayMessage(message);
  }
}

2. Admin Connection Status

Event Type: admin_connected

Sent when an admin claims the session.

Payload:

{
  "type": "admin_connected",
  "payload": {
    "admin_id": 2,
    "message": "An admin has joined the chat"
  }
}

3. Typing Indicator

Event Type: typing

Indicates when the admin is typing.

Payload:

{
  "type": "typing",
  "payload": {
    "is_typing": true,
    "sender_type": "admin"
  }
}

Example Handler:

if (payload.type === "typing") {
  if (payload.payload.sender_type === "admin") {
    showTypingIndicator(payload.payload.is_typing);
  }
}

4. Error Messages

Event Type: error

Payload:

{
  "type": "error",
  "payload": {
    "message": "Failed to send message",
    "code": "SEND_FAILED"
  }
}

Sending Messages

1. Send Text Message

Send via WebSocket:

ws.send(JSON.stringify({
  type: "message",
  payload: {
    content: "Hello, I need help with my order"
  }
}));

Response: You'll receive the message back with full details including id and created_at.

2. Send Typing Indicator

// User started typing
ws.send(JSON.stringify({
  type: "typing",
  payload: {
    is_typing: true
  }
}));

// User stopped typing (after a delay)
setTimeout(() => {
  ws.send(JSON.stringify({
    type: "typing",
    payload: {
      is_typing: false
    }
  }));
}, 3000);

Complete Example

class StoreChat {
  constructor(token, sessionId) {
    this.token = token;
    this.sessionId = sessionId;
    this.ws = null;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 5;
  }

  connect() {
    const wsUrl = `ws://localhost:8000/v1/chat/ws/store/?token=${encodeURIComponent(this.token)}`;
    this.ws = new WebSocket(wsUrl);

    this.ws.onopen = () => {
      console.log("Chat connected");
      this.reconnectAttempts = 0;
    };

    this.ws.onmessage = (event) => {
      const payload = JSON.parse(event.data);
      this.handleEvent(payload);
    };

    this.ws.onclose = () => {
      console.log("Chat disconnected");
      this.reconnect();
    };

    this.ws.onerror = (error) => {
      console.error("WebSocket error:", error);
    };
  }

  handleEvent(payload) {
    switch (payload.type) {
      case "message":
        if (payload.payload?.message) {
          const msg = payload.payload.message;
          if (msg.sender_type === "admin") {
            this.displayMessage(msg);
          }
        }
        break;

      case "admin_connected":
        this.showAdminConnected();
        break;

      case "typing":
        if (payload.payload?.sender_type === "admin") {
          this.showTypingIndicator(payload.payload.is_typing);
        }
        break;

      case "error":
        console.error("Chat error:", payload.payload?.message);
        break;
    }
  }

  sendMessage(content) {
    if (this.ws?.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify({
        type: "message",
        payload: { content }
      }));
    }
  }

  sendTyping(isTyping) {
    if (this.ws?.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify({
        type: "typing",
        payload: { is_typing: isTyping }
      }));
    }
  }

  reconnect() {
    if (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++;
      const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
      console.log(`Reconnecting in ${delay}ms...`);
      setTimeout(() => this.connect(), delay);
    }
  }

  disconnect() {
    if (this.ws) {
      this.ws.close();
    }
  }

  displayMessage(message) {
    // Implement your UI logic here
    console.log(`${message.sender_type}: ${message.content}`);
  }

  showAdminConnected() {
    // Show UI notification that admin joined
    console.log("Admin has joined the chat");
  }

  showTypingIndicator(isTyping) {
    // Show/hide typing indicator
    console.log(`Admin is ${isTyping ? "typing..." : "not typing"}`);
  }
}

// Usage
const chat = new StoreChat(authToken, sessionId);
chat.connect();

Error Handling

Authentication Errors

If the token is invalid or expired, the WebSocket connection will be rejected with a 401 status.

Session Errors

If the store doesn't have an active session, create one first using the REST endpoint:

GET /v1/chat/store/session/
Authorization: Token <store_token>

Connection Errors

Implement exponential backoff for reconnection attempts:

let reconnectDelay = 1000;
const maxDelay = 30000;

function reconnect() {
  setTimeout(() => {
    connect();
    reconnectDelay = Math.min(reconnectDelay * 2, maxDelay);
  }, reconnectDelay);
}

Best Practices

  1. Always URL-encode the token when passing it as a query parameter
  2. Implement auto-reconnection with exponential backoff
  3. Handle connection state before sending messages
  4. Send typing indicators with debouncing (e.g., after 3 seconds of no typing)
  5. Display connection status to the user (connected/disconnected)
  6. Buffer messages during disconnection and send when reconnected
  7. Auto-scroll to the latest message when new messages arrive