---
title: "CDN / แท็กสคริปต์"
description: "เพิ่มวิดเจ็ตเสียง ThunderPhone ลงในเว็บไซต์ใดก็ได้โดยไม่ต้องใช้บันเดิลเลอร์"
---

บิลด์ CDN รวม React ไว้ภายใน ดังนั้นคุณจึงใช้วิดเจ็ตบนเว็บไซต์แบบสแตติก WordPress Webflow หรือหน้าใดก็ได้ที่คุณเพิ่ม HTML ได้ ไม่ต้องใช้ npm ไม่ต้องใช้ bundler และไม่ต้องใช้เฟรมเวิร์ก

## URL ของ CDN

<CodeGroup>
```html Latest (recommended)
<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
```

```html Pinned version
<!-- Each stable release also publishes an immutable /widget/vX.Y.Z/ path
     matching the @thunderphone/widget npm version (v1.1.2 at the time of
     writing). If you pin, you own updating the URL for new releases. -->
<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/v1.1.2/style.css" />
<script src="https://cdn.thunderphone.com/widget/v1.1.2/widget.js"></script>
```
</CodeGroup>

<Tip>
  URL `latest` คือ URL ที่ตัวสร้างโค้ดฝังของแดชบอร์ดสร้างขึ้น โดยแคชไว้ 5 นาทีและรับเวอร์ชันเสถียรใหม่โดยอัตโนมัติ พาธ `/widget/vX.Y.Z/` ที่ปักหมุดไว้เปลี่ยนแปลงไม่ได้และแคชระยะยาว -- หากปักหมุด ให้ใช้เวอร์ชันที่ตรงกับรีลีส npm `@thunderphone/widget` ที่คุณพัฒนาด้วย
</Tip>

---

## การใช้งานพื้นฐาน

```html
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
</head>
<body>

  <div id="thunderphone"></div>

  <script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
  <script>
    ThunderPhone.mount({
      element: '#thunderphone',
      publishableKey: 'pk_live_your_publishable_key',
    })
  </script>

</body>
</html>
```

วิดเจ็ตจะเมานต์ลงในองค์ประกอบเป้าหมายและแสดงผลเป็น **แถบตำแหน่งคงที่ที่มุมหนึ่งของวิวพอร์ต** (ค่าเริ่มต้นคือ `bottom-right` ควบคุมด้วยตัวเลือก `position`) องค์ประกอบที่ใช้เมานต์เป็นเพียงราก React -- ตำแหน่งขององค์ประกอบนั้นในหน้าไม่ส่งผลต่อตำแหน่งที่วิดเจ็ตปรากฏ

---

## ตัวเลือกสำหรับการเมานต์

`ThunderPhone.mount()` รับตัวเลือกเดียวกับคอมโพเนนต์ React พร้อมพร็อพเพอร์ตี `element` เพิ่มเติม:

| ตัวเลือก | ประเภท | จำเป็น | ค่าเริ่มต้น | คำอธิบาย |
|--------|------|----------|---------|-------------|
| `element` | `string \| HTMLElement` | ใช่ | -- | CSS selector (เช่น `'#thunderphone'`) หรือการอ้างอิงองค์ประกอบ DOM |
| `publishableKey` | `string` | ใช่ | -- | คีย์ API แบบเผยแพร่ได้ (`pk_live_...`) ระบบจะระบุเอเจนต์โดยอัตโนมัติจากการกำหนดค่าวิดเจ็ตของคีย์ |
| `theme` | `'light' \| 'dark'` | ไม่ | `'light'` | ชุดสี |
| `primaryColor` | `string` | ไม่ | `'#000000'` (สว่าง) / `'#ffffff'` (มืด) | สตริงสี CSS ที่ใช้เป็นสีเน้น |
| `title` | `string` | ไม่ | `'Voice assistant'` | ข้อความที่แสดงในแถบวิดเจ็ต |
| `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | ไม่ | `'bottom-right'` | ตำแหน่งคงที่ในวิวพอร์ต |
| `apiBase` | `string` | ไม่ | `'https://api.thunderphone.com/v1'` | แทนที่ URL ฐานของ API |
| `language` | `string` | ไม่ | -- | แทนที่ภาษาสำหรับแต่ละเซสชัน -- รหัสภาษาหรือโลแคล เช่น `en` `es` หรือ `fr-FR` เมื่อไม่ได้ตั้งค่า จะใช้ภาษาที่กำหนดค่าไว้สำหรับเอเจนต์ |
| `voice` | `string` | ไม่ | -- | แทนที่เสียงสำหรับแต่ละเซสชัน -- ชื่อเสียง เช่น `maria` เมื่อไม่ได้ตั้งค่า จะใช้เสียงที่กำหนดค่าไว้สำหรับเอเจนต์ |
| `context` | `string` | ไม่ | -- | บริบทข้อเท็จจริงของหน้าหรือเว็บไซต์สำหรับแต่ละเซสชันที่ส่งต่อไปยังเอเจนต์ เซิร์ฟเวอร์จะตัดให้เหลือ 12,000 อักขระ |
| `onConnect` | `() => void` | ไม่ | -- | เรียกใช้เมื่อเซสชันเสียงเชื่อมต่อ |
| `onDisconnect` | `() => void` | ไม่ | -- | เรียกใช้เมื่อเซสชันสิ้นสุด |
| `onError` | `(error) => void` | ไม่ | -- | เรียกใช้เมื่อเกิดข้อผิดพลาด Error มีฟิลด์ `error` (รหัส) และ `message` |
| `ringtone` | `boolean \| string` | ไม่ | `false` | เล่นเสียงเรียกเข้าระหว่างเชื่อมต่อ ใช้ `true` สำหรับเสียงเรียกเข้าเริ่มต้น หรือสตริง URL สำหรับเสียงแบบกำหนดเอง |

---

## การล้างทรัพยากร

`ThunderPhone.mount()` จะส่งคืนอินสแตนซ์วิดเจ็ตที่มีเมธอดสำหรับล้างทรัพยากร:

```html
<script>
  var widget = ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
  })

  // Later, when you want to remove the widget:
  widget.unmount()

  // Or equivalently:
  widget.destroy()
</script>
```

ทั้ง `unmount()` และ `destroy()` ทำงานเหมือนกัน โดยจะตัดการเชื่อมต่อเซสชันเสียงที่กำลังใช้งานอยู่และนำวิดเจ็ตออกจาก DOM ใช้เมธอดที่อ่านเข้าใจกว่าในโค้ดของคุณ

<Note>
  ล้างทรัพยากรของวิดเจ็ตเสมอเมื่อออกจากหน้าในแอปพลิเคชันแบบหน้าเดียว หรือเมื่อองค์ประกอบที่บรรจุวิดเจ็ตถูกนำออก วิธีนี้ช่วยให้มั่นใจว่าเซสชันเสียงที่กำลังใช้งานอยู่จะถูกตัดการเชื่อมต่ออย่างถูกต้อง
</Note>

---

## ตัวอย่าง

### ธีมมืดพร้อมสีแบบกำหนดเอง

```html
<div id="thunderphone"></div>

<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
    theme: 'dark',
    primaryColor: '#8b5cf6',
    title: 'Talk to our AI',
  })
</script>
```

### ตำแหน่งแบบกำหนดเอง

```html
<div id="thunderphone"></div>

<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
    position: 'bottom-left',
  })
</script>
```

### พร้อมคอลแบ็กเหตุการณ์

```html
<div id="thunderphone"></div>

<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
    onConnect: function () {
      console.log('Call started')
    },
    onDisconnect: function () {
      console.log('Call ended')
    },
    onError: function (error) {
      console.error('Widget error:', error.error, error.message)
    },
  })
</script>
```

### พร้อมเสียงเรียกเข้า

```html
<div id="thunderphone"></div>

<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
    ringtone: true, // or a custom URL: 'https://example.com/ringtone.mp3'
  })
</script>
```

### การใช้การอ้างอิงองค์ประกอบ DOM

```html
<div id="thunderphone"></div>

<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  var container = document.getElementById('thunderphone')

  ThunderPhone.mount({
    element: container,
    publishableKey: 'pk_live_your_publishable_key',
  })
</script>
```

### การผสานรวม WordPress / CMS

เพิ่มโค้ดนี้ลงในบล็อก HTML แบบกำหนดเอง หรือส่วนท้ายของธีม:

```html
<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>

<div id="thunderphone-widget"></div>
<script>
  ThunderPhone.mount({
    element: '#thunderphone-widget',
    publishableKey: 'pk_live_your_publishable_key',
  })
</script>
```

<Tip>
  `<div>` สามารถวางไว้ที่ใดก็ได้ -- เป็นเพียงจุดเมานต์เท่านั้น วิดเจ็ตจะแสดงผลเป็นโอเวอร์เลย์แบบตรึงในมุมของวิวพอร์ต (กำหนดด้วยตัวเลือก `position`) และจะไม่ไหลไปตามเนื้อหาโดยรอบ
</Tip>

---

## การแก้ไขปัญหา

<AccordionGroup>
  <Accordion title="วิดเจ็ตไม่แสดง">
    ตรวจสอบให้แน่ใจว่าโหลดทั้งไฟล์ CSS และ JS แล้ว ตรวจสอบคอนโซลของเบราว์เซอร์เพื่อดูข้อผิดพลาดของเครือข่าย ยืนยันว่าองค์ประกอบเป้าหมายมีอยู่ใน DOM ก่อนเรียก `ThunderPhone.mount()`
  </Accordion>

  <Accordion title="ไม่ได้กำหนด ThunderPhone">
    สคริปต์ยังไม่ได้โหลด ตรวจสอบให้แน่ใจว่าแท็ก `<script>` สำหรับ `widget.js` อยู่ก่อนคำสั่งเรียกเมานต์ หรือครอบคำสั่งเรียกเมานต์ไว้ในตัวรับฟัง `DOMContentLoaded`
  </Accordion>

  <Accordion title="ข้อผิดพลาด: ไม่อนุญาตโดเมน">
    เพิ่มโดเมนของคุณในรายการโดเมนที่อนุญาตในการตั้งค่า **นักพัฒนา** ที่ [app.thunderphone.com](https://app.thunderphone.com) โปรดทราบว่าอนุญาตให้ใช้ `localhost` เสมอ
  </Accordion>
</AccordionGroup>

---

## ขั้นตอนถัดไป

<CardGroup cols={2}>
  <Card title="การปรับแต่งรูปแบบ" icon="palette" href="/th/widget/styling">
    ปรับแต่งรูปลักษณ์ของวิดเจ็ตด้วยคุณสมบัติแบบกำหนดเองของ CSS
  </Card>
  <Card title="คอมโพเนนต์ React" icon="react" href="/th/widget/react">
    ใช้ React อยู่หรือไม่ การผสานรวมคอมโพเนนต์ทำได้ง่ายกว่า
  </Card>
</CardGroup>
