Crisp
Crisp is a customer messaging platform that lets you communicate with your customers through chat, email, and more.
Nuxt Scripts provides a useScriptCrisp() composable and a headless Facade Component <ScriptCrisp> component to interact with crisp.
Nuxt Config Setup
The simplest way to load Crisp globally in your Nuxt App is to use Nuxt config. Alternatively you can directly use the useScriptCrisp composable.
export default defineNuxtConfig({
scripts: {
registry: {
crisp: {
id: 'YOUR_WEBSITE_ID'
}
}
}
})useScriptCrisp()
The useScriptCrisp composable lets you have fine-grain control over when and how Crisp is loaded on your site.
const { proxy } = useScriptCrisp()
proxy.$crisp.push(['do', 'chat:open'])Please follow the Registry Scripts guide to learn more about advanced usage.
First-Party Mode
This script supports First-Party Mode which is auto-enabled, routing all traffic through your domain for improved privacy and ad blocker bypass.
export default defineNuxtConfig({
scripts: {
registry: {
crisp: {
id: 'YOUR_WEBSITE_ID'
}
}
}
})Example
Using Crisp only in production while using the proxy to send events.
<script setup lang="ts">
const { proxy } = useScriptCrisp()
// noop in development, ssr
// just works in production, client
function handleAction() {
proxy.$crisp.push(['do', 'chat:open'])
}
</script>
<template>
<div>
<button @click="handleAction">
Send Event
</button>
</div>
</template><ScriptCrisp>
The <ScriptCrisp> component is headless Facade Component wrapping the useScriptCrisp() composable, providing a simple, performance optimized way to load Crisp in your Nuxt app.
It's optimized for performance by using the Element Event Triggers, only loading crisp when specific elements events happen.
By default, it will load on the click DOM event.
Demo
<script setup lang="ts">
const isLoaded = ref(false)
</script>
<template>
<div class="not-prose">
<div class="flex items-center justify-center p-5">
<ScriptCrisp id="b1021910-7ace-425a-9ef5-07f49e5ce417" class="crisp">
<template #awaitingLoad>
<div class="crisp-icon" />
</template>
<template #loading>
<ScriptLoadingIndicator color="black" />
</template>
</ScriptCrisp>
</div>
<div class="text-center">
<UAlert v-if="!isLoaded" class="mb-5" size="sm" color="blue" variant="soft" title="Click to load" description="Clicking the button to the right will load crisp script" />
<UAlert v-else color="green" variant="soft" title="Crisp is loaded" description="The Crisp Facade component is no longer being displayed." />
</div>
</div>
</template>
<style>
.crisp {
width: 54px;
height: 54px;
border-radius: 54px;
cursor: pointer;
background-color: #1972F5;
position: relative; /* change to fixed */
bottom: 20px;
right: 24px;
z-index: 100000;
box-shadow: 0 4px 10px 0 rgba(0,0,0!important,.05) !important;
}
.crisp-icon {
position: absolute;
top: 16px;
left: 11px;
width: 32px;
height: 26px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjMwIiB3aWR0aD0iMzUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxmaWx0ZXIgaWQ9ImEiIGhlaWdodD0iMTM4LjclIiB3aWR0aD0iMTMxLjQlIiB4PSItMTUuNyUiIHk9Ii0xNS4xJSI+PGZlTW9ycGhvbG9neSBpbj0iU291cmNlQWxwaGEiIG9wZXJhdG9yPSJkaWxhdGUiIHJhZGl1cz0iMSIgcmVzdWx0PSJzaGFkb3dTcHJlYWRPdXRlcjEiLz48ZmVPZmZzZXQgZHk9IjEiIGluPSJzaGFkb3dTcHJlYWRPdXRlcjEiIHJlc3VsdD0ic2hhZG93T2Zmc2V0T3V0ZXIxIi8+PGZlR2F1c3NpYW5CbHVyIGluPSJzaGFkb3dPZmZzZXRPdXRlcjEiIHJlc3VsdD0ic2hhZG93Qmx1ck91dGVyMSIgc3RkRGV2aWF0aW9uPSIxIi8+PGZlQ29tcG9zaXRlIGluPSJzaGFkb3dCbHVyT3V0ZXIxIiBpbjI9IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0ib3V0IiByZXN1bHQ9InNoYWRvd0JsdXJPdXRlcjEiLz48ZmVDb2xvck1hdHJpeCBpbj0ic2hhZG93Qmx1ck91dGVyMSIgdmFsdWVzPSIwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwLjA3IDAiLz48L2ZpbHRlcj48cGF0aCBpZD0iYiIgZD0iTTE0LjIzIDIwLjQ2bC05LjY1IDEuMUwzIDUuMTIgMzAuMDcgMmwxLjU4IDE2LjQ2LTkuMzcgMS4wNy0zLjUgNS43Mi00LjU1LTQuOHoiLz48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48dXNlIGZpbGw9IiMwMDAiIGZpbHRlcj0idXJsKCNhKSIgeGxpbms6aHJlZj0iI2IiLz48dXNlIGZpbGw9IiNmZmYiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIyIiB4bGluazpocmVmPSIjYiIvPjwvZz48L3N2Zz4=)!important
}
@media (max-height: 600px) {
.crisp {
bottom: 14px;
right: 14px;
}
}
</style>
Component API
See the Facade Component API for full props, events, and slots.
With Environment Variables
If you prefer to configure your id using environment variables.
export default defineNuxtConfig({
scripts: {
registry: {
crisp: true,
}
},
// you need to provide a runtime config to access the environment variables
runtimeConfig: {
public: {
scripts: {
crisp: {
id: '', // NUXT_PUBLIC_SCRIPTS_CRISP_ID
},
},
},
},
})
NUXT_PUBLIC_SCRIPTS_CRISP_ID=<YOUR_ID>
Events
The <ScriptCrisp> component emits a single ready event when Crisp loads.
const emits = defineEmits<{
ready: [crisp: Crisp]
}>()
<script setup lang="ts">
function onReady(crisp) {
console.log('Crisp is ready', crisp)
}
</script>
<template>
<ScriptCrisp @ready="onReady" />
</template>
Slots
awaitingLoad
This slot displays content while Crisp is loading.
<template>
<ScriptCrisp>
<template #awaitingLoad>
<div style="width: 54px; height: 54px; border-radius: 54px; cursor: pointer; background-color: #1972F5;">
chat!
</div>
</template>
</ScriptCrisp>
</template>
loading
This slot displays content while Crisp is loading.
Tip: You should use the ScriptLoadingIndicator by default for accessibility and UX.
<template>
<ScriptCrisp>
<template #loading>
<div class="bg-blue-500 text-white p-5">
Loading...
</div>
</template>
</ScriptCrisp>
</template>
useScriptCrisp()
The useScriptCrisp() composable lets you have fine-grain control over Crisp SDK. It provides a way to load crisp SDK and interact with it programmatically.
export function useScriptCrisp<T extends CrispApi>(_options?: CrispInput) {}
Please follow the Registry Scripts guide to learn more about advanced usage.
For more information, please refer to the Crisp API documentation.
idstring required The Crisp ID.
runtimeConfigobjectExtra configuration options. Used to configure the locale. Same as CRISP_RUNTIME_CONFIG.
tokenIdstringAssociated a session, equivalent to using CRISP_TOKEN_ID variable. Same as CRISP_TOKEN_ID.
cookieDomainstringRestrict the domain that the Crisp cookie is set on. Same as CRISP_COOKIE_DOMAIN.
cookieExpirynumberThe cookie expiry in seconds. Same as CRISP_COOKIE_EXPIRATION.
Example
Loading the Crisp SDK and interacting with it programmatically.
<script setup lang="ts">
const { proxy } = useScriptCrisp({
id: 'YOUR_ID'
})
proxy.set('user:nickname', 'Harlan')
proxy.do('chat:open')
</script>