diff --git a/README.md b/README.md
index 02647ea5..a9243635 100644
--- a/README.md
+++ b/README.md
@@ -75,6 +75,7 @@ Place the `IntercomProvider` as high as possible in your application. This will
| onUnreadCountChange | (number) => void | triggered when the current number of unread messages changes | false | |
| shouldInitialize | boolean | indicates if the Intercom should be initialized. Can be used in multistaged environment | false | true |
| apiBase | string | If you need to route your Messenger requests through a different endpoint than the default. Generally speaking, this is not needed. Format: `https://${INTERCOM_APP_ID}.intercom-messenger.com` (See: [https://github.com/devrnt/react-use-intercom/pull/96](https://github.com/devrnt/react-use-intercom/pull/96)) | false | |
+| initializeDelay | number | Indicates if the intercom initialization should be delayed, delay is in ms, defaults to 0. See https://github.com/devrnt/react-use-intercom/pull/236 | false | |
#### Example
```javascript
@@ -239,6 +240,15 @@ These props are `JavaScript` 'friendly', so [camelCase](https://en.wikipedia.org
> Mind that all the properties in `react-use-intercom` are camel cased, except for the `customAttributes` property in the `boot` and `update` method from `useIntercom`.
## Advanced
+
+### Delay initialization
+
+`` uses an official intercom snippet and is directly initialized on load. In the background this snippet will load some external code that makes Intercom work. All of this magic happens on the initial load and in some use cases this can become problematic (E.g. when LCP is priority).
+
+Since [v1.2.0](https://github.com/devrnt/react-use-intercom/releases/tag/v1.2.0) it's possible to delay this initialisation by passing `initializeDelay` in `` (it's in milliseconds). However most of the users won't need to mess with this.
+
+For reference see https://github.com/devrnt/react-use-intercom/pull/236 and https://forum.intercom.com/s/question/0D52G00004WxWLs/can-i-delay-loading-intercom-on-my-site-to-reduce-the-js-load
+### useCallback
To reduce the amount of re-renders in your React application I suggest to make use of [`useCallback`](https://reactjs.org/docs/hooks-reference.html#usecallback)
**TLDR:** `useCallback` will return a memoized version of the callback that only changes if one of the dependencies has changed.
diff --git a/playground/app.tsx b/playground/app.tsx
index 62f51864..06281e1f 100644
--- a/playground/app.tsx
+++ b/playground/app.tsx
@@ -8,6 +8,7 @@ import {
ProviderEventsPage,
ProviderApiPage,
UseIntercomTourPage,
+ UseIntercomWithDelay
} from './modules';
import { Page, Style } from './modules/common';
@@ -47,6 +48,7 @@ const App = () => {
+
@@ -61,6 +63,9 @@ const App = () => {
useIntercom with tour
+
+ useIntercom with delayed boot
+
diff --git a/playground/modules/useIntercom/index.ts b/playground/modules/useIntercom/index.ts
index f51c1959..3653d9ac 100644
--- a/playground/modules/useIntercom/index.ts
+++ b/playground/modules/useIntercom/index.ts
@@ -1,2 +1,3 @@
export { default as UseIntercomPage } from './useIntercom';
export { default as UseIntercomTourPage } from './useIntercomTour';
+export { default as UseIntercomWithDelay } from './useIntercomWithDelay'
diff --git a/playground/modules/useIntercom/useIntercomWithDelay.tsx b/playground/modules/useIntercom/useIntercomWithDelay.tsx
new file mode 100644
index 00000000..1aa7660a
--- /dev/null
+++ b/playground/modules/useIntercom/useIntercomWithDelay.tsx
@@ -0,0 +1,42 @@
+import * as React from 'react';
+import styled from 'styled-components';
+
+import { IntercomProvider } from '../../../.';
+
+const Grid = styled.div`
+ display: grid;
+ grid-template-columns: repeat(1, 1fr);
+ width: 100%;
+`;
+
+const Item = styled.div`
+ display: grid;
+ grid-template-rows: min-content;
+
+ &::after {
+ content: '';
+ margin: 2rem 0 1.5rem;
+ border-bottom: 2px solid var(--grey);
+ width: 100%;
+ }
+`;
+
+const RawUseIntercomPage = () => {
+ return (
+
+
+
Intercom will be initialized (and autobooted) after 5000ms
+
+
+ );
+};
+
+const UseIntercomWithDelayPage = () => {
+ return (
+
+
+
+ );
+};
+
+export default UseIntercomWithDelayPage;
diff --git a/src/initialize.ts b/src/initialize.ts
index dd39b883..afbc69c0 100644
--- a/src/initialize.ts
+++ b/src/initialize.ts
@@ -3,10 +3,11 @@
* Snippet to initialize the Intercom instance
*
* @param appId - Intercom app id
+ * @param [timeout=0] - Amount of milliseconds that the initialization should be delayed, defaults to 0
*
* @see {@link https://developers.intercom.com/installing-intercom/docs/basic-javascript}
*/
-const initialize = (appId: string) => {
+const initialize = (appId: string, timeout = 0) => {
var w = window;
var ic = w.Intercom;
if (typeof ic === 'function') {
@@ -23,12 +24,14 @@ const initialize = (appId: string) => {
};
w.Intercom = i;
var l = function() {
- var s = d.createElement('script');
- s.type = 'text/javascript';
- s.async = true;
- s.src = 'https://widget.intercom.io/widget/' + appId;
- var x = d.getElementsByTagName('script')[0];
- x.parentNode.insertBefore(s, x);
+ setTimeout(function() {
+ var s = d.createElement('script');
+ s.type = 'text/javascript';
+ s.async = true;
+ s.src = 'https://widget.intercom.io/widget/' + appId;
+ var x = d.getElementsByTagName('script')[0];
+ x.parentNode.insertBefore(s, x);
+ }, timeout);
};
if (document.readyState === 'complete') {
l();
diff --git a/src/provider.tsx b/src/provider.tsx
index 221f8105..408de717 100644
--- a/src/provider.tsx
+++ b/src/provider.tsx
@@ -22,6 +22,7 @@ export const IntercomProvider: React.FC = ({
onUnreadCountChange,
shouldInitialize = !isSSR,
apiBase,
+ initializeDelay,
...rest
}) => {
const isBooted = React.useRef(autoBoot);
@@ -36,7 +37,7 @@ export const IntercomProvider: React.FC = ({
);
if (!isSSR && !window.Intercom && shouldInitialize) {
- initialize(appId);
+ initialize(appId, initializeDelay);
// Only add listeners on initialization
if (onHide) IntercomAPI('onHide', onHide);
if (onShow) IntercomAPI('onShow', onShow);
@@ -56,7 +57,10 @@ export const IntercomProvider: React.FC = ({
}
const ensureIntercom = React.useCallback(
- (functionName: string = 'A function', callback: Function) => {
+ (
+ functionName: string = 'A function',
+ callback: (() => void) | (() => string),
+ ) => {
if (!window.Intercom && !shouldInitialize) {
logger.log(
'warn',
@@ -173,8 +177,8 @@ export const IntercomProvider: React.FC = ({
const getVisitorId = React.useCallback(() => {
return ensureIntercom('getVisitorId', () => {
- return (IntercomAPI('getVisitorId') as unknown) as string;
- });
+ return IntercomAPI('getVisitorId');
+ }) as string;
}, [ensureIntercom]);
const startTour = React.useCallback(
diff --git a/src/types.ts b/src/types.ts
index d07b8003..543fa57f 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -419,4 +419,10 @@ export type IntercomProviderProps = {
* Format https://${INTERCOM_APP_ID}.intercom-messenger.com
*/
apiBase?: string;
+ /**
+ * Indicates if the intercom initialization should be delayed, delay is in ms
+ *
+ * @remarks If not set delay is set to 0ms
+ * */
+ initializeDelay?: number;
};
diff --git a/test/useIntercom.test.tsx b/test/useIntercom.test.tsx
index cdd477fb..cab46cdb 100644
--- a/test/useIntercom.test.tsx
+++ b/test/useIntercom.test.tsx
@@ -44,4 +44,30 @@ describe('useIntercom', () => {
expect(window.intercomSettings).toEqual({ app_id: INTERCOM_APP_ID });
});
+
+ test('should await a certain amount on delayed initialization', async () => {
+ const { result, waitFor } = renderHook(() => useIntercom(), {
+ wrapper: ({ children }) => (
+
+ {children}
+
+ ),
+ });
+
+ const { boot } = result.current;
+
+ act(() => {
+ boot();
+ });
+
+ expect(window.intercomSettings).toEqual({ app_id: undefined });
+
+ await waitFor(() => {}, { timeout: 5000 });
+
+ act(() => {
+ boot();
+ });
+
+ expect(window.intercomSettings).toEqual({ app_id: INTERCOM_APP_ID });
+ });
});