Documentation Index

Fetch the complete documentation index at: https://academy.insiderone.com/llms.txt

Use this file to discover all available pages before exploring further.

Configure app cards

Prev Next

The App Cards module provides a complete API for accessing and managing Insider One’s app cards campaigns. It allows you to fetch marketing messages and notifications, track read/unread status, handle interactive buttons within messages, and observe app cards events in real time.

Messages can contain rich content including text, images, and interactive buttons with deeplink actions.

This documentation covers the App Cards API (Insider.appCards) and the current architecture. The legacy Insider.getMessageCenterData(...) method is a separate, older interface for retrieving push notification payloads as a notification center. If you are building a new integration, use the App Cards API.

The InsiderAppCards instance cannot be constructed directly. Access it through the main Insider plugin: Insider.appCards.

Prerequisites

  • cordova-plugin-insider 4.0.1 or later

  • Cordova 7.0.0 or later, cordova-android 6.3.0 or later, cordova-ios 4.3.0 or later (per plugin.xml)

  • Plugin is available after the Cordova deviceready event fires. Call window.Insider.init(...) on deviceready before accessing App Cards.

Access

The plugin is clobbered onto the global Insider object by Cordova, so Insider.appCards is directly reachable from anywhere in your JavaScript once the plugin is ready:

const appCards = Insider.appCards;

Insider.appCards is a frozen namespace object and is always safe to reference after deviceready. The native SDK itself (Android/iOS) returns a no-op instance when it is not initialized or is frozen (e.g., after GDPR consent is revoked). In that state, every asynchronous call resolves with an InsiderAppCardsError whose code is SDK_NOT_INITIALIZED (the native bridge maps AppCardsException.SDK_NOT_INITIALIZED / InsiderAppCardsErrorCodeSdkNotInitialized to the string "sdkNotInitialized"), and every void method (view, click, clickButton) silently returns.

Error handling

App Cards operations can fail with a typed InsiderAppCardsError. In callback form, the error is delivered as the first argument; in Promise form, it is thrown by await.

InsiderAppCardsError

Extends the standard Error class with a structured code that maps to native SDK error codes on both Android and iOS. The class is exposed on the plugin as Insider.AppCardsError.

Name

Type

Required

Description

name

'InsiderAppCardsError'

Yes

Always 'InsiderAppCardsError'

code

InsiderAppCardsErrorCodeType

Yes

Error code identifying the type of error

message

string

Yes

A human-readable error description

Static methods:

Name

Signature

Description

from

(error: { code: string; message: string } | string | unknown) => InsiderAppCardsError

Normalizes a native bridge error into a typed InsiderAppCardsError

InsiderAppCardsErrorCode

Exposed on the plugin as Insider.AppCardsErrorCode.

Constant

Value

Description

UNKNOWN

"unknown"

An unknown or unexpected error occurred.

SDK_NOT_INITIALIZED

"sdkNotInitialized"

The Insider SDK is not initialized, frozen, or not GDPR compliant.

INVALID_PARAMETER

"invalidParameter"

An invalid parameter was provided (e.g., empty or non-string IDs).

NETWORK_ERROR

"networkError"

A network error occurred during the request.

SERVER_ERROR

"serverError"

The server returned an error response.

PARSE_ERROR

"parseError"

The server response could not be parsed.

Method example:

try {
  const response = await window.Insider.appCards.getCampaigns();

  console.log("Campaigns:", response.appCards.length);
} catch (error) {
  if (error instanceof Insider.AppCardsError) {
    switch (error.code) {
      case Insider.AppCardsErrorCode.NETWORK_ERROR:
        console.warn("Network issue, please try again");
        break;

      case Insider.AppCardsErrorCode.SDK_NOT_INITIALIZED:
        console.warn("SDK not ready");
        break;

      default:
        console.warn(
          "App Cards error:",
          error.code,
          error.message
        );
        break;
    }
  }
}

Core types

InsiderAppCardsCampaignResponse

Root container returned from getCampaigns. Holds the full list of app cards retrieved for the current user.

Name

Type

Required

Description

appCards

InsiderAppCard[]

Yes

Array of all app cards in the campaigns

InsiderAppCard

Represents a single app card. Contains all data for the card: content, images, buttons, and associated action.

Name

Type

Required

Description

id

string

Yes

Unique identifier for the app card

type

InsiderAppCardType

Yes

Type of the app card ("message" or "image")

isRead

boolean

Yes

Whether the app card has been read by the user

content

InsiderAppCardContent

No

Text content (title and description)

images

InsiderAppCardImage[]

No

Array of images associated with the app card

buttons

InsiderAppCardButton[]

No

Array of action buttons that can be displayed with the app card

action

InsiderAppCardAction

No

Action to be executed when the app card is tapped

App Card types:

Constant

Description

"message"

Text-based app card

"image"

Image-based app card

Convenience methods:

Method

Description

markAsRead(completion)

Marks this single card as read. Also available as a Promise (omit completion).

markAsUnread(completion)

Marks this single card as unread. Also available as a Promise.

delete(completion)

Deletes this card permanently.

click()

Handles a click event (executes action + logs click conversion).

view()

Handles a view event (logs view conversion).

InsiderAppCardContent

Textual content of an app card.

Name

Type

Required

Description

title

string

Yes

Main title text of the app card

description

string

Yes

Description text of the app card

InsiderAppCardImage

Image associated with an app card.

Name

Type

Required

Description

url

string

Yes

URL of the image to be displayed

InsiderAppCardButton

An interactive button within an app card.

Name

Type

Required

Description

id

string

Yes

Unique identifier for the button

appCardId

string

Yes

Unique identifier of the parent app card

text

string

Yes

Display text shown on the button

action

InsiderAppCardAction

No

Action executed when the button is tapped

Convenience methods:

Method

Description

click()

Handles a click event (executes action + logs button click event).

InsiderAppCardAction (Abstract)

Base type for app card actions. Subtypes represent different actions executed when a user interacts with an app card or a button, such as opening a deeplink, showing feedback, or navigating to system settings.

Name

Type

Required

Description

type

InsiderAppCardActionType

Yes

Type of the action

Action types:

Constant

Description

"deep_link"

Deeplink navigation

"feedback"

Feedback action

"open_settings"

Open system app settings

The concrete runtime type is one of InsiderAppCardDeeplinkAction | InsiderAppCardFeedbackAction | InsiderAppCardOpenSettingsAction. Check action.type before narrowing to a subtype.

InsiderAppCardDeeplinkAction

Deeplink action that navigates to a specific location in the app or to an external URL. Extends InsiderAppCardAction with type === 'deep_link'.

Name

Type

Required

Description

url

string | null

No

The resolved deeplink URL (URL scheme > internal browser > external browser). Returns null when none is configured.

deeplinkType

InsiderAppCardDeeplinkType

Yes

Identifies which URL family was resolved.

json

any | null

No

Parsed JSON payload attached to the deeplink, or null if no JSON was supplied

keysAndValues

{ key: string; value: string }[]

No

Array of key-value pairs defining additional deeplink parameters

Deeplink types:

Constant

Description

"url_scheme"

Custom URL scheme (e.g., myapp://...)

"internal"

Internal webview URL

"external"

External browser URL

"unknown"

Unknown or missing URL

InsiderAppCardFeedbackAction

Marker type for a feedback action. Extends InsiderAppCardAction with no additional fields; type is always "feedback".

InsiderAppCardOpenSettingsAction

Marker type for opening the app's system settings. Extends InsiderAppCardAction with no additional fields; type is always "open_settings".

InsiderAppCardCategory

Represents a single category assigned to an app card.

Name

Type

Required

Description

id

number

Yes

Unique identifier of the category

name

string

Yes

Category name as entered in the panel, e.g., "promotion"

Match on name for app logic: It is the human-readable value configured in the panel. id is stable and useful as a key.

InsiderAppCard.categories

Name

Type

Required

Description

categories

InsiderAppCardCategory[]

Yes

Categories attached to the card. Always an array. Empty when the card has none.

Unlike images and buttons, which are undefined when absent, and content, which is null when absent, categories is never undefined or null. It is always safe to iterate directly:

appCard.categories.forEach(category => {
  console.log(category.id, category.name);
});

Access categories

Categories arrive on the getCampaigns response on every card. No extra call is needed.

Promise style:

const appCards = Insider.appCards;


try {
  const campaignResponse = await appCards.getCampaigns();


  campaignResponse.appCards.forEach(appCard => {
    const names = appCard.categories.map(category => category.name);
    console.log('App Card:', appCard.id, 'Categories:', names.join(', '));
  });
} catch (error) {
  console.warn('Failed to fetch campaigns:', error.code, error.message);
}

Callback style:

const appCards = Insider.appCards;


appCards.getCampaigns((error, campaignResponse) => {
  if (error) {
    console.warn('Failed to fetch campaigns:', error.code, error.message);
    return;
  }


  campaignResponse.appCards.forEach(appCard => {
    appCard.categories.forEach(category => {
      console.log('Category:', category.id, category.name);
    });
  });
});

Filter cards by category

Show only the cards belonging to a given category. E.g., a "Promotions" tab in an inbox screen.

function cardsInCategory(appCards, categoryName) {
  return appCards.filter(appCard =>
    appCard.categories.some(category => category.name === categoryName)
  );
}


const campaignResponse = await Insider.appCards.getCampaigns();
const promotions = cardsInCategory(campaignResponse.appCards, 'promotion');

Group cards by category

Build a sectioned list. A card with multiple categories appears in each of its groups; a card with none is collected under a default bucket.

function groupByCategory(appCards) {
  const groups = {};


  appCards.forEach(appCard => {
    if (appCard.categories.length === 0) {
      groups['other'] = groups['other'] || [];
      groups['other'].push(appCard);
      return;
    }


    appCard.categories.forEach(category => {
      groups[category.name] = groups[category.name] || [];
      groups[category.name].push(appCard);
    });
  });


  return groups;
}

The plugin ships type definitions for the new model.

import type {
  InsiderAppCard,
  InsiderAppCardCategory,
} from 'cordova-plugin-insider/types/InsiderAppCard';


function categoryNames(appCard: InsiderAppCard): string[] {
  return appCard.categories.map((category: InsiderAppCardCategory) => category.name);
}

categories is typed as a non-optional InsiderAppCardCategory[], reflecting the always-an-array guarantee. No null checks or optional chaining is required.

Behavior notes

Case

Behavior

Card has no categories.

categories is []

Categories are missing from the response.

categories is []

A single category entry is invalid.

That entry is ignored; the remaining categories are kept, and the card is still returned

categories is present but not an array.

The whole card is dropped by the native SDK and is not returned in the response

An invalid category entry never fails the whole getCampaigns call; the entry is dropped and the card is still delivered. This is different from a card whose categories value is not an array at all: such a card is treated as malformed and dropped entirely by the native SDK on both iOS and Android.

Categories are delivered only in the getCampaigns response. markAsRead, markAsUnread, and delete operate on card identifiers and are unaffected.

Category support behaves identically on iOS and Android.

Available Methods

getCampaigns

Method signatures

window.Insider.appCards.getCampaigns(completion);

window.Insider.appCards.getCampaigns(); // returns a Promise

Retrieves the user's app card campaigns. Fetches all available app cards from the Insider platform for the current user. Pending campaign requests are canceled before a new one is initiated.

Name

Type

Required

Description

completion

(error?: InsiderAppCardsError, response?: InsiderAppCardsCampaignResponse) => void

Yes

Called with the campaign response or an error. Omit to use the Promise form.

The method supports both completion-callback and Promise forms. Pass a callback to receive (error, response), or omit it and await the returned Promise.

Method example

try {
  const response = await window.Insider.appCards.getCampaigns();

  response.appCards.forEach((appCard) => {
    console.log('App Card Id:', appCard.id, 'Read:', appCard.isRead);
  });
} catch (error) {
  if (error instanceof Insider.AppCardsError) {
    console.warn(error.code, error.message);
  }
}

markAsRead

Method signatures

window.Insider.appCards.markAsRead(appCardIds, completion);

window.Insider.appCards.markAsRead(appCardIds); // returns a Promise

Marks specified app cards as read. Updates the read status of one or more app cards to indicate they have been viewed by the user. The operation synchronizes with the Insider backend to persist state across devices.

Name

Type

Required

Description

appCardIds

string[]

Yes

A non-empty array of app card identifiers to mark as read

completion

(error?: InsiderAppCardsError) => void

No

Called with an error if the request fails, otherwise called with no arguments on success. Omit for the Promise form.

App card IDs that don't exist on the backend are silently ignored. You can also call appCard.markAsRead(completion) directly on an InsiderAppCard instance to mark a single card.

Method example

try {
  await window.Insider.appCards.markAsRead(['card_123', 'card_456']);
  console.log('App cards marked as read successfully');
} catch (error) {
  if (error instanceof Insider.AppCardsError) {
    console.warn(error.code, error.message);
  }
}

markAsUnread

Method signatures

window.Insider.appCards.markAsUnread(appCardIds, completion);

window.Insider.appCards.markAsUnread(appCardIds); // returns a Promise

Marks specified app cards as unread. Updates the read status of one or more app cards to unread. The operation synchronizes with the Insider backend to persist state across devices.

Name

Type

Required

Description

appCardIds

string[]

Yes

A non-empty array of app card identifiers to mark as unread

completion

(error?: InsiderAppCardsError) => void

No

Called with an error if the request fails, otherwise called with no arguments on success. Omit for the Promise form.

You can also call appCard.markAsUnread(completion) directly on an InsiderAppCard instance to unmark a single card.

Method example

try {
  await window.Insider.appCards.markAsUnread(['card_123', 'card_456']);
  console.log('App cards marked as unread successfully');
} catch (error) {
  if (error instanceof Insider.AppCardsError) {
    console.warn(error.code, error.message);
  }
}

delete

Method signatures

window.Insider.appCards.delete(appCardIds, completion);

window.Insider.appCards.delete(appCardIds); // returns a Promise

Permanently removes one or more app cards from the user's campaigns. The operation synchronizes with the Insider backend.

Name

Type

Required

Description

appCardIds

string[]

Yes

A non-empty array of app card identifiers to delete

completion

(error?: InsiderAppCardsError) => void

No

Called with an error if the request fails; otherwise called with no arguments on success. Omit for the Promise form.

You can also call appCard.delete(completion) directly on an InsiderAppCard instance to delete a single card.

Method example

try {
  await window.Insider.appCards.delete(['card_123', 'card_456']);
  console.log('App cards deleted successfully');
} catch (error) {
  if (error instanceof Insider.AppCardsError) {
    console.warn(error.code, error.message);
  }
}

click

Method signature

window.Insider.appCards.click(appCard)

Records a click event for an app card. Call this method when a user clicks or taps on an app card. This executes the app card's deeplink action (if present) and notifies observers.

Name

Type

Required

Description

appCard

InsiderAppCard

Yes

The app card that was clicked. Must be an instance returned from getCampaigns.

You can also call appCard.click() directly on the card instance.

Example

window.Insider.appCards.click(appCard);

view

Method signature

window.Insider.appCards.view(appCard)

Records a view event for an app card. Call this method when an app card becomes visible to the user. This notifies observers and can be used for analytics tracking.

Name

Type

Required

Description

appCard

InsiderAppCard

Yes

The app card that was viewed. Must be an instance returned from getCampaigns

You can also call appCard.view() directly on the card instance.

Example

window.Insider.appCards.view(appCard);

clickButton

Method signature

window.Insider.appCards.clickButton(button)

Records a click event for a button within an app card. Call this method when a user clicks or taps on a button in an app card. This executes the button's action (if present) and notifies observers.

Name

Type

Required

Description

button

InsiderAppCardButton

Yes

The button that was clicked. Must be an instance obtained from appCard.buttons.

You can also call button.click() directly on the button instance.

Example

window.Insider.appCards.clickButton(button);

Full Integration Example

End-to-end flow: wait for deviceready, initialize the SDK, fetch campaigns, view a card, click a button, branch on action type, and mark unread cards as read — with proper error handling.

document.addEventListener('deviceready', onDeviceReady, false);

function onDeviceReady() {
  window.Insider.init('your_partner_name', 'group.com.example.app', (event) => {
    // handle Insider notification callbacks here
  });

  loadAppCards();
}

async function loadAppCards() {
  try {
    const response = await window.Insider.appCards.getCampaigns();
    const cards = response.appCards ?? [];

    if (cards.length === 0) return;

    const firstCard = cards[0];
    window.Insider.appCards.view(firstCard);

    const firstButton = firstCard.buttons && firstCard.buttons[0];

    if (firstButton) {
      window.Insider.appCards.clickButton(firstButton);
      handleAction(firstButton.action);
    }

    const unreadIds = cards
      .filter((card) => !card.isRead)
      .map((card) => card.id);

    if (unreadIds.length > 0) {
      await window.Insider.appCards.markAsRead(unreadIds);
    }
  } catch (error) {
    if (error instanceof Insider.AppCardsError) {
      switch (error.code) {
        case Insider.AppCardsErrorCode.NETWORK_ERROR:
          console.warn('Network issue, please try again');
          break;

        case Insider.AppCardsErrorCode.SDK_NOT_INITIALIZED:
          console.warn('SDK not ready');
          break;

        default:
          console.warn('App Cards error:', error.code, error.message);
      }
    }
  }
}

function handleAction(action) {
  if (!action) return;

  switch (action.type) {
    case 'deep_link':
      if (action.url) {
        // Open the deeplink — use cordova-plugin-inappbrowser for internal URLs,
        // window.open for external ones, or a custom URL-scheme handler.
        window.open(action.url, '_system');
      }
      break;

    case 'feedback':
      // present your feedback UI
      break;

    case 'open_settings':
      // navigate to system settings via your preferred Cordova plugin
      break;
  }
}