# In-app messages

You don’t need to do anything besides install the web SDK and identify people to send in-app messages to your website visitors. However, you may want to understand how some in-app features work to better target and display messages.

## How it works[](#how-it-works)

In-app messages for your website work differently than push notifications would: they require JavaScript, and they don’t go through a push notification service (like APNs or FCM).

This means that as long as you `identify` your web visitors, and those visitors don’t disable JavaScript, you can send in-app messages to people.

## Send an in-app message[](#send-an-in-app-message)

In general, you don’t need to do anything special with the web SDK to send an in-app message. You simply need to identify a person before you can send a message; you can’t send in-app messages anonymously.

That said, to send an in-app message, you’ll need to do the following things. Because most of these things happen outside the SDK, we’ve linked to relevant documentation.

1.  [Enable in-app messaging](/journeys/in-app-getting-started/#enable-in-app)
2.  [Set up message templates](/journeys/in-app-messages/)
3.  [Set up in-app messages in your campaigns or broadcasts](/journeys/send-in-app-message/#send-an-in-app-message)
4.  [Identify visitors to your website](/integrations/data-in/connections/javascript/legacy-js/identify/). You cannot send in-app messages anonymously.

## Page rules and in-app messages[](#page-rules-and-in-app-messages)

**[Page rules](/journeys/send-in-app-message/#page-rule)** help you determine the pages where people can encounter your messages, ensuring that they’re relevant to the pages people visit on your website.

Page rules also help avoid conflicting messages by distributing messages to the pages where they’re most relevant to your audience. If you send two messages of the same priority without page rules, they’ll appear one after the other.

[![set in-app page rules to determine the page your message appears on](https://docs.customer.io/images/in-app-page-rule.png)](#a55af0f9917c15a7b484c9df200f448d-lightbox)

When you set a page rule for the *Web* platform, we use the page URL pathname (`new URL(window.location.href).pathname`) unless you pass `page` calls with a different `name` parameter. We don’t support query strings.

For example, an *include* rule for `https://example.com/*/billing` allows a message to appear on `https://example.com/ui/billing` or documents about billing under `https://example.com/billing`. See the [page method reference](/integrations/data-in/connections/javascript/method-reference/#page) for more information.

 Use `*` to represent all pages

When you select a channel, you have to enter a page rule. But, if you want to show a message on *every* page on your website or app, you can simply enter `*`.

### Page rules for single-page applications[](#page-rules-for-single-page-applications)

If your website is a single-page app (SPA), you must [send `page` calls](/integrations/data-in/connections/javascript/legacy-js/events/#page-view-events) to tell the SDK what “page” a person is on.

## Listen to in-app message events[](#listen-to-in-app-message-events)

The JavaScript snippet exposes several in-app message events that you can listen to via the `_cio.on` and `_cio.off` API. All events have a payload object with a `type` property that indicates the type of event and `detail` property that contains data corresponding to the event type.

Make sure you add `"on"` and `"off`" to the list of functions you call on `_cio` in the snippet.

```javascript
<script type="text/javascript">
    var _cio = _cio || [];
    (function() {
        var a,b,c;a=function(f){return function(){_cio.push([f].
        concat(Array.prototype.slice.call(arguments,0)))}};b=["load","identify",
        "sidentify","track","page","on","off"];for(c=0;c<b.length;c++){_cio[b[c]]=a(b[c])};
        var t = document.createElement('script'),
            s = document.getElementsByTagName('script')[0];
        t.async = true;
        t.id    = 'cio-tracker';
        t.setAttribute('data-site-id', 'YOUR_SITE_ID');
        t.setAttribute('data-use-array-params', 'true');
        t.setAttribute('data-use-in-app', 'true');
        t.src = 'https://assets.customer.io/assets/track.js';
        //If your account is in the EU, use:
        //t.src = 'https://assets.customer.io/assets/track-eu.js'
        s.parentNode.insertBefore(t, s);
    })();
</script>
```

#### Message opened event[](#message-opened-event)

This event is triggered when an in-app message is shown to the user. The `detail` property always contains the `messageId` property whereas the `deliveryId` is not present if it’s a test message.

 Handle a message opened event

#### Handle a message opened event[](#Handle a message opened event)

```javascript
const onMessageOpened = function (event) {
    console.log('Type: ', event.type);
    console.log('Message Id: ', event.detail.messageId);
    console.log('Delivery Id: ', event.detail.deliveryId); // not present in test messages
};

// run the listener everytime message is shown
_cio.on('in-app:message-opened', onMessageOpened);

// run the listener only once
_cio.on('in-app:message-opened', onMessageOpened, { once: true })

// turn off the listener
_cio.off('in-app:message-opened', onMessageOpened)
```

 Event object

#### Event object[](#Event object)

*   type string
    
    Defines the event type.
    
    Accepted values:`in-app:message-opened`
    

#### Message dismissed event[](#message-dismissed-event)

This event is triggered when an in-app message is dismissed by the user.

 Handle a message dismissed event

#### Handle a message dismissed event[](#Handle a message dismissed event)

```javascript
_cio.on('in-app:message-dismissed', function (event) {
    // handle dismissed message
});
```

 Event object

#### Event object[](#Event object)

*   type string
    
    Defines the event type.
    
    Accepted values:`in-app:message-dismissed`
    

#### Message action event[](#message-action-event)

This event is triggered when the user performs an action on an in-app message.

 Handle a message action event

#### Handle a message action event[](#Handle a message action event)

```javascript
_cio.on('in-app:message-action', function (event) {
    // handle action
    
    // optional call to dismiss the message after handling the action
    event.detail.message.dismiss();
});
```

 Event object

#### Event object[](#Event object)

*   detail object
    
    *   actionName string
        
        The name of the action specified when building the in-app message.
        
    *   actionValue string
        
        The type of action that triggered the event.
        
    *   deliveryId string
        
        Delivery Id for the corresponding in-app message (not present in test message).
        
    *   messageId string
        
        Identifier string of the in-app message.
        
*   type string
    
    Defines the event type.
    
    Accepted values:`in-app:message-action`
    

#### Message error event[](#message-error-event)

This event is triggered when an in-app message produces an error.

 Handle a message error event

#### Handle a message error event[](#Handle a message error event)

```javascript
_cio.on('in-app:message-error', function (event) {
    // handle error
});
```

 Event object

#### Event object[](#Event object)

*   type string
    
    Defines the event type.
    
    Accepted values:`in-app:message-error`