Skip to content

Commit c96863c

Browse files
committed
Add callbacks for before chat provider init and after script ready
The callbacks are available for setting values prior to initialization (e.g for user identification), and for interacting with a provider script once fully loaded (e.g. for registering events with a provider.)
1 parent a8f46ca commit c96863c

10 files changed

Lines changed: 97 additions & 25 deletions

File tree

README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# React Live Chat Loader
22

33
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
4+
45
[![All Contributors](https://img.shields.io/badge/all_contributors-8-orange.svg?style=flat-square)](#contributors-)
6+
57
<!-- ALL-CONTRIBUTORS-BADGE:END -->
68

7-
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)](CODE_OF_CONDUCT.md)
9+
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)](CODE_OF_CONDUCT.md)
810

911
An npm module that allows you to mitigate the negative performance and user
1012
experience impact of chat tools. `react-live-chat-loader` shows a fake widget
@@ -22,7 +24,7 @@ Made by the team at [♠ Calibre](https://calibreapp.com/), your performance com
2224
6. [Contributing](#-contributing)
2325
7. [Examples](#-examples)
2426

25-
## 💡 How it Works
27+
## 💡 How it Works
2628

2729
Chat widgets rely heavily on JavaScript which comes at a cost. Given the
2830
significant impact that comes from the download, parse, compile and execution of
@@ -40,7 +42,7 @@ connection (using `navigator.connection.effectiveType`) or has data-saver enable
4042

4143
> ⚠️ **Please note**: Some chat widget providers open automatically based on the people’s interaction from their last session.
4244
43-
## 📥 Installation
45+
## 📥 Installation
4446

4547
To download react-live-chat-loader run:
4648

@@ -126,6 +128,8 @@ You can pass the following props to the `LiveChatLoaderProvider` provider:
126128
- `idlePeriod`: How long to wait in ms before loading the provider. Default is
127129
`2000`. Set to `0` to never load. This value is used in a `setTimeout` in
128130
browsers that don't support `requestIdleCallback`.
131+
- `beforeInit`: A function to be called after the script has loaded, but before the chat provider has been initialized (optional)
132+
- `onReady`: A function to be called once the script has been loaded, the chat provider has been initialized and is ready for use (optional)
129133

130134
## 💬 Supported Providers
131135

@@ -338,9 +342,11 @@ You can customise the Chatwoot Widget by passing the following props to the
338342
</details>
339343

340344
## ➕ Adding a Provider
345+
341346
To add a new live chat provider, follow the steps in [Contributing: Adding a Provider](CONTRIBUTING.md#-adding-a-provider).
342347

343348
## 🙌 Contributing
349+
344350
Happy to hear you’re interested in contributing to React Live Chat Loader! Please find our contribution guidelines [here](CONTRIBUTING.md).
345351

346352
## 🖥️ Examples
@@ -352,7 +358,7 @@ Happy to hear you’re interested in contributing to React Live Chat Loader! Ple
352358
- [How to avoid performance regressions when using live chat tools](https://calibreapp.com/blog/fast-live-chat)
353359
- [Reducing the Intercom Messenger bundle size by 65%](https://www.intercom.com/blog/reducing-intercom-messenger-bundle-size/)
354360

355-
## ✨ Contributors
361+
## ✨ Contributors
356362

357363
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
358364

src/components/LiveChatLoaderProvider.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@ import * as Providers from '../providers'
33
import { State, Provider } from '../types'
44
import { LiveChatLoaderContext } from '../context'
55

6-
export const LiveChatLoaderProvider = ({
7-
provider,
8-
children,
9-
idlePeriod = 5000,
10-
baseUrl,
11-
...props
12-
}: {
6+
interface LiveChatLoaderProps {
137
provider: Provider
148
children: JSX.Element
159
idlePeriod?: number
1610
providerKey: string
1711
appID?: string
1812
baseUrl?: string
19-
}): JSX.Element | null => {
13+
beforeInit?: () => void
14+
onReady?: () => void
15+
}
16+
17+
export const LiveChatLoaderProvider = ({
18+
provider,
19+
children,
20+
idlePeriod = 5000,
21+
baseUrl,
22+
...props
23+
}: LiveChatLoaderProps): JSX.Element | null => {
2024
const [state, setState] = useState<State>('initial')
2125
const value = {
2226
provider,

src/context.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ interface Context {
1111
locale?: string
1212
idlePeriod?: number
1313
baseUrl?: string
14+
beforeInit?: () => void
15+
onReady?: () => void
1416
}
1517

1618
export const LiveChatLoaderContext = createContext<Context>({} as Context)

src/hooks/useChat.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ const useChat = (
2727
setState,
2828
appID,
2929
locale,
30-
baseUrl
30+
baseUrl,
31+
beforeInit,
32+
onReady
3133
} = useContext(LiveChatLoaderContext)
3234

3335
useEffect(() => {
@@ -84,7 +86,15 @@ const useChat = (
8486
return
8587
}
8688

87-
chatProvider.load({ providerKey, setState, appID, locale, baseUrl })
89+
chatProvider.load({
90+
providerKey,
91+
setState,
92+
appID,
93+
locale,
94+
baseUrl,
95+
beforeInit,
96+
onReady
97+
})
8898

8999
if (open) {
90100
chatProvider.open()

src/providers/chatwoot.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,25 @@ const load = ({
3939
providerKey,
4040
locale = 'en',
4141
setState,
42-
baseUrl = domain
42+
baseUrl = domain,
43+
beforeInit = () => undefined,
44+
onReady = () => undefined
4345
}: {
4446
providerKey: string
4547
locale?: string
4648
setState: (state: State) => void
4749
baseUrl?: string
50+
beforeInit?: () => void
51+
onReady?: () => void
4852
}): void => {
4953
const loaded = loadScript(function() {
50-
setTimeout(() => setState('complete'), 1000)
54+
beforeInit()
55+
56+
setTimeout(() => {
57+
setState('complete')
58+
onReady()
59+
}, 1000)
60+
5161
window.chatwootSDK.run({
5262
websiteToken: providerKey,
5363
baseUrl,

src/providers/drift.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,25 @@ const loadScript = (): boolean => {
6969

7070
const load = ({
7171
providerKey,
72-
setState
72+
setState,
73+
beforeInit = () => undefined,
74+
onReady = () => undefined
7375
}: {
7476
providerKey: string
7577
setState: (state: State) => void
78+
beforeInit?: () => void
79+
onReady?: () => void
7680
}): boolean => {
7781
const loaded = loadScript()
7882

7983
// Continue as long as drift hasn’t already been initialised.
8084
if (loaded) {
85+
beforeInit()
8186
window.drift.load(providerKey)
8287
window.drift.SNIPPET_VERSION = '0.3.1'
8388
window.drift.on('ready', () => {
8489
setState('complete')
90+
onReady()
8591
})
8692
}
8793

src/providers/helpScout.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,27 @@ const loadScript = (): boolean => {
3939

4040
const load = ({
4141
providerKey,
42-
setState
42+
setState,
43+
beforeInit = () => undefined,
44+
onReady = () => undefined
4345
}: {
4446
providerKey: string
4547
setState: (state: State) => void
48+
beforeInit?: () => void
49+
onReady?: () => void
4650
}): boolean => {
4751
const loaded = loadScript()
4852

4953
// Continue as long as helpscout hasn’t already been initialised.
5054
if (loaded) {
55+
beforeInit()
5156
window.Beacon('init', providerKey)
5257
window.Beacon('once', 'ready', () =>
5358
// Allow helpscout to complete loading before removing fake widget
54-
setTimeout(() => setState('complete'), 2000)
59+
setTimeout(() => {
60+
setState('complete')
61+
onReady()
62+
}, 2000)
5563
)
5664
}
5765

src/providers/intercom.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,29 @@ const loadScript = (appId: string): boolean => {
4747

4848
const load = ({
4949
providerKey,
50-
setState
50+
setState,
51+
beforeInit = () => undefined,
52+
onReady = () => undefined
5153
}: {
5254
providerKey: string
5355
setState: (state: State) => void
56+
beforeInit?: () => void
57+
onReady?: () => void
5458
}): boolean => {
5559
const loaded = loadScript(providerKey)
5660

5761
// Continue as long as userlike hasn’t already been initialised.
5862
if (loaded) {
63+
beforeInit()
5964
window.Intercom('boot', { app_id: providerKey })
6065
waitForLoad(
6166
() => window.Intercom.booted,
6267
// Allow intercom to complete loading before removing fake widget
63-
() => setTimeout(() => setState('complete'), 2000)
68+
() =>
69+
setTimeout(() => {
70+
setState('complete')
71+
onReady()
72+
}, 2000)
6473
)
6574
}
6675

src/providers/messenger.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,20 @@ const loadScript = (locale: string): boolean => {
3636
const load = ({
3737
appID,
3838
locale = 'en_US',
39-
setState
39+
setState,
40+
beforeInit = () => undefined,
41+
onReady = () => undefined
4042
}: {
4143
appID?: string
4244
locale?: string
4345
setState: (state: State) => void
46+
beforeInit?: () => void
47+
onReady?: () => void
4448
}): boolean => {
4549
const loaded = loadScript(locale)
4650
// Continue as long as messenger hasn’t already been initialised.
4751
if (loaded) {
52+
beforeInit()
4853
window.fbAsyncInit = function() {
4954
window.FB.init(
5055
Object.assign(
@@ -58,7 +63,10 @@ const load = ({
5863
)
5964
window.FB.Event.subscribe('customerchat.load', () =>
6065
// Allow messenger to complete loading before removing fake widget
61-
setTimeout(() => setState('complete'), 3000)
66+
setTimeout(() => {
67+
setState('complete')
68+
onReady()
69+
}, 3000)
6270
)
6371
}
6472
}

src/providers/userlike.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,27 @@ const loadScript = (providerKey: string): boolean => {
3535

3636
const load = ({
3737
providerKey,
38-
setState
38+
setState,
39+
beforeInit = () => undefined,
40+
onReady = () => undefined
3941
}: {
4042
providerKey: string
4143
setState: (state: State) => void
44+
beforeInit?: () => void
45+
onReady?: () => void
4246
}): boolean => {
4347
const loaded = loadScript(providerKey)
4448
// Continue as long as userlike hasn’t already been initialised.
4549
if (loaded) {
50+
beforeInit()
4651
waitForLoad(
4752
() => !!window.userlike,
4853
// Allow userlike to complete loading before removing fake widget
49-
() => setTimeout(() => setState('complete'), 2000)
54+
() =>
55+
setTimeout(() => {
56+
setState('complete')
57+
onReady()
58+
}, 2000)
5059
)
5160
}
5261

0 commit comments

Comments
 (0)