├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── CHANGELOG.md ├── Example ├── .gitignore ├── .ruby-version ├── README.md ├── config.xml ├── hooks │ └── iosDeploymentTarget.js ├── package-lock.json ├── package.json └── www │ ├── css │ └── index.css │ ├── img │ ├── Intercom-logo.png │ ├── Intercom_logo-github.png │ ├── android │ │ ├── hdpi.png │ │ ├── mdpi.png │ │ ├── xhdpi.png │ │ ├── xxhdpi.png │ │ └── xxxhdpi.png │ ├── icon-29.png │ ├── icon-29@2x.png │ ├── icon-29@3x.png │ ├── icon-30.png │ ├── icon-40.png │ ├── icon-40@2x.png │ ├── icon-40@3x.png │ ├── icon-60.png │ ├── icon-60@2x.png │ ├── icon-60@3x.png │ ├── icon-76.png │ ├── icon-76@2x.png │ ├── icon-83.5@2x.png │ ├── launch │ │ └── Default@2x~universal~anyany.png │ └── logo.png │ ├── index.html │ └── js │ └── index.js ├── LICENSE ├── README.md ├── circle.yml ├── intercom-plugin ├── package-lock.json ├── package.json ├── plugin.xml ├── scripts │ ├── checkForUpdate.js │ └── prepareCocoaPods.js ├── src │ ├── android │ │ ├── CordovaHeaderInterceptor.java │ │ ├── HelpCenterCollectionContentModel.java │ │ ├── HelpCenterCollectionModel.java │ │ ├── HelpCenterCollectionSectionModel.java │ │ ├── IntercomBridge.java │ │ ├── RegistrationModel.java │ │ ├── build-extras-intercom.gradle │ │ └── intercom.gradle │ └── ios │ │ ├── AppDelegate+IntercomPush.h │ │ ├── AppDelegate+IntercomPush.m │ │ ├── ICMHelpCenterArticle+DictionaryConversion.h │ │ ├── ICMHelpCenterArticle+DictionaryConversion.m │ │ ├── ICMHelpCenterArticleSearchResult+DictionaryConversion.h │ │ ├── ICMHelpCenterArticleSearchResult+DictionaryConversion.m │ │ ├── ICMHelpCenterCollection+DictionaryConversion.h │ │ ├── ICMHelpCenterCollection+DictionaryConversion.m │ │ ├── ICMHelpCenterCollectionContent+DictionaryConversion.h │ │ ├── ICMHelpCenterCollectionContent+DictionaryConversion.m │ │ ├── ICMUserAttributes+DictionaryConversion.h │ │ ├── ICMUserAttributes+DictionaryConversion.m │ │ ├── IntercomBridge.h │ │ └── IntercomBridge.m └── www │ ├── intercom.js │ └── intercomContent.js ├── runAndroidSample.sh └── runiOSSample.sh /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Please use the following template to submit your issue. Following this template will allow us to quickly investigate and help you with your issue. Please be aware that issues which do not conform to this template may be closed. 2 | 3 | For feature requests please contact us at team@intercom.io 4 | 5 | 6 | ## Version info 7 | - Intercom for Cordova/PhoneGap version: 8 | - iOS/Android OS version: 9 | - iOS/Android Device: 10 | 11 | ## Expected behavior 12 | 13 | ## Actual behavior 14 | 15 | ## Steps to reproduce 16 | 1. 17 | 2. 18 | 3. 19 | 20 | ## Logs -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Example/node_modules 3 | intercom-plugin/node_modules 4 | intercom-cordova.code-workspace 5 | node_modules/* -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Intercom for Cordova/PhoneGap 2 | 3 | ## 14.1.0 (2025-01-28) 4 | 5 | 🚀 Enhancements 6 | * Improved delineation between AI Agents and bots. 7 | * New handover experience from AI Agents to teammates. 8 | * Added Privacy Policy in the conversation screen. 9 | * Special notice now supports multiple languages. 10 | * Intercom SDK now targets Android 15 (API level 35) (Android) 11 | * Added edge-to-edge support (Android) 12 | 13 | ## 14.0.3 (2024-12-11) 14 | 15 | 🐛 Bug Fixes 16 | * Solves a crash in carousels. (iOS) 17 | * Addressed issue where video input wasn’t available in a conversation. (iOS) 18 | * Fixes issue where first part in a conversation would fail to show as failed in the scenario where it didn’t send. (iOS) 19 | * Resolved some layout issues in the conversation screen for users with large font sizes enabled. (iOS) 20 | * Fixed the bug where users were unable to add a phone number in the attribute collector. (Android) 21 | * Fixed a crash caused by `IllegalArgumentException: y must be < bitmap.height()`. (Android) 22 | 23 | ## 14.0.2 (2024-06-25) 24 | 25 | 🐛 Bug Fixes 26 | * Now sets the minimum deployment target in the `plugin.xml` for iOS to avoid collisions with other plugins. 27 | 28 | ## 14.0.1 (2024-06-014) 29 | 30 | 🚀 Enhancements 31 | * It is now possible to send push notifications to the Simulator. (iOS) 32 | 33 | 🐛 Bug Fixes 34 | * Fixed an issue where it was not possible to close modal view that was opened from a Messenger App. (iOS) 35 | * The message composer is now always displayed on the conversation screen when appropriate.(iOS) 36 | * When a conversation is closed, form entry is disabled on the conversation screen. (iOS & Android) 37 | * Made some minor UI bug fixes. (iOS) 38 | * Fixed the issue where push open stats weren’t tracked correctly. (Android) 39 | 40 | ## 14.0.0 (2024-06-05) 41 | 🚀 Enhancements 42 | * Updated Intercom Cordova Plugin to support the latest versions of the core iOS and Android SDKs. 43 | * Updated to the latest versions of `cordova`, `cordova-android` and `cordova-ios`. 44 | * As this is a major release, we have deprecated a number of APIs and added some new ones. The deprecated APIs will continue to work for the next few versions of the plugin, after which they will be removed fully. 45 | 46 | #### Summary of API changes. 47 | | Deprecated API | New API | 48 | | ----------- | ----------- | 49 | | registerIdentifiedUser() | loginUserWithUserAttributes() | 50 | | registerUnidentifiedUser() | loginUnidentifiedUser() | 51 | | reset() | logout() | 52 | | displayMessenger() | present() | 53 | | displayHelpCenter() | present(intercom.Space.HelpCenter) | 54 | | displayMessageComposerWithInitialMessage() | presentMessageComposer(initialMessage) | 55 | | displayMessageComposer() | presentMessageComposer() | 56 | | displayHelpCenterCollections() | presentContent(intercomContent.helpCenterCollectionsWithIds([ids]) | 57 | | displayCarousel() | presentContent(intercomContent.carouselWithCarouselId(carouselId) | 58 | | displayArticle() | presentContent(intercomContent.articleWithArticleId(articleId)) | 59 | | displaySurvey() | presentContent(intercomContent.surveyWithSurveyId(surveyId)) | 60 | | N/A | presentContent(intercomContent.conversationWithConversationId(conversationId)) | 61 | 62 | #### Summary of required versions of libararies and SDKs. 63 | | Name | Required Version | 64 | | ----------- | ----------- | 65 | | cordova | 12.0.0 | 66 | | cordova-android | 13.0.0 | 67 | | cordova-ios | 7.1.0 | 68 | | iOS SDK | 15.0.0 | 69 | | Android SDK | 34 | 70 | 71 | 72 | ## 13.10.0 (2024-04-26) 73 | 🚀 Enhancements 74 | * Added support for iOS 16. 75 | * Added support for Android 13 76 | * Xcode 14 is required to build v13.0.0 77 | 78 | ## 12.1.0 (2022-06-01) 79 | * The Intercom Cordova plugin has been updated to use the latest version of the Intercom's iOS SDK (v12.4.0) and Android SDK (v12.4.1) 80 | * You can now display a Survey programmatically with `intercom.displaySurvey("12345")` 81 | 82 | ## 12.0.0 (2022-03-30) 83 | #### v12.0.0 of the Cordova plugin supports the latest version (12.0.0) of the Intercom mobile SDK. 84 | ##### 🚀 Enhancements 85 | 86 | **In v12.0.0 of the Intercom mobile SDK, we’re introducing Intercom Surveys — beautiful native in-product surveys to bring all your customer communication to one platform!!** 87 | 88 | ![Intercom Surveys Introduction](https://user-images.githubusercontent.com/6392766/159682454-25995724-68f7-4201-a6c2-5b1bffe11ed1.png) 89 | 90 | **📱 New feature: Intercom Surveys** 91 | 92 | 👋🏼 Meet Intercom Surveys - Don’t just ask their opinion, act on it. Now, you can seamlessly capture and act on customer feedback and needs, all within Intercom. Intercom Surveys makes it quick and easy to create and send highly targeted, easily customisable in-product native survey - across web and mobile. 93 | 94 | * Choose the relevant question type from multitude of question types available like rating scales (NPS, emoji, star), multiple-choice, dropdown and more 95 | * Customise the color of your survey’s background and buttons 96 | * Target the right survey to the right audience at the right time 97 | * Save survey responses as user attributes to drive follow up actions 98 | * Add a customisable intro and thank you message 99 | * Decide whether or not users should be able to dismiss the survey 100 | * Encourage further user actions by inserting a call-to-action button in the thank you message with a link (external URL or deep link) 101 | * Leverage email and mobile push as fallback channels if in-product doesn’t get you a response 102 | * Many more ways to customise your survey — show or hide avatar of survey sender, format survey text and insert user or company attributes in text 103 | * Use the power of Intercom platform — A/B testing and control groups, goal tracking, orchestrating surveys as a part of series, analysing and exporting results as CSV 104 | 105 | 👉 You will need to start a 14 day free trial or purchase the Surveys Add-On starting from $49 per month in order to set a survey live 106 | 👉 Upgrade to the latest version of the mobile SDK today to use the feature on mobile. No additional integration work required. 107 | 108 | [Learn more about Intercom Surveys](https://www.intercom.com/surveys) 109 | 110 | https://user-images.githubusercontent.com/3718984/159649798-a255ab7a-df79-4015-875c-399872e6186c.mp4 111 | 112 | https://user-images.githubusercontent.com/6392766/159682983-e13d3080-8025-4f90-9a75-14f41b81a5bc.mp4 113 | 114 | ## 11.0.0 (2022-01-13) 115 | * The Intercom Cordova plugin has been updated to use the latest version of the Intercom iOS (v11.0.0) and Android SDK (v10.6.0) 116 | * The minimum deployment version for iOS is now iOS 13. 117 | * Using Intercom cordova plugin for the Android platform does not require jcenter 118 | 119 | ## 10.2.0 (2021-09-28) 120 | * The Intercom Cordova plugin has been updated to use the latest version of the Intercom iOS (v10.3.0) and Android SDK (v10.2.0) 121 | 122 | Reduce customer inquiries for your team and provide faster resolutions for your customers – without sacrificing a great experience. We’ve redesigned our Messenger with an integrated help center experience that increases customer engagement by up to 3x to help you deliver the best self-serve support. 123 | 124 | ##### Enhancements 125 | * A new article search card on your Messenger’s home screen. 126 | * There are now two conversation cards, just as with our web Messenger; one for existing and one for new conversations. This gives more emphasis to existing conversations, reducing the chance of duplicates being created. 127 | * Optionally require specific customers to attempt to self-serve to answer their question before they can reach out to a teammate. 128 | * Place the article search card at the top of the Messenger home screen to give your self-serve content more prominence. 129 | * Uncover insights and opportunities to optimize your self-serve support by using our updated Articles reporting. 130 | * A number of improvements for accessibility features in the Messenger, with more coming in future updates. 131 | * If you’ve set a custom icon for the Intercom launcher, that icon will now be used in your app as well. 132 | * Support for iOS 15 is also included in this release. 133 | 134 | ## 10.1.1 (2021-09-14) 135 | * Include dependencies needed to make the Android version build 136 | 137 | ## 10.1.0 (2021-08-23) 138 | * The Intercom Cordova plugin has been updated to use the latest version (v10.1.0) of the Intercom iOS and Android SDK 139 | * Updated to cordova-android 10.0.0 140 | 141 | ## 10.0.0 (2021-06-29) 142 | #### v10.0.0 of the Cordova plugin supports the latest version (10.0.1) of the Intercom mobile SDK. 143 | ##### Enhancements 144 | * We have redesigned the Help Center for mobile apps. ✨ 145 | * New UI, optimized specifically for mobile apps and small screens 146 | * Type-ahead search to help users find answers quicker than ever 147 | * Control whether users open up a specific collection of articles, a group of collections, or specific search results 148 | * Localization - with right to left language display 149 | * Accessibility support: screen readers, dynamic font sizes, and keyboard navigation - to support all end users 150 | * New Help Center Data API that enables you to build your own help center UI, enabling a much deeper and custom integration into your app. 151 | ##### Improvements and bug fixes 152 | * Fixed an issue where the special notice message would not display. 153 | * `hideMessenger()` has now been deprecated and removed. Please use `hideIntercom()` instead. This method will hide all Intercom UI in your app. 154 | 155 | ## 9.4.0 (2020-11-17) 156 | * Updated both the Android and iOS SDK to 9.0.0 157 | * On iOS, cocoapods 1.10 is required to install the iOS SDK correctly. 158 | 159 | ## 9.3.0 (2020-11-10) 160 | 161 | * The Intercom Cordova plugin has been updated to use v8.3.0 of the Intercom Android SDK and v8.1.0 of the iOS SDK as the latest version. 162 | * New feature: You can now open an article or Mobile Carousel programmatically in your app. We have added two new methods to our API to enable this, [displayArticle](https://developers.intercom.com/installing-intercom/docs/cordova-phonegap-configuration#section-present-an-article-programmatically) and [displayCarousel](https://developers.intercom.com/installing-intercom/docs/cordova-phonegap-configuration#section-present-a-carousel-programmatically). 163 | * Updated to cordova-ios 6.1.1. 164 | 165 | ## 9.2.1 (2020-09-17) 166 | 167 | * The Intercom Cordova plugin has been updated to use v8.2.0 of the Intercom Android SDK. 168 | * The Intercom Cordova plugin has been updated to use v8.0.0 of the Intercom iOS SDK. 169 | 170 | ## 9.2.0 (2020-09-09) 171 | 172 | * The Intercom Cordova plugin has been updated to use v8.1.0 of the Intercom Android SDK as the latest version. 173 | * Fixed the Gradle [issue](https://community.intercom.com/t/cordova-android-9-and-cordova-intercom-9-1/2235) with enabling push notification 174 | 175 | ## 9.1.1 (2020-08-25) 176 | 177 | * The Intercom Cordova plugin has been updated to use v8.0.0 of the Intercom Android SDK as the latest version. 178 | 179 | ## 9.1.0 (2020-07-20) 180 | 181 | * The Cordova plugin has been updated to be compatible with v7.2.0 of the Android SDK and v9.0.0 of Cordova Android. 182 | * v7.2.0 of the Android SDK now uses [Android X](https://developer.android.com/jetpack/androidx), and includes updates to the Gson and Firebase Messaging libraries it uses. 183 | * In [Cordova Android v9.0.0](https://cordova.apache.org/announcements/2020/06/29/cordova-android-9.0.0.html), the minimum Android API level is now API 22 (Android 5.1). The Cordova plugin's minimum version is now API 22 as well. 184 | 185 | ## 9.0.1 (2020-07-08) 186 | 187 | The Intercom Cordova plugin has been updated to use v7.1.1 of the iOS and Android SDK. We fixed a number of bugs in this release: 188 | 189 | * Android: 190 | * **Fixed:** An issue where buttons on the Messenger conversation card were not fully visible on small devices. 191 | * **Fixed:** An issue where the conversation header wasn’t updates after a teammate reply. 192 | * iOS: 193 | * **Improved:** If your app does not request location permissions, you will no longer have to add a location permission string to your PList when using the Intercom iOS SDK. 194 | 195 | ## 9.0.0 (2020-06-17) 196 | **v9.0.0 of the Cordova plugin supports the latest version (7.1.0) of the Intercom mobile SDK. We’re introducing a fantastic new mobile engagement feature called Mobile Carousels. We’ve also added support for closed conversations, as well as a number of fixes and performance improvements.** 197 | 198 | ### 📱 New Feature: Mobile Carousels 199 | 200 | Bring your best features. We'll bring the spotlight. Use [Mobile Carousels](https://intercom.com/mobile) to connect with app users at every touchpoint—show them around, provide support, and highlight features you know they'll love. 201 | 202 | Mobile Carousels are a multi-screen message designed to feel right at home in your mobile app. 203 | 204 | * Rich multi-screen messages. 205 | * Highly customizable, right inside Intercom. 206 | * Request device permissions like push notifications, camera, location and more. 207 | * Deep link into your app, open URLs, or start conversations in the Intercom Messenger. 208 | * Target the right message to the right audience. 209 | * A/B testing and control groups. 210 | * Goal tracking. 211 | * Schedule your Mobile Carousel with ease. 212 | 213 | Upgrade to the latest version of the plugin and mobile SDK today to use the feature. No additional integration work required. 214 | 215 | ### [Learn more about Mobile Carousels](https://www.intercom.com/mobile-carousels) 216 | 217 | 218 | 219 | ![Carousel - Made for mobile - Red](https://user-images.githubusercontent.com/3185423/84785788-ce315d00-afe3-11ea-9647-01792c698d05.png) 220 | 221 | ![anrdroid_standard](https://user-images.githubusercontent.com/3185423/84802829-0b541a00-aff9-11ea-9e7f-1613e8d7d369.gif) 222 | 223 | ![Carousel - Permissions - iOS - Yellow](https://user-images.githubusercontent.com/3185423/84785834-dee1d300-afe3-11ea-9c66-accbc6a93458.png) 224 | 225 | 226 | ### 📱 Closed Conversations 227 | 228 | The mobile SDK now respects the `prevent replies to closed conversations` setting if you have it enabled. The text composer will be disabled for closed conversations, and your users will be able to start a new conversation if they need to. The UI updates in real time as the conversation takes place. 229 | 230 | ![Closed Conversation](https://user-images.githubusercontent.com/5046761/84785550-8579a400-afe3-11ea-978d-49cba15cf54c.gif) 231 | 232 | 233 | ### 📱 Improvements and bug fixes 234 | 235 | We made a number of performance improvements and squashed a number of bugs in this release. This includes: 236 | 237 | * Android: 238 | * **Improved:** The mobile SDK and its features now initialize and open more quickly. 239 | * **Improved:** More elegant image loading states. 240 | * **Fixed:** An issue where the composer occasionally failed to respect the ‘disable composer for inbound bots’ setting. 241 | * **Fixed:** A crash associated with certain colour customization settings. 242 | * **Fixed:** A java.lang.OutOfMemoryError crash. 243 | * **Fixed:** A ReactionInputView.highlightSelectedReaction > IndexOutOfBoundsException crash. 244 | * **Fixed:** An issue where file extensions were sometimes removed when uploading them. 245 | * **Fixed:** An issue where emoji reactions were sometimes rendered twice. 246 | * **Fixed:** An issue with overlapping text in the ‘Your conversations’ list in the Messenger home. 247 | * **Fixed:** An issue where an outbound message didn’t appear in real-time after changing the device orientation. 248 | * **Fixed:** An issue where custom bot failed to save custom attributes 249 | * **Fixed:** A crash with error java.lang.ArithmeticException divide by zero 250 | * **Removed:** The experimental API is no longer available. 251 | 252 | * iOS: 253 | * **Improved:** The mobile SDK and its features now initialize and open more quickly. 254 | * **Improved:** More elegant image loading states. 255 | * **Improved:** Added support for pointers in iPadOS 13.4 and up. 256 | * **Improved:** Added support for Provisional Push Notifications 257 | * **Fixed:** An issue where Intercom was not relinquishing keyWindow status, causing problems with external keyboards and text input fields. 258 | * **Fixed:** An issue where the header background colour for articles was incorrect. 259 | * **Fixed:** A crash in iOS 13 when tapping close button after sending a reply to a conversation. 260 | * **Fixed:** A crash when exiting conversation before Operator has responded. 261 | * **Fixed:** An issue where conversations were marked as read when the app was in the background. 262 | * **Fixed:** An issue where some images were causing apps to crash during the upload process. 263 | 264 | ## 8.0.0 (2019-11-04) 265 | 266 | * Upgraded to version 6.0.0 of the iOS and Android SDK. 267 | * iOS 10 is now the minimum version of iOS that is supported by the Intercom iOS SDK. 268 | * We have deprecated support for iOS 8 & 9. 269 | * Android API level 21 (v5 - Lollipop) is now the minimum version of Android that is supported by the Intercom Android SDK. 270 | * If your app still support API levels before 21 you'll need to bump minSdkVersion to 21 in order to use version 6+ of our SDK. 271 | 272 | ## 7.1.1 (2019-09-05) 273 | 274 | * * The Intercom Cordova plugin has been updated to use v5.4.1 of the Intercom Android SDK as the latest version. This is because v5.5.0 of the Intercom Android SDK targets Android 10, which is currently unsupported by Cordova. 275 | 276 | ## 7.1.0 (2019-07-17) 277 | 278 | * Updated to cordova-android 8.0.0 and cordova-ios 5.0.0 279 | * Removed GCM as [Google has removed GCM](https://developers.google.com/cloud-messaging/faq) 280 | * Updated Firebase version 281 | * Updated our Example app to use the newer versions of Cordova 282 | * Now using the latest versions of the Intercom [Android SDK](https://github.com/intercom/intercom-android/releases) and [iOS SDK](https://github.com/intercom/intercom-android/releases) with support for Custom Bots! 283 | 284 | ## 7.0.0 (2019-06-20) 285 | 286 | * Cordova 9 support 287 | 288 | ## 6.2.0 (2018-12-18) 289 | 290 | * Support sending a push token to Intercom manually with the addition of the method `sendPushTokenToIntercom` 291 | 292 | ## 6.1.0 (2018-07-20) 293 | 294 | **Enable mobile users to help themselves with the new mobile SDK for iOS and Android 🎉 😃** 295 | 296 | The new Intercom mobile SDK brings the Messenger Home to your mobile applications. This means you can add messenger apps that allow your users to self-serve instead of starting a conversation. Users can now quickly access relevant help articles, review pinned content, and view product status in real time – all from the messenger home screen. 297 | 298 | ![android-release-screens](https://user-images.githubusercontent.com/2615468/42951497-316de29a-8b6e-11e8-8ed8-a0a3a93f6f4f.png) 299 | 300 | ![ios-release-screens](https://user-images.githubusercontent.com/3185423/42937925-71ab4b5c-8b48-11e8-913b-88d48c9b82f3.png) 301 | 302 | **API changes** 303 | 304 | * `displayConversationsList` - Use `displayMessenger` instead. 305 | 306 | These deprecated methods will still work, but will be removed in a future release. 307 | 308 | ## 6.0.0 (2018-06-12) 309 | 310 | The Business Messenger reimagined. 311 | 312 | **Messenger apps** 313 | * Complete actions beyond chat in the Messenger seamlessly with a growing library of apps. Messenger apps are being rolled out to all customers over the next 2 weeks. 314 | 315 | **Extendable platform** 316 | * Create your own Messenger apps to suit your unique workflows – and enable entirely new ones. 317 | 318 | **Updated Design** 319 | * Updated visual design with new wallpapers and expanded color settings. 320 | 321 | **Messenger settings** 322 | * New wallpapers to customize your profile. 323 | * Set a background color for your profile and an action color for cards and chat bubbles. 324 | * Support light theme colors in your messenger. 325 | 326 | **Help Center** 327 | * Added the method `displayHelpCenter()`. Calling this method in your app displays your Articles Help Center. Learn more about Articles [here](https://www.intercom.com/articles/features). 328 | 329 | ![5-0-0-android-release-screens](https://user-images.githubusercontent.com/2615468/39157445-befb7196-4752-11e8-8a33-57636975ecec.png) 330 | 331 | ![5-0-0-ios-release-screens](https://user-images.githubusercontent.com/3185423/39155559-6a3f239e-474a-11e8-8eb0-fdb0c69d288f.jpg) 332 | 333 | ## 5.1.1 (2018-02-26) 334 | 335 | * Include FCM libraries when building without build plugin [#257](https://github.com/intercom/intercom-cordova/pull/257) 336 | 337 | ## 5.1.0 (2018-02-26) 338 | 339 | * Created fork of `phonegap-plugin-push` to allow it to work with this plugin: https://github.com/intercom/phonegap-plugin-push 340 | * Allow FCM notifications without applying build plugin [#253](https://github.com/intercom/intercom-cordova/pull/253) 341 | * Update recommended build tool & library versions [#252](https://github.com/intercom/intercom-cordova/pull/252) 342 | * Remove broken support for multiple GCM libraries [#251](https://github.com/intercom/intercom-cordova/pull/251) 343 | * Fix GCM sender ID reading [#250](https://github.com/intercom/intercom-cordova/pull/250) 344 | * Change hook for checkForUpdate to be after_prepare [#249](https://github.com/intercom/intercom-cordova/pull/249) 345 | 346 | ## 5.0.2 (2018-02-12) 347 | 348 | * Fix issue with Intercom pod not being updated / installed when GitHub response was not 200 OK: [#246](https://github.com/intercom/intercom-cordova/pull/246) 349 | 350 | ## 5.0.1 (2018-01-23) 351 | 352 | * Removes dependency on `PackageManager.GET_META_DATA`, which Cordova does not appear to generate any longer for new projects: [#239](https://github.com/intercom/intercom-cordova/issues/239). 353 | 354 | ## 5.0.0 (2018-01-22) 355 | 356 | * Supports `cordova-android` 7.0.0, the default Android build version when using `cordova-cli` 8.0.0, though it may also be specified on earlier versions (tested on [Cordova 7.1.0](https://github.com/apache/cordova-cli/releases/tag/7.1.0)) 357 | 358 | * Deprecates GCM as a push type in favor of FCM. This includes removing the ability to specify a GCM/FCM sender id directly from config.xml. To use push on Android, adding your google-services.json to the root of your project is now required. 359 | 360 | * Per the [`cordova-android` 7.0.0 release notes](cordova.apache.org/announcements/2017/12/04/cordova-android-7.0.0.html), the minimum Android API version supported is now API Level 19. 361 | 362 | --- 363 | 364 | Update guide: 365 | 366 | 1. If you have not already done so, update your `cordova-cli`: 367 | ``` 368 | npm install -g cordova 369 | cd my_project 370 | cordova platform remove android 371 | cordova platform add android@7.0.0 372 | ``` 373 | 2. Update `plugin-cordova-intercom`: 374 | ``` 375 | cordova plugin remove cordova-plugin-intercom 376 | cordova plugin add cordova-plugin-intercom 377 | ``` 378 | 3. Ensure your config.xml specifies an android-minSdkVersion at or above 19: 379 | * `` 380 | 4. To use push on Android: 381 | * Ensure you've added `` to your config.xml 382 | * Copy your FCM `google-services.json` file to the root directory of your project. 383 | 384 | _NB: The above steps may not be exhaustive and are dependent on your app and system Cordova configuration_ 385 | 386 | ## 4.1.2 (2017-11-16) 387 | 388 | * Further fixes to issue with diagnostic messages on Android: [#219](https://github.com/intercom/intercom-cordova/issues/219). 389 | 390 | ## 4.1.1 (2017-11-15) 391 | 392 | * Fixed issue with diagnostic messages on Android: [#219](https://github.com/intercom/intercom-cordova/issues/219). 393 | 394 | ## 4.1.0 (2017-11-02) 395 | 396 | * Updated Intercom for Android to 4.1.x 397 | * Updated Intercom for iOS to 4.1.x 398 | * Added `intercom.logout()`. 399 | * Added diagnostic messages for Android build errors. 400 | 401 | ## 4.0.0 (2017-08-29) 402 | 403 | * Updated Intercom for Android to 4.0.1 404 | * Updated Intercom for iOS to 4.0.1 405 | * Removed deprecated method `intercom.setSecureMode(hmac, data)`. 406 | * Added support for iOS 11. 407 | * Added support for Android Oreo. 408 | * Updated GCM & FCM to version 11. 409 | 410 | ## 3.2.2 (2017-05-17) 411 | 412 | * Prevent unsafe versions of the Support Library being used to fix [#182](https://github.com/intercom/intercom-cordova/issues/182). 413 | 414 | ## 3.2.1 (2017-05-03) 415 | 416 | * Fixed build error reported in [#180](https://github.com/intercom/intercom-cordova/issues/180). 417 | 418 | ## 3.2.0 (2017-04-21) 419 | 420 | * Added a new method to the API `intercom.setUserHash(userHash)` to support Identity Verification. This method replaces `intercom.setSecureMode(hmac, data)` which was used for our previous security feature Secure Mode. 421 | * Updated Intercom for Android to 3.2.x. 422 | * Updated Intercom for iOS to 3.2.x. 423 | 424 | ## 3.1.3 (2017-04-05) 425 | 426 | * Added hook to ensure the local CocoaPods specs repo is up to date when installing the plugin (see [#170](https://github.com/intercom/intercom-cordova/pull/170)). 427 | 428 | ## 3.1.2 (2017-03-31) 429 | 430 | * Fixed compatibility with other Android GCM providers (details are outlined in [#166](https://github.com/intercom/intercom-cordova/pull/166)). It is no longer necessary to use a fork of `phonegap-plugin-push`. 431 | * Added hook to automatically update Intercom for iOS via CocoaPods (see [#168](https://github.com/intercom/intercom-cordova/pull/168)). 432 | 433 | ## 3.1.1 (2017-03-16) 434 | 435 | * Removed reliance on hooks for Android FCM support. Gradle is now used for the whole process. 436 | * Improved iOS interoperability with `phonegap-plugin-push` (Fixes [#154](https://github.com/intercom/intercom-cordova/issues/154)). 437 | * Automatically add `remote-notification` background mode to the app's `Info.plist` on iOS. 438 | * Updated minimum Intercom for iOS version to [3.1.2](https://github.com/intercom/intercom-ios/releases/tag/3.1.2). 439 | 440 | ## 3.1.0 (2017-03-10) 441 | 442 | * Updated Intercom for Android to [3.1.x](https://github.com/intercom/intercom-android/releases/). 443 | * FCM push notifications for Android are now supported. This can be configured by specifying `intercom-android-push-type` in your `config.xml`. 444 | * Updated Intercom for iOS to [3.1.x](https://github.com/intercom/intercom-ios/releases/). 445 | * Intercom for iOS is now installed via CocoaPods, so updates can be received automatically. 446 | 447 | ## 3.0.26 (2016-01-25) 448 | 449 | * Updated Intercom for Android to [3.0.20](https://github.com/intercom/intercom-android/releases/tag/3.0.20). 450 | * Updated Intercom for iOS to [3.0.24](https://github.com/intercom/intercom-android/releases/tag/3.0.24). 451 | 452 | ## 3.0.25 (2016-01-20) 453 | 454 | * Updated Intercom for Android to [3.0.19](https://github.com/intercom/intercom-android/releases/tag/3.0.19). 455 | * Updated Intercom for iOS to [3.0.23](https://github.com/intercom/intercom-android/releases/tag/3.0.23). 456 | 457 | ## 3.0.24 (2016-01-16) 458 | 459 | * Updated Intercom for Android to [3.0.18](https://github.com/intercom/intercom-android/releases/tag/3.0.18). 460 | 461 | ## 3.0.23 (2016-12-22) 462 | 463 | * Updated Intercom to provide support for Ionic 2. 464 | 465 | ## 3.0.22 (2016-12-19) 466 | 467 | * Updated Intercom for iOS to [3.0.22](https://github.com/intercom/intercom-android/releases/tag/3.0.22). 468 | * Updated Intercom for Android to [3.0.17](https://github.com/intercom/intercom-android/releases/tag/3.0.17). 469 | 470 | ## 3.0.21 (2016-12-14) 471 | 472 | * Updated Intercom for Android to [3.0.16](https://github.com/intercom/intercom-android/releases/tag/3.0.16). 473 | 474 | ## 3.0.20 (2016-12-06) 475 | 476 | * Now supports Intercom Educate. Learn more [here](https://www.intercom.com/customer-support-software/knowledge-base). 477 | * Updated Intercom for iOS to [3.0.21](https://github.com/intercom/intercom-android/releases/tag/3.0.21). 478 | * Updated Intercom for Android to [3.0.15](https://github.com/intercom/intercom-android/releases/tag/3.0.15). 479 | 480 | ## 3.0.19 (2016-11-21) 481 | 482 | * Improved initialization process for Android. 483 | 484 | ## 3.0.18 (2016-11-18) 485 | 486 | * Updated Intercom for iOS to [3.0.19](https://github.com/intercom/intercom-android/releases/tag/3.0.19). 487 | * Updated Intercom for Android to [3.0.13](https://github.com/intercom/intercom-android/releases/tag/3.0.13). 488 | 489 | ## 3.0.17 (2016-11-10) 490 | 491 | * Updated Intercom for Android to [3.0.12](https://github.com/intercom/intercom-android/releases/tag/3.0.12). 492 | * Added NSPhotoLibraryUsageDescription to Info.plist for iOS 493 | 494 | ## 3.0.16 (2016-11-07) 495 | 496 | * Updated Intercom for Android to [3.0.11](https://github.com/intercom/intercom-android/releases/tag/3.0.11). 497 | * Updated Intercom for iOS to [3.0.18](https://github.com/intercom/intercom-ios/releases/tag/3.0.18). 498 | 499 | ## 3.0.15 (2016-10-19) 500 | 501 | * Updated Intercom for iOS to [3.0.17](https://github.com/intercom/intercom-ios/releases/tag/3.0.17). 502 | 503 | ## 3.0.14 (2016-10-18) 504 | 505 | * Updated Intercom for iOS to [3.0.16](https://github.com/intercom/intercom-ios/releases/tag/3.0.16). 506 | 507 | ## 3.0.13 (2016-10-12) 508 | 509 | * Re-publish to npm to work around registry issue. 510 | 511 | ## 3.0.12 (2016-10-10) 512 | 513 | * Added a new method `displayMessageComposerWithInitialMessage` which opens up the message composer and takes in a string to pre-populate the message composer with. Example usage `intercom.displayMessageComposerWithInitialMessage("Question asked from the FAQ page: ");` 514 | * Updated Intercom for Android to [3.0.10](https://github.com/intercom/intercom-android/releases/tag/3.0.10). 515 | * Updated Intercom for iOS to [3.0.13](https://github.com/intercom/intercom-ios/releases/tag/3.0.13). 516 | 517 | ## 3.0.11 (2016-09-16) 518 | 519 | * Updated Intercom for Android to [3.0.9](https://github.com/intercom/intercom-android/releases/tag/3.0.9). 520 | * Updated Intercom for iOS to [3.0.12](https://github.com/intercom/intercom-ios/releases/tag/3.0.12). 521 | 522 | ## 3.0.10 (2016-09-09) 523 | 524 | * Updated Intercom for Android to [3.0.7](https://github.com/intercom/intercom-android/releases/tag/3.0.7). 525 | * Updated Intercom for iOS to [3.0.11](https://github.com/intercom/intercom-ios/releases/tag/3.0.11). 526 | 527 | ## 3.0.9 (2016-08-29) 528 | 529 | * Updated Intercom for Android to [3.0.4](https://github.com/intercom/intercom-android/releases/tag/3.0.4). 530 | 531 | ## 3.0.8 (2016-08-19) 532 | 533 | * Fixed [#73](https://github.com/intercom/intercom-cordova/issues/70). 534 | 535 | ## 3.0.7 (2016-08-16) 536 | 537 | * Fixed [#70](https://github.com/intercom/intercom-cordova/issues/70). 538 | * Fixed [#71](https://github.com/intercom/intercom-cordova/issues/71). 539 | * Updated Intercom for Android to [3.0.3](https://github.com/intercom/intercom-android/releases/tag/3.0.3). 540 | * Updated Intercom for iOS to [3.0.10](https://github.com/intercom/intercom-ios/releases/tag/3.0.10). 541 | 542 | ## 3.0.6 (2016-08-10) 543 | 544 | * Fixed [#67](https://github.com/intercom/intercom-cordova/issues/66). 545 | * Added `Photos.framework` to stop iOS build error. 546 | 547 | ## 3.0.5 (2016-08-05) 548 | 549 | * Updated Intercom for iOS to [3.0.8](https://github.com/intercom/intercom-ios/releases/tag/3.0.8). 550 | 551 | # 3.0.4 (2016-08-03) 552 | 553 | * Updated Intercom for iOS to [3.0.7](https://github.com/intercom/intercom-ios/releases/tag/3.0.7). 554 | * Updated iOS configuration in `plugin.xml` for compatibility with older versions of Cordova (As reported in [#65](https://github.com/intercom/intercom-cordova/issues/65) & [#66](https://github.com/intercom/intercom-cordova/issues/66)). 555 | 556 | # 3.0.3 (2016-07-29) 557 | 558 | * Updated Intercom for iOS to [3.0.4](https://github.com/intercom/intercom-ios/releases/tag/3.0.4). 559 | * Fixed [#64](https://github.com/intercom/intercom-cordova/issues/64). 560 | * Changed minimum Cordova version to 4.0.0. 561 | 562 | # 3.0.2 (2016-07-27) 563 | 564 | * Fixed [#63](https://github.com/intercom/intercom-cordova/issues/63). 565 | 566 | # 3.0.1 (2016-07-27) 567 | 568 | * Fixed Android build error. 569 | 570 | # 3.0.0 (2016-07-26) 571 | 572 | Where is 2.x? We're skipping it. We did this to align the Cordova plugin with our iOS, Android and web counter parts. 573 | 574 | Our new Messenger is out of beta! 🎉 You can read all about the updated design and new functionality [here](https://www.intercom.io/in-app-messaging). 575 | 576 | * Updated Intercom for iOS to [3.0.3](https://github.com/intercom/intercom-ios/releases/tag/3.0.3). 577 | * Updated Intercom for Android to [3.0.2](https://github.com/intercom/intercom-android/releases/tag/3.0.2). 578 | 579 | Added the following methods: 580 | * `intercom.displayMessenger()` 581 | * `intercom.setLauncherVisibility(visibility)` 582 | * `intercom.setInAppMessageVisibility(visibility)` 583 | * `intercom.unreadConversationCount()` 584 | 585 | Removed these methods: 586 | * `intercom.setVisibility(visibility)` 587 | * `intercom.setupGCM()` 588 | * `intercom.openGCMMessage()` 589 | * `intercom.setupAPN(token)` 590 | * `intercom.setPreviewPosition(position)` 591 | * `intercom.setPreviewPadding()` 592 | 593 | # 1.1.7 (2016-06-02) 594 | 595 | * Fixed Android crash reported in [#55](https://github.com/intercom/intercom-cordova/issues/55). 596 | 597 | # 1.1.6 (2016-05-25) 598 | 599 | * Updated Intercom for iOS to [2.3.21](https://github.com/intercom/intercom-ios/releases/tag/2.3.21). 600 | 601 | # 1.1.5 (2016-04-11) 602 | 603 | * Fixed Cordova CLI 6.1.1 compatibility. Fixes [#48](https://github.com/intercom/intercom-cordova/issues/48). 604 | * Updated Intercom for iOS to [2.3.19](https://github.com/intercom/intercom-ios/releases/tag/2.3.19). 605 | 606 | ## 1.1.4 (2016-01-11) 607 | 608 | * Updated Google Play Services for compatibility with other plugins. Fixes [#31](https://github.com/intercom/intercom-cordova/issues/31). 609 | 610 | ## 1.1.3 (2015-10-08) 611 | 612 | * Updated Intercom for iOS to [2.3.18](https://github.com/intercom/intercom-ios/releases/tag/2.3.18). 613 | * Updated Intercom for Android to [1.1.+](https://github.com/intercom/intercom-android/releases/). 614 | 615 | ## 1.1.2 (2015-10-08) 616 | 617 | * Updated Intercom for iOS to [2.3.11](https://github.com/intercom/intercom-ios/releases/tag/2.3.11). 618 | 619 | ## 1.1.1 (2015-10-01) 620 | 621 | * Updated Intercom for iOS to [2.3.10](https://github.com/intercom/intercom-ios/releases/tag/2.3.10). 622 | * Updated Intercom for Android to [1.1.7](https://github.com/intercom/intercom-android/blob/master/CHANGELOG.md). 623 | * Improved handling of Android dependencies to reduce `Multiple dex files` errors. 624 | 625 | ## 1.1.0 (2015-09-21) 626 | 627 | * Updated Intercom for iOS to [2.3.5](https://github.com/intercom/intercom-ios/releases/tag/2.3.5). 628 | * Updated Intercom for Android to [1.1.4](https://github.com/intercom/intercom-android/blob/master/CHANGELOG.md). 629 | * App ID and API keys are now configurable in your `config.xml` (fixes https://github.com/intercom/intercom-cordova/issues/1). 630 | 631 | ## 1.0.9 (2015-09-11) 632 | 633 | * Updated Intercom for iOS to [2.3.4](https://github.com/intercom/intercom-ios/releases/tag/2.3.4). 634 | * Fixed https://github.com/intercom/intercom-cordova/issues/20. 635 | 636 | ## 1.0.8 (2015-08-18) 637 | 638 | * Updated Intercom for iOS to [2.3.3](https://github.com/intercom/intercom-ios/releases/tag/2.3.3). 639 | 640 | ## 1.0.7 (2015-08-05) 641 | 642 | * Updated Intercom for iOS to [2.3.2](https://github.com/intercom/intercom-ios/releases/tag/2.3.2). 643 | 644 | ## 1.0.6 (2015-07-28) 645 | 646 | * Updated Intercom for Android to [1.1.3](https://github.com/intercom/intercom-android/blob/master/CHANGELOG.md). 647 | 648 | ## 1.0.5 (2015-07-20) 649 | 650 | * Updated Intercom for iOS to [2.3.1](https://github.com/intercom/intercom-ios/blob/master/CHANGES) and updated Intercom for Android to [1.1.2](https://github.com/intercom/intercom-android/blob/master/CHANGELOG.md). 651 | * The plugin is now available through npm. 652 | 653 | ## 1.0.2 (2015-07-01) 654 | 655 | * Updated Intercom for iOS to [2.3.0](https://github.com/intercom/intercom-ios/blob/master/CHANGES) and updated Intercom for Android to [1.1.1](https://github.com/intercom/intercom-android/blob/master/CHANGELOG.md). 656 | * Fixed https://github.com/intercom/intercom-cordova/issues/5 and https://github.com/intercom/intercom-cordova/issues/7 657 | 658 | ## 1.0.1 (2015-06-05) 659 | 660 | * Improved push notification handling by introducing much simpler `intercom.registerForPush(senderId)`. 661 | * Updated Intercom for iOS to 2.2.4 and updated Intercom for Android to 1.0.3. 662 | 663 | ## 1.0.0 (2015-05-25) 664 | 665 | * Initial release of the Intercom plugin for Cordova and PhoneGap. 666 | -------------------------------------------------------------------------------- /Example/.gitignore: -------------------------------------------------------------------------------- 1 | platforms/ 2 | plugins/ 3 | .DS_Store -------------------------------------------------------------------------------- /Example/.ruby-version: -------------------------------------------------------------------------------- 1 | 3.3.0 2 | -------------------------------------------------------------------------------- /Example/README.md: -------------------------------------------------------------------------------- 1 | # Example Cordova app 2 | 3 | This is a simple Cordova app with an Intercom integration. 4 | 5 | ## Installing the Cordova CLI 6 | 7 | To install Cordova, run the following from your command line: 8 | 9 | ``` 10 | npm install -g cordova 11 | npm install -g ios-sim 12 | ``` 13 | 14 | ## Configuration 15 | 16 | Before you run your app, you'll need to add your Intercom **AppID** and **API Key** to `config.xml` for both Android and/or iOS. 17 | ```xml 18 | 19 | 20 | 21 | ``` 22 | 23 | If you want to enable Android FCM push notifications copy your `google-services.json` file into the `Example/` folder add this line to `config.xml`: 24 | ```xml 25 | 26 | ``` 27 | 28 | ## Running the app 29 | 30 | To get started, add your platform(s) of choice: 31 | 32 | ``` 33 | cordova platform add ios 34 | cordova platform add android 35 | ``` 36 | 37 | Now you can install the Intercom plugin: 38 | 39 | ``` 40 | cordova plugin add cordova-plugin-intercom 41 | ``` 42 | You can now run your app with the following command: 43 | #### iOS 44 | ``` 45 | cordova run ios 46 | ``` 47 | ### Android 48 | ``` 49 | cordova run android 50 | ``` 51 | -------------------------------------------------------------------------------- /Example/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Intercom Cordova 4 | 5 | An Intercom sample application for Cordova. 6 | 7 | 8 | Brian Boyle 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 60 | 63 | 64 | -------------------------------------------------------------------------------- /Example/hooks/iosDeploymentTarget.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | module.exports = function (context) { 5 | const platformRoot = path.join(context.opts.projectRoot, 'platforms/ios'); 6 | const projectPbxproj = path.join(platformRoot, 'CordovaLib', 'CordovaLib.xcodeproj', 'project.pbxproj'); 7 | 8 | if (fs.existsSync(projectPbxproj)) { 9 | let contents = fs.readFileSync(projectPbxproj, 'utf8'); 10 | 11 | // Update deployment target 12 | contents = contents.replace(/IPHONEOS_DEPLOYMENT_TARGET = 11\.0;/g, 'IPHONEOS_DEPLOYMENT_TARGET = 15.0;'); 13 | 14 | fs.writeFileSync(projectPbxproj, contents, 'utf8'); 15 | console.log('Updated CordovaLib deployment target to iOS 15.0'); 16 | } 17 | }; -------------------------------------------------------------------------------- /Example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "io.intercom.cordova.sample", 3 | "version": "0.0.1", 4 | "displayName": "Intercom Cordova", 5 | "cordova": { 6 | "platforms": [ 7 | "ios", 8 | "android" 9 | ], 10 | "plugins": { 11 | "cordova-plugin-intercom": {} 12 | } 13 | }, 14 | "devDependencies": { 15 | "cordova-ios": "^7.1.1", 16 | "cordova-plugin-intercom": "file:../intercom-plugin" 17 | }, 18 | "dependencies": { 19 | "cordova-android": "13.0.0" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/www/css/index.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | * { 20 | -webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */ 21 | outline: none; 22 | } 23 | 24 | body { 25 | -webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */ 26 | -webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */ 27 | -webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */ 28 | font-family:'HelveticaNeue-Light', 'HelveticaNeue', Helvetica, Arial, sans-serif; 29 | font-size:12px; 30 | height:100%; 31 | margin:0px; 32 | padding:0px; 33 | text-transform:uppercase; 34 | width:100%; 35 | overflow: scroll; 36 | } 37 | 38 | /* Portrait layout (default) */ 39 | .app { 40 | /*background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */*/ 41 | position:absolute; /* position in the center of the screen */ 42 | left:50%; 43 | top:50%; 44 | height:50px; /* text area height */ 45 | width:225px; /* text area width */ 46 | text-align:center; 47 | padding:50px 0px 0px 0px; /* image height is 200px (bottom 20px are overlapped with text) */ 48 | margin: 0 auto; /* offset vertical: half of image height and text area height */ 49 | } 50 | 51 | /* Landscape layout (with min-width) */ 52 | @media screen and (min-aspect-ratio: 1/1) and (min-width:400px) { 53 | .app { 54 | padding:75px 0px 75px 170px; /* padding-top + padding-bottom + text area = image height */ 55 | margin:-90px 0px 0px -198px; /* offset vertical: half of image height */ 56 | /* offset horizontal: half of image width and text area width */ 57 | } 58 | } 59 | 60 | .logo { 61 | margin-top: 75px; 62 | margin-bottom: 20px; 63 | } 64 | 65 | button { 66 | background-color: #FFFFFF; 67 | border: none; 68 | color: #00A3FF; 69 | text-align: center; 70 | text-decoration: none; 71 | display: inline-block; 72 | font-size: 20px; 73 | } 74 | 75 | p { 76 | font-size: 20px; 77 | } 78 | @keyframes fade { 79 | from { opacity: 1.0; } 80 | 50% { opacity: 0.4; } 81 | to { opacity: 1.0; } 82 | } 83 | 84 | @-webkit-keyframes fade { 85 | from { opacity: 1.0; } 86 | 50% { opacity: 0.4; } 87 | to { opacity: 1.0; } 88 | } 89 | -------------------------------------------------------------------------------- /Example/www/img/Intercom-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/Intercom-logo.png -------------------------------------------------------------------------------- /Example/www/img/Intercom_logo-github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/Intercom_logo-github.png -------------------------------------------------------------------------------- /Example/www/img/android/hdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/android/hdpi.png -------------------------------------------------------------------------------- /Example/www/img/android/mdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/android/mdpi.png -------------------------------------------------------------------------------- /Example/www/img/android/xhdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/android/xhdpi.png -------------------------------------------------------------------------------- /Example/www/img/android/xxhdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/android/xxhdpi.png -------------------------------------------------------------------------------- /Example/www/img/android/xxxhdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/android/xxxhdpi.png -------------------------------------------------------------------------------- /Example/www/img/icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-29.png -------------------------------------------------------------------------------- /Example/www/img/icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-29@2x.png -------------------------------------------------------------------------------- /Example/www/img/icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-29@3x.png -------------------------------------------------------------------------------- /Example/www/img/icon-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-30.png -------------------------------------------------------------------------------- /Example/www/img/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-40.png -------------------------------------------------------------------------------- /Example/www/img/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-40@2x.png -------------------------------------------------------------------------------- /Example/www/img/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-40@3x.png -------------------------------------------------------------------------------- /Example/www/img/icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-60.png -------------------------------------------------------------------------------- /Example/www/img/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-60@2x.png -------------------------------------------------------------------------------- /Example/www/img/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-60@3x.png -------------------------------------------------------------------------------- /Example/www/img/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-76.png -------------------------------------------------------------------------------- /Example/www/img/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-76@2x.png -------------------------------------------------------------------------------- /Example/www/img/icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/icon-83.5@2x.png -------------------------------------------------------------------------------- /Example/www/img/launch/Default@2x~universal~anyany.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/launch/Default@2x~universal~anyany.png -------------------------------------------------------------------------------- /Example/www/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intercom/intercom-cordova/a9e3ea75680444b0adc80727f915508e305e2523/Example/www/img/logo.png -------------------------------------------------------------------------------- /Example/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Intercom Cordova Sample 8 | 9 | 10 | 11 |
12 | 13 | 14 |

15 |

16 |

17 |

18 |

19 |

20 |

21 |

22 |

23 |

Help Center Data API

24 |

25 |

26 |

27 |

28 |

29 |
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Example/www/js/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | var app = { 20 | // Application Constructor 21 | initialize: function() { 22 | this.bindEvents(); 23 | }, 24 | // Bind Event Listeners 25 | // 26 | // Bind any events that are required on startup. Common events are: 27 | // 'load', 'deviceready', 'offline', and 'online'. 28 | bindEvents: function() { 29 | document.addEventListener('deviceready', this.onDeviceReady, false); 30 | }, 31 | // deviceready Event Handler 32 | // 33 | // The scope of 'this' is the event. In order to call the 'receivedEvent' 34 | // function, we must explicitly call 'app.receivedEvent(...);' 35 | onDeviceReady: function() { 36 | app.receivedEvent('deviceready'); 37 | intercom.setLauncherVisibility('VISIBLE'); 38 | intercom.setInAppMessageVisibility('VISIBLE'); 39 | 40 | intercom.unreadConversationCount(function(result) { 41 | console.log('Unread conversations: ' + result); 42 | }); 43 | 44 | document.getElementById("login-btn").addEventListener("click", function(){ 45 | app.login(); 46 | }, false); 47 | 48 | document.getElementById("logout-btn").addEventListener("click", function(){ 49 | intercom.logout(); 50 | var storage = window.localStorage; 51 | storage.removeItem("email"); 52 | app.configureViewForLoggedOutUser(); 53 | console.log('Logout successful'); 54 | }, false); 55 | 56 | document.getElementById("open-intercom-btn").addEventListener("click", function(){ 57 | intercom.present(); 58 | }, false); 59 | 60 | document.getElementById("open-help-center-btn").addEventListener("click", function(){ 61 | intercom.presentSpace(intercom.space.HelpCenter); 62 | }, false); 63 | 64 | document.getElementById("open-help-center-filtered-btn").addEventListener("click", function(){ 65 | // Replace this with your own collections 66 | var collectionIds = ["COLLECTION_ID1", "COLLECTION_ID2"]; 67 | var helpCenterCollections = intercomContent.helpCenterCollectionsWithIds(collectionIds) 68 | intercom.presentContent(helpCenterCollections) 69 | }, false); 70 | 71 | document.getElementById("help-center-data-api-fetch-btn").addEventListener("click", function(){ 72 | var onSuccess = function(data) { 73 | console.log('Successfully fetched collections : ' + data); 74 | } 75 | var onError = function(code) { 76 | console.log('Failed to fetch collections with code :' + code); 77 | } 78 | intercom.fetchHelpCenterCollections(onSuccess, onError); 79 | }, false); 80 | 81 | document.getElementById("help-center-data-api-fetch-content-btn").addEventListener("click", function(){ 82 | // Add your collection Id here 83 | var collectionId = "COLLECTION_ID" 84 | var onSuccess = function(data) { 85 | console.log('Successfully fetched collection content : ' + data); 86 | } 87 | var onError = function(code) { 88 | console.log('Failed to fetch collection content with code :' + code); 89 | } 90 | intercom.fetchHelpCenterCollection(collectionId, onSuccess, onError); 91 | }, false); 92 | 93 | document.getElementById("help-center-data-api-search-btn").addEventListener("click", function(){ 94 | // Add your search term here 95 | var searchTerm = "SEARCH_TERM" 96 | var onSuccess = function(data) { 97 | console.log('Successfully searched help center : ' + data); 98 | } 99 | var onError = function(code) { 100 | console.log('Failed to search help center with code :' + code); 101 | } 102 | intercom.searchHelpCenter(searchTerm, onSuccess, onError); 103 | }, false); 104 | 105 | document.getElementById("display-carousel-btn").addEventListener("click", function(){ 106 | // Replace this with your own carousel Id 107 | var carousel = intercomContent.carouselWithCarouselId('CAROUSEL_ID') 108 | intercom.presentContent(carousel) 109 | }, false); 110 | 111 | document.getElementById("display-article-btn").addEventListener("click", function(){ 112 | // Replace this with your own article Id 113 | var article = intercomContent.articleWithArticleId('ARTICLE_ID') 114 | intercom.presentContent(article); 115 | }, false); 116 | 117 | document.getElementById("display-survey-btn").addEventListener("click", function(){ 118 | // Replace this with your own survey Id 119 | var survey = intercomContent.surveyWithSurveyId('SURVEY_ID') 120 | intercom.presentContent(survey); 121 | }, false); 122 | 123 | document.getElementById("display-conversation-btn").addEventListener("click", function(){ 124 | // Replace this with your own conversation Id 125 | var conversation = intercomContent.conversationWithConversationId('CONVERSATION_ID') 126 | intercom.presentContent(conversation); 127 | }, false); 128 | 129 | document.getElementById("is-user-logged-in-btn").addEventListener("click", function(){ 130 | var onSuccess = function(data) { 131 | console.log('User logged in status: ' + data); 132 | } 133 | var onError = function(code) { 134 | console.log('Failed to fetch logged in status :' + code); 135 | } 136 | intercom.isUserLoggedIn(onSuccess, onError); 137 | }, false); 138 | 139 | document.getElementById("fetch-logged-in-attributes-btn").addEventListener("click", function(){ 140 | var onSuccess = function(data) { 141 | console.log('Successfully fetched logged in attributes: ' + data); 142 | } 143 | var onError = function(code) { 144 | console.log('Failed to fetch logged in attributes: ' + code); 145 | } 146 | intercom.fetchLoggedInUserAttributes(onSuccess, onError); 147 | }, false); 148 | }, 149 | // Update DOM on a Received Event 150 | receivedEvent: function(id) { 151 | 152 | var storage = window.localStorage; 153 | if (storage.getItem("email")) { 154 | app.configureViewForLoggedInUser(); 155 | } else { 156 | app.configureViewForLoggedOutUser(); 157 | } 158 | }, 159 | 160 | login: function() { 161 | // Replace this email with your own 162 | var emailAddress = "sample-email@test.com"; 163 | if (emailAddress) { 164 | var onSuccess = function() { 165 | console.log('Successfully logged in to Intercom!'); 166 | } 167 | var onError = function(code) { 168 | console.log('Failed to login to Intercom :' + code); 169 | } 170 | intercom.loginUserWithUserAttributes({email: emailAddress}, onSuccess, onError); 171 | var storage = window.localStorage; 172 | storage.setItem("email", emailAddress); 173 | app.configureViewForLoggedInUser(); 174 | } 175 | }, 176 | 177 | configureViewForLoggedInUser: function() { 178 | document.getElementById("logout-btn").style.visibility = 'visible'; 179 | document.getElementById("open-intercom-btn").style.visibility = 'visible'; 180 | document.getElementById("open-help-center-btn").style.visibility = 'visible'; 181 | document.getElementById("display-carousel-btn").style.visibility = 'visible'; 182 | document.getElementById("display-article-btn").style.visibility = 'visible'; 183 | document.getElementById("display-survey-btn").style.visibility = 'visible'; 184 | document.getElementById("display-conversation-btn").style.visibility = 'visible'; 185 | document.getElementById("login-btn").style.visibility = 'hidden'; 186 | }, 187 | 188 | configureViewForLoggedOutUser: function() { 189 | document.getElementById("logout-btn").style.visibility = 'hidden'; 190 | document.getElementById("open-intercom-btn").style.visibility = 'hidden'; 191 | document.getElementById("open-help-center-btn").style.visibility = 'hidden'; 192 | document.getElementById("display-carousel-btn").style.visibility = 'hidden'; 193 | document.getElementById("display-article-btn").style.visibility = 'hidden'; 194 | document.getElementById("display-survey-btn").style.visibility = 'hidden'; 195 | document.getElementById("display-conversation-btn").style.visibility = 'hidden'; 196 | document.getElementById("login-btn").style.visibility = 'visible'; 197 | } 198 | }; 199 | 200 | app.initialize(); 201 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2011- Intercom, Inc. (https://www.intercom.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Intercom](Example/www/img/Intercom_logo-github.png) 2 | 3 | ## Onboard, retain and support mobile users at scale 4 | Engage customers with email, push, and in‑app messages and support them with an integrated knowledge base and help desk. 5 | 6 | ### The Intercom Messenger 7 | The [Intercom Messenger](https://www.intercom.com/help/en/articles/316-the-intercom-messenger-in-your-product-and-on-your-website) is the home for the conversations your customers have with you via Intercom, and the place where they can self-serve for support or to learn more about your product. 8 | 9 | The Messenger works for both logged in and logged out users. It’s worth reading the detailed instructions in our [developer docs](https://developers.intercom.com/installing-intercom/docs/intercom-for-ios) on user management before you get started. 10 | 11 | You can open the Intercom Messenger from a button in your app, programmatically when someone does something, or from a persistent button that sits over your app’s UI. 12 | 13 | When you trigger the Intercom Messenger, your customer is presented with a home screen. This is configurable inside Intercom to change how it looks and what’s presented. 14 | 15 | From there, your customer can search for help articles or start a conversation. A conversation goes to your inbox inside Intercom, and replies in both directions happen in real time. You can also send push notifications to your customers to let them know they have a reply after they’ve left your app. 16 | 17 | ![iOSREadme1](https://user-images.githubusercontent.com/3185423/84803321-c5e41c80-aff9-11ea-89b0-514332887066.jpg) 18 | 19 | ### [Outbound messaging features](https://www.intercom.com/mobile-carousels) 20 | You can send messages to your customers from Intercom, and the mobile SDK will present them in your app. Messages can be targeted at specific users or groups of users, and can be scheduled to be sent during specific time windows. 21 | 22 | Companies use this for many use cases, including onboarding new users, announcing features, proactive support, important notices etc. 23 | 24 | The mobile SDK supports many different message formats, all of which can be created and configured inside Intercom. These include: 25 | 26 | * **Push notifications** - these can open your app or follow a deep link. 27 | * **Chats** - messages from someone in your team to your customer. 28 | * **Mobile Carousels** - highly customizable, multi-screen messages with calls to action and device permissions. 29 | * **Small posts** - a short announcement. 30 | * **Large posts** - a full screen announcement. 31 | 32 | We check for new messages when your app opens and whenever your customer or your app interacts with Intercom. 33 | 34 | ![iOS - Content types](https://user-images.githubusercontent.com/3185423/84890387-4191a800-b092-11ea-821e-e920ba7ef6a5.png) 35 | 36 | ## Installation 37 | 38 | ### Cordova 39 | 40 | To install the plugin in your Cordova app, run the following: 41 | ```script 42 | cordova plugin add cordova-plugin-intercom 43 | ``` 44 | ### PhoneGap 45 | 46 | To add the plugin to your PhoneGap app, add the following to your `config.xml`: 47 | ```xml 48 | 49 | ``` 50 | 51 | ### Requirements 52 | | Name | Required Version | 53 | | ----------- | ----------- | 54 | | cordova | 12.0.0 | 55 | | cordova-android | 13.0.0 | 56 | | cordova-ios | 7.1.0 | 57 | | iOS SDK | 15.0.0 | 58 | | Android SDK | 34 | 59 | 60 | ## Example App 61 | 62 | An example app is provided [here](https://github.com/intercom/intercom-cordova/tree/master/Example) that shows a basic Cordova/Phonegap app integration with Intercom. 63 | 64 | ## Setup and Configuration 65 | 66 | * Our [installation guide]((https://developers.intercom.com/installing-intercom/cordova-phonegap/installation/)) contains full setup and initialisation instructions. 67 | * The [configuration guide](https://developers.intercom.com/installing-intercom/cordova-phonegap/configuration/) provides info on how to configure Intercom for Cordova/Phonegap. 68 | * Read our guide on [Push Notifications](https://developers.intercom.com/installing-intercom/cordova-phonegap/push-notifications/) support. 69 | * Please contact us on [Intercom](https://www.intercom.com/) with any questions you may have, we're only a message away! 70 | 71 | 72 | ## Acknowledgements 73 | 74 | Thanks to [Josh Dover](https://github.com/joshdover) from [AskU](http://www.asku.co/) for making a Cordova plugin for Intercom for iOS which helped lots of people to integrate Intercom in their iOS Cordova apps. 👍 75 | 76 | ## License 77 | 78 | intercom-cordova is released under the [MIT License](http://www.opensource.org/licenses/MIT). 79 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | android: circleci/android@2.5.0 5 | 6 | setup_ruby: &setup_ruby 7 | run: 8 | name: Setup Ruby 9 | command: sed -i '' 's/.*chruby ruby.*/chruby ruby-3.3.0/' ~/.bash_profile 10 | 11 | jobs: 12 | ios: 13 | macos: 14 | xcode: "15.4.0" 15 | resource_class: macos.m1.large.gen1 16 | shell: /bin/bash --login -eo pipefail 17 | steps: 18 | - <<: *setup_ruby 19 | - checkout 20 | - run: 21 | name: Install node/npm 22 | command: command -v node || brew install node 23 | - run: 24 | name: Install Cordova 25 | command: npm install -g cordova 26 | - run: 27 | name: Add iOS platform 28 | command: cd Example && cordova platform add ios@latest 29 | - run: 30 | name: Install intercom plugin 31 | command: cd Example && cordova plugin add ../intercom-plugin 32 | - run: 33 | name: Build 34 | command: cd Example && cordova build ios 35 | 36 | android: 37 | executor: 38 | name: android/android-machine 39 | resource-class: large 40 | tag: default 41 | environment: 42 | GRADLE_OPTS: -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -Dorg.gradle.daemon=false -Dorg.gradle.caching=true -Dorg.gradle.configureondemand=true -Dkotlin.compiler.execution.strategy=in-process -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-XX:MaxMetaspaceSize=512m" -Dorg.gradle.workers.max=2 43 | working_directory: ~/project/Example 44 | steps: 45 | - checkout 46 | - run: 47 | name: Accept all Android licenses 48 | command: | 49 | yes | $ANDROID_HOME/tools/bin/sdkmanager --licenses || if [ $? -ne '141' ]; then exit $?; fi; 50 | - run: 51 | name: Install Cordova 52 | command: npm install -g cordova@12.0.0 53 | - run: 54 | name: Add Android platform 55 | command: cd Example && cordova platform add android@latest 56 | - run: 57 | name: Install intercom plugin 58 | command: cd Example && cordova plugin add ../intercom-plugin 59 | - run: 60 | name: Build 61 | command: cd Example && cordova build android --verbose -- --gradleArg=--stacktrace 62 | 63 | publish: 64 | executor: 65 | name: android/android-machine 66 | resource-class: large 67 | tag: default 68 | steps: 69 | - checkout 70 | - run: 71 | name: Publish to npm 72 | command: | 73 | echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > intercom-plugin/.npmrc 74 | npm config set scope $ORG_NAME 75 | cd intercom-plugin && npm publish 76 | 77 | workflows: 78 | version: 2.1 79 | ios_and_android: 80 | jobs: 81 | - ios: 82 | filters: 83 | tags: 84 | only: /[0-9]+(\.[0-9]+)+/ 85 | - android: 86 | filters: 87 | tags: 88 | only: /[0-9]+(\.[0-9]+)+/ 89 | - publish: 90 | requires: 91 | - ios 92 | - android 93 | filters: 94 | tags: 95 | only: /[0-9]+(\.[0-9]+)+/ 96 | branches: 97 | ignore: /.*/ 98 | -------------------------------------------------------------------------------- /intercom-plugin/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-intercom", 3 | "version": "14.0.3", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "cordova-plugin-intercom", 9 | "version": "14.0.3", 10 | "license": "MIT License", 11 | "dependencies": { 12 | "q": "^1.5.1" 13 | }, 14 | "engines": { 15 | "cordovaDependencies": { 16 | "14.0.0": { 17 | "cordova": "=>12.0.0", 18 | "cordova-android": ">=13.0.0", 19 | "cordova-ios": "7.1.0" 20 | } 21 | } 22 | } 23 | }, 24 | "node_modules/q": { 25 | "version": "1.5.1", 26 | "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", 27 | "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", 28 | "license": "MIT", 29 | "engines": { 30 | "node": ">=0.6.0", 31 | "teleport": ">=0.2.0" 32 | } 33 | } 34 | }, 35 | "dependencies": { 36 | "q": { 37 | "version": "1.5.1", 38 | "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", 39 | "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /intercom-plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-intercom", 3 | "version": "14.1.0", 4 | "description": "Official Cordova plugin for Intercom", 5 | "author": "Intercom", 6 | "license": "MIT License", 7 | "homepage": "https://github.com/intercom/intercom-cordova#readme", 8 | "cordova": { 9 | "id": "cordova-plugin-intercom", 10 | "platforms": [ 11 | "ios", 12 | "android" 13 | ] 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/intercom/intercom-cordova.git" 18 | }, 19 | "keywords": [ 20 | "intercom", 21 | "intercom-cordova", 22 | "ecosystem:cordova", 23 | "cordova-ios", 24 | "cordova-android" 25 | ], 26 | "dependencies": { 27 | "q": "^1.5.1" 28 | }, 29 | "engines": { 30 | "cordovaDependencies": { 31 | "14.0.0": { 32 | "cordova": "=>12.0.0", 33 | "cordova-android": ">=13.0.0", 34 | "cordova-ios": "7.1.0" 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /intercom-plugin/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Intercom 4 | Intercom 5 | MIT License 6 | Cordova plugin for Intercom for mobile 7 | https://github.com/intercom/intercom-cordova.git 8 | intercom,intercom-cordova 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | Send photos in your messages to the app. 58 | 59 | 60 | 61 | 62 | remote-notification 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /intercom-plugin/scripts/checkForUpdate.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | function fetchUpdateInfo(callback) { 4 | var updateInfo = { 5 | releaseDate: 0, 6 | podUpdateDate: 0, 7 | lastCheckDate: 0 8 | }; 9 | 10 | fs.readFile('platforms/ios/.intercom_update', 'utf8', function (err, data) { 11 | if (!err) { 12 | obj = JSON.parse(data); 13 | updateInfo.podUpdateDate = obj.podUpdateDate; 14 | updateInfo.releaseDate = obj.releaseDate; 15 | updateInfo.lastCheckDate = obj.lastCheckDate; 16 | } 17 | callback(updateInfo); 18 | }); 19 | } 20 | 21 | function writeUpdateInfo(updateInfo, callback) { 22 | fs.writeFile('platforms/ios/.intercom_update', JSON.stringify(updateInfo), 'utf8', function (err,data) { 23 | callback(); 24 | }); 25 | } 26 | 27 | function updateIntercomIfNeeded(updateInfo, callback) { 28 | var exec = require('child_process').exec; 29 | var completion = function() { 30 | writeUpdateInfo(updateInfo, function() { 31 | callback(); 32 | }); 33 | }; 34 | 35 | if (updateInfo.releaseDate > updateInfo.podUpdateDate) { 36 | console.log("Updating Intercom"); 37 | exec('cd platforms/ios && pod update Intercom', function(error, stdout, stderr) { 38 | if (!error) { 39 | console.log(stdout); 40 | updateInfo.podUpdateDate = Date.now(); 41 | } 42 | completion(); 43 | }); 44 | } else { 45 | completion(); 46 | } 47 | } 48 | 49 | function fetchLatestRelease(callback) { 50 | var https = require('https'); 51 | 52 | var req = https.get({ 53 | headers: { 54 | accept: 'application/json', 55 | 'User-Agent': 'Intercom-Cordova-Plugin' 56 | }, 57 | host: 'api.github.com', 58 | path: '/repos/intercom/intercom-ios/releases/latest' 59 | }, function(response) { 60 | if (response.statusCode != 200) { 61 | callback(null); 62 | return; 63 | } 64 | 65 | var body = ''; 66 | response.on('data', function(d) { 67 | body += d; 68 | }); 69 | response.on('end', function() { 70 | var parsedResponse = JSON.parse(body); 71 | callback(parsedResponse); 72 | }); 73 | }); 74 | req.on('error', function(e) { 75 | callback(null); 76 | }); 77 | } 78 | 79 | module.exports = function() { 80 | var q = require('q'); 81 | var deferral = new q.defer(); 82 | 83 | fetchUpdateInfo(function(updateInfo) { 84 | // Check at most once every 48 hours 85 | if (Date.now() - updateInfo.lastCheckDate > 1000 * 60 * 60 * 48) { 86 | fetchLatestRelease(function(releaseData) { 87 | updateInfo.lastCheckDate = Date.now(); 88 | 89 | if (releaseData != null) { 90 | updateInfo.releaseDate = Date.parse(releaseData['published_at']); 91 | } else { 92 | // last release date is unavailable, set it to today so that the pod is installed 93 | updateInfo.releaseDate = Date.now(); 94 | } 95 | 96 | updateIntercomIfNeeded(updateInfo, function() { 97 | deferral.resolve(); 98 | }); 99 | }); 100 | } else { 101 | deferral.resolve(); 102 | } 103 | }); 104 | return deferral.promise; 105 | } 106 | -------------------------------------------------------------------------------- /intercom-plugin/scripts/prepareCocoaPods.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | var q = require('q'); 3 | var exec = require('child_process').exec; 4 | 5 | var deferral = new q.defer(); 6 | 7 | console.log('Fetching latest CocoaPods specs repo '); 8 | exec('pod repo update --verbose', function(error, stdout, stderr) { 9 | deferral.resolve(); 10 | }); 11 | 12 | return deferral.promise; 13 | } 14 | -------------------------------------------------------------------------------- /intercom-plugin/src/android/CordovaHeaderInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.intercom.android.sdk.api; 2 | 3 | import android.content.Context; 4 | 5 | public class CordovaHeaderInterceptor { 6 | public static void setCordovaVersion(Context context, String cordovaVersion) { 7 | HeaderInterceptor.setCordovaVersion(context, cordovaVersion); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /intercom-plugin/src/android/HelpCenterCollectionContentModel.java: -------------------------------------------------------------------------------- 1 | package io.intercom.android.sdk; 2 | 3 | import java.util.List; 4 | 5 | import io.intercom.android.sdk.helpcenter.sections.HelpCenterArticle; 6 | import io.intercom.android.sdk.helpcenter.sections.HelpCenterSection; 7 | 8 | public class HelpCenterCollectionContentModel { 9 | private String collectionId; 10 | private List articles; 11 | private List sections; 12 | private String summary; 13 | private String title; 14 | 15 | public HelpCenterCollectionContentModel( 16 | String collectionId, 17 | List articles, 18 | List sections, 19 | String summary, 20 | String title 21 | ) { 22 | this.collectionId = collectionId; 23 | this.articles = articles; 24 | this.sections = sections; 25 | this.summary = summary; 26 | this.title = title; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /intercom-plugin/src/android/HelpCenterCollectionModel.java: -------------------------------------------------------------------------------- 1 | package io.intercom.android.sdk; 2 | 3 | public class HelpCenterCollectionModel { 4 | private String collectionId; 5 | private String summary; 6 | private String title; 7 | 8 | public HelpCenterCollectionModel( 9 | String collectionId, 10 | String summary, 11 | String title 12 | ) { 13 | this.collectionId = collectionId; 14 | this.summary = summary; 15 | this.title = title; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /intercom-plugin/src/android/HelpCenterCollectionSectionModel.java: -------------------------------------------------------------------------------- 1 | package io.intercom.android.sdk; 2 | 3 | import java.util.List; 4 | 5 | import io.intercom.android.sdk.helpcenter.sections.HelpCenterArticle; 6 | 7 | class HelpCenterCollectionSectionModel { 8 | private List articles; 9 | private String title; 10 | 11 | public HelpCenterCollectionSectionModel( 12 | List articles, 13 | String title 14 | ) { 15 | this.articles = articles; 16 | this.title = title; 17 | } 18 | } -------------------------------------------------------------------------------- /intercom-plugin/src/android/IntercomBridge.java: -------------------------------------------------------------------------------- 1 | package io.intercom.android.sdk; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.util.Log; 6 | 7 | import com.google.gson.Gson; 8 | 9 | import org.apache.cordova.CallbackContext; 10 | import org.apache.cordova.CordovaInterface; 11 | import org.apache.cordova.CordovaPlugin; 12 | import org.apache.cordova.PluginResult; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.json.JSONArray; 15 | import org.json.JSONObject; 16 | 17 | import java.util.ArrayList; 18 | import java.util.HashMap; 19 | import java.util.Iterator; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.Arrays; 23 | 24 | import io.intercom.android.sdk.Intercom.Visibility; 25 | import io.intercom.android.sdk.api.CordovaHeaderInterceptor; 26 | import io.intercom.android.sdk.api.UserUpdateRequest; 27 | import io.intercom.android.sdk.helpcenter.api.CollectionContentRequestCallback; 28 | import io.intercom.android.sdk.helpcenter.api.CollectionRequestCallback; 29 | import io.intercom.android.sdk.helpcenter.api.HelpCenterArticleSearchResult; 30 | import io.intercom.android.sdk.helpcenter.api.SearchRequestCallback; 31 | import io.intercom.android.sdk.helpcenter.collections.HelpCenterCollection; 32 | import io.intercom.android.sdk.helpcenter.sections.HelpCenterCollectionContent; 33 | import io.intercom.android.sdk.helpcenter.sections.HelpCenterSection; 34 | import io.intercom.android.sdk.identity.Registration; 35 | import io.intercom.android.sdk.push.IntercomPushClient; 36 | import io.intercom.android.sdk.IntercomSpace.*; 37 | import io.intercom.android.sdk.IntercomContent.*; 38 | import io.intercom.android.sdk.IntercomError; 39 | import io.intercom.android.sdk.IntercomStatusCallback; 40 | 41 | public class IntercomBridge extends CordovaPlugin { 42 | 43 | private static final String CUSTOM_ATTRIBUTES = "custom_attributes"; 44 | 45 | @Override protected void pluginInitialize() { 46 | cordova.getActivity().runOnUiThread(new Runnable() { 47 | @Override public void run() { 48 | setUpIntercom(); 49 | try { 50 | Injector.get().getApi().updateUser( 51 | UserUpdateRequest.create(true, false, true), 52 | new IntercomStatusCallback() { 53 | @Override public void onSuccess() { } 54 | @Override public void onFailure(IntercomError error) { } 55 | }); 56 | } catch (RuntimeException e) { 57 | // Intercom is not initialised yet, do nothing 58 | } 59 | } 60 | }); 61 | } 62 | 63 | @Override public void onStart() { 64 | cordova.getActivity().runOnUiThread(new Runnable() { 65 | @Override public void run() { 66 | //We also initialize intercom here just in case it has died. If Intercom is already set up, this won't do anything. 67 | setUpIntercom(); 68 | 69 | Intercom.client().handlePushMessage(); 70 | } 71 | }); 72 | } 73 | 74 | @Override public void onNewIntent(Intent intent) { 75 | cordova.getActivity().setIntent(intent); 76 | } 77 | 78 | private void setUpIntercom() { 79 | try { 80 | Context context = cordova.getActivity().getApplicationContext(); 81 | 82 | CordovaHeaderInterceptor.setCordovaVersion(context, "12.1.0"); 83 | 84 | switch (IntercomPushManager.getInstalledModuleType()) { 85 | case FCM: { 86 | String senderId = getSenderId(context); 87 | 88 | if (senderId != null) { 89 | Log.d("Intercom-Cordova", "Using FCM Sender ID: " + senderId); 90 | IntercomPushManager.cacheSenderId(context, senderId); 91 | } 92 | break; 93 | } 94 | } 95 | 96 | //Get app credentials from config.xml or the app bundle if they can't be found 97 | String apiKey = preferences.getString("intercom-android-api-key", ""); 98 | String appId = preferences.getString("intercom-app-id", ""); 99 | 100 | Intercom.initialize(cordova.getActivity().getApplication(), apiKey, appId); 101 | } catch (Exception e) { 102 | Log.e("Intercom-Cordova", "ERROR: Something went wrong when initializing Intercom. Have you set your APP_ID and ANDROID_API_KEY?", e); 103 | } 104 | } 105 | 106 | private String getSenderId(Context context) { 107 | String preferencesSenderId = preferences.getString("intercom-android-sender-id", ""); 108 | String resourcesSenderId; 109 | try { 110 | // copied from `google-services.json` in our Gradle script 111 | resourcesSenderId = context.getResources().getString(R.string.intercom_gcm_sender_id); 112 | } 113 | catch (Exception e) { 114 | Log.d("Intercom-Cordova", "Failed to get sender ID from resources: ", e); 115 | resourcesSenderId = ""; 116 | } 117 | 118 | if (preferencesSenderId.isEmpty()) { 119 | return resourcesSenderId; 120 | } 121 | 122 | // sometimes the XML parser Cordova uses formats numbers with scientific notation, giving an incorrect sender ID 123 | // if this is the case, fall back to the ID from the `google-services.json` file 124 | if (preferencesSenderId.contains(".") && !resourcesSenderId.isEmpty()) { 125 | return resourcesSenderId; 126 | } 127 | return preferencesSenderId; 128 | } 129 | 130 | private enum Action { 131 | loginUserWithUserAttributes { 132 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 133 | JSONObject options = args.optJSONObject(0); 134 | String email = options.optString("email"); 135 | String userId = options.optString("userId"); 136 | Boolean hasEmail = email != null && email.length() > 0; 137 | Boolean hasUserId = userId != null && userId.length() > 0; 138 | 139 | Registration registration = null; 140 | if (hasEmail && hasUserId) { 141 | registration = new Registration().withEmail(email).withUserId(userId); 142 | } else if (hasEmail) { 143 | registration = new Registration().withEmail(email); 144 | } else if (hasUserId) { 145 | registration = new Registration().withUserId(userId); 146 | } 147 | if (registration != null) { 148 | Intercom.client().loginIdentifiedUser(registration, new IntercomStatusCallback() { 149 | @Override 150 | public void onSuccess() { 151 | callbackContext.success(); 152 | } 153 | 154 | @Override 155 | public void onFailure(IntercomError intercomError) { 156 | Log.d("Intercom-Cordova", "ERROR: " + intercomError.getErrorMessage()); 157 | callbackContext.error(String.valueOf(intercomError.getErrorCode()) + " : " + intercomError.getErrorMessage()); 158 | } 159 | }); 160 | } 161 | } 162 | }, 163 | loginUnidentifiedUser { 164 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 165 | Intercom.client().loginUnidentifiedUser(new IntercomStatusCallback() { 166 | @Override 167 | public void onSuccess() { 168 | callbackContext.success(); 169 | } 170 | 171 | @Override 172 | public void onFailure(IntercomError intercomError) { 173 | Log.e("ERROR", intercomError.getErrorMessage()); 174 | callbackContext.error(String.valueOf(intercomError.getErrorCode()) + " : " + intercomError.getErrorMessage()); 175 | } 176 | }); 177 | } 178 | }, 179 | logout { 180 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 181 | Intercom.client().logout(); 182 | callbackContext.success(); 183 | } 184 | }, 185 | isUserLoggedIn { 186 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 187 | boolean loggedIn = Intercom.client().isUserLoggedIn(); 188 | callbackContext.success(loggedIn ? "true" : "false"); 189 | } 190 | }, 191 | fetchLoggedInUserAttributes { 192 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 193 | Registration registration = Intercom.client().fetchLoggedInUserAttributes(); 194 | if (registration != null) { 195 | RegistrationModel responseModel = new RegistrationModel(registration.getEmail(), registration.getUserId()); 196 | String json = new Gson().toJson(responseModel); 197 | callbackContext.success(json); 198 | } else { 199 | callbackContext.error("No user is currently logged in"); 200 | } 201 | } 202 | }, 203 | setUserHash { 204 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 205 | String hmac = args.optString(0); 206 | Intercom.client().setUserHash(hmac); 207 | callbackContext.success(); 208 | } 209 | }, 210 | logEvent { 211 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 212 | String eventName = args.optString(0); 213 | Map metaData = IntercomBridge.mapFromJSON(args.optJSONObject(1)); 214 | 215 | if (metaData == null) { 216 | Intercom.client().logEvent(eventName); 217 | } else { 218 | Intercom.client().logEvent(eventName, metaData); 219 | } 220 | callbackContext.success(); 221 | } 222 | }, 223 | unreadConversationCount { 224 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 225 | int count = Intercom.client().getUnreadConversationCount(); 226 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, count)); 227 | } 228 | }, 229 | present { 230 | @Override 231 | void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 232 | Intercom.client().present(); 233 | callbackContext.success(); 234 | } 235 | }, 236 | presentIntercomSpace { 237 | @Override 238 | void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 239 | String space = args.optString(0); 240 | IntercomSpace selectedSpace = IntercomSpace.Home; 241 | switch (space) { 242 | case "TICKETS": 243 | selectedSpace = IntercomSpace.Tickets; 244 | break; 245 | case "MESSAGES": 246 | selectedSpace = IntercomSpace.Messages; 247 | break; 248 | case "HELP_CENTER": 249 | selectedSpace = IntercomSpace.HelpCenter; 250 | break; 251 | default: 252 | selectedSpace = IntercomSpace.Home; 253 | } 254 | Intercom.client().present(selectedSpace); 255 | callbackContext.success(); 256 | } 257 | }, 258 | 259 | presentContent { 260 | @Override 261 | void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 262 | Map contentHash = IntercomBridge.mapFromJSON(args.optJSONObject(0)); 263 | Boolean hasContentType = contentHash.containsKey("type"); 264 | if (hasContentType) { 265 | IntercomContent content = null; 266 | String contentType = contentHash.get("type").toString(); 267 | 268 | switch (contentType) { 269 | case "ARTICLE": 270 | content = new IntercomContent.Article(contentHash.get("id").toString()); 271 | break; 272 | case "CAROUSEL": 273 | content = new IntercomContent.Carousel(contentHash.get("id").toString()); 274 | break; 275 | case "SURVEY": 276 | content = new IntercomContent.Survey(contentHash.get("id").toString()); 277 | break; 278 | case "HELP_CENTER_COLLECTIONS": 279 | List collectionIds = (List)contentHash.get("ids"); 280 | content = new IntercomContent.HelpCenterCollections(collectionIds); 281 | break; 282 | case "CONVERSATION": 283 | content = new IntercomContent.Conversation(contentHash.get("id").toString()); 284 | break; 285 | } 286 | if (content != null) { 287 | Intercom.client().presentContent(content); 288 | callbackContext.success(); 289 | } else { 290 | callbackContext.error("Invalid content type"); 291 | } 292 | } else { 293 | callbackContext.error("Intercom content must have a type"); 294 | } 295 | } 296 | }, 297 | 298 | presentMessageComposer { 299 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 300 | String initialMessage = args.optString(0); 301 | if (initialMessage != null) { 302 | Intercom.client().displayMessageComposer(initialMessage); 303 | } else { 304 | Intercom.client().displayMessageComposer(); 305 | } 306 | } 307 | }, 308 | 309 | fetchHelpCenterCollections { 310 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 311 | Intercom.client().fetchHelpCenterCollections(new CollectionRequestCallback() { 312 | @Override 313 | public void onComplete(@NotNull List list) { 314 | ArrayList responseModel = new ArrayList<>(); 315 | for (HelpCenterCollection helpCenterCollection : list) { 316 | String summary = helpCenterCollection.getSummary(); 317 | if (summary.isEmpty()) { 318 | summary = null; 319 | } 320 | responseModel.add( 321 | new HelpCenterCollectionModel( 322 | helpCenterCollection.getId(), 323 | summary, 324 | helpCenterCollection.getTitle() 325 | ) 326 | ); 327 | } 328 | String json = new Gson().toJson(responseModel); 329 | callbackContext.success(json); 330 | } 331 | 332 | @Override 333 | public void onError(int i) { 334 | callbackContext.error(i); 335 | } 336 | 337 | @Override 338 | public void onFailure() { 339 | callbackContext.error(""); 340 | } 341 | }); 342 | } 343 | }, 344 | fetchHelpCenterCollection { 345 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 346 | String collectionId = args.optString(0); 347 | Intercom.client().fetchHelpCenterCollection(collectionId, new CollectionContentRequestCallback() { 348 | @Override 349 | public void onComplete(@NotNull HelpCenterCollectionContent helpCenterCollectionContent) { 350 | ArrayList sectionModels = new ArrayList<>(); 351 | for (HelpCenterSection helpCenterSection : helpCenterCollectionContent.getHelpCenterSections()) { 352 | sectionModels.add( 353 | new HelpCenterCollectionSectionModel( 354 | helpCenterSection.getHelpCenterArticles(), 355 | helpCenterSection.getTitle() 356 | ) 357 | ); 358 | } 359 | HelpCenterCollectionContentModel responseModel = new HelpCenterCollectionContentModel( 360 | helpCenterCollectionContent.getCollectionId(), 361 | helpCenterCollectionContent.getHelpCenterArticles(), 362 | sectionModels, 363 | helpCenterCollectionContent.getSummary(), 364 | helpCenterCollectionContent.getTitle() 365 | ); 366 | String json = new Gson().toJson(responseModel); 367 | callbackContext.success(json); 368 | } 369 | 370 | @Override 371 | public void onError(int i) { 372 | callbackContext.error(i); 373 | } 374 | 375 | @Override 376 | public void onFailure() { 377 | callbackContext.error(""); 378 | } 379 | }); 380 | } 381 | }, 382 | searchHelpCenter { 383 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 384 | String searchTerm = args.optString(0); 385 | Intercom.client().searchHelpCenter(searchTerm, new SearchRequestCallback() { 386 | @Override 387 | public void onComplete(@NotNull List list) { 388 | String json = new Gson().toJson(list); 389 | callbackContext.success(json); 390 | } 391 | 392 | @Override 393 | public void onError(int i) { 394 | callbackContext.error(i); 395 | } 396 | 397 | @Override 398 | public void onFailure() { 399 | callbackContext.error(""); 400 | } 401 | }); 402 | } 403 | }, 404 | setLauncherVisibility { 405 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 406 | String visibilityString = args.optString(0); 407 | Visibility visibility = Intercom.VISIBLE; 408 | if ("GONE".equals(visibilityString)) { 409 | visibility = Intercom.GONE; 410 | } 411 | Intercom.client().setLauncherVisibility(visibility); 412 | callbackContext.success(); 413 | } 414 | }, 415 | setInAppMessageVisibility { 416 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 417 | String visibilityString = args.optString(0); 418 | Visibility visibility = Intercom.VISIBLE; 419 | if ("GONE".equals(visibilityString)) { 420 | visibility = Intercom.GONE; 421 | } 422 | Intercom.client().setInAppMessageVisibility(visibility); 423 | callbackContext.success(); 424 | } 425 | }, 426 | hideIntercom { 427 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 428 | Intercom.client().hideIntercom(); 429 | callbackContext.success(); 430 | } 431 | }, 432 | updateUser { 433 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 434 | Map attributes = IntercomBridge.mapFromJSON(args.optJSONObject(0)); 435 | UserAttributes.Builder builder = new UserAttributes.Builder(); 436 | Object customAttributes = attributes.get(CUSTOM_ATTRIBUTES); 437 | if (customAttributes instanceof Map) { 438 | //noinspection unchecked 439 | builder.customAttributes.putAll((Map) customAttributes); 440 | } 441 | attributes.remove(CUSTOM_ATTRIBUTES); 442 | builder.attributes.putAll(attributes); 443 | Intercom.client().updateUser(builder.build()); 444 | callbackContext.success(); 445 | } 446 | }, 447 | registerForPush { 448 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 449 | //This doesn't need to do anything on Android 450 | } 451 | }, 452 | sendPushTokenToIntercom { 453 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 454 | String token = args.optString(0); 455 | IntercomPushClient intercomPushClient = new IntercomPushClient(); 456 | intercomPushClient.sendTokenToIntercom(cordova.getActivity().getApplication(), token); 457 | } 458 | }, 459 | unknown { 460 | @Override void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova) { 461 | callbackContext.error("[Intercom-Cordova] ERROR: Undefined function"); 462 | } 463 | }; 464 | 465 | abstract void performAction(JSONArray args, CallbackContext callbackContext, CordovaInterface cordova); 466 | 467 | public static Action fromString(String actionAsString) { 468 | Action action = unknown; 469 | 470 | try { 471 | action = valueOf(actionAsString); 472 | } catch (NullPointerException ignored) {} 473 | catch (IllegalArgumentException ignored) {} 474 | 475 | return action; 476 | } 477 | } 478 | 479 | public boolean execute(String actionString, final JSONArray args, final CallbackContext callbackContext) { 480 | final Action action = Action.fromString(actionString); 481 | 482 | cordova.getActivity().runOnUiThread(new Runnable() { 483 | @Override public void run() { 484 | action.performAction(args, callbackContext, IntercomBridge.this.cordova); 485 | } 486 | }); 487 | return action != Action.unknown; 488 | } 489 | 490 | private static Map mapFromJSON(JSONObject jsonObject) { 491 | if (jsonObject == null) { 492 | return null; 493 | } 494 | Map map = new HashMap<>(); 495 | Iterator keysIter = jsonObject.keys(); 496 | while (keysIter.hasNext()) { 497 | String key = keysIter.next(); 498 | Object value = getObject(jsonObject.opt(key)); 499 | if (value != null) { 500 | map.put(key, value); 501 | } 502 | } 503 | return map; 504 | } 505 | 506 | private static List listFromJSON(JSONArray jsonArray) { 507 | List list = new ArrayList<>(); 508 | for (int i = 0, count = jsonArray.length(); i < count; i++) { 509 | Object value = getObject(jsonArray.opt(i)); 510 | if (value != null) { 511 | list.add(value); 512 | } 513 | } 514 | return list; 515 | } 516 | 517 | private static Object getObject(Object value) { 518 | if (value instanceof JSONObject) { 519 | value = mapFromJSON((JSONObject) value); 520 | } else if (value instanceof JSONArray) { 521 | value = listFromJSON((JSONArray) value); 522 | } 523 | return value; 524 | } 525 | } 526 | -------------------------------------------------------------------------------- /intercom-plugin/src/android/RegistrationModel.java: -------------------------------------------------------------------------------- 1 | package io.intercom.android.sdk; 2 | 3 | public class RegistrationModel { 4 | private String email; 5 | private String userId; 6 | 7 | public RegistrationModel( 8 | String email, 9 | String userId 10 | ) { 11 | this.email = email; 12 | this.userId = userId; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /intercom-plugin/src/android/build-extras-intercom.gradle: -------------------------------------------------------------------------------- 1 | // Uses the app id as a prefix (instead of com.google.android). This prevents 2 | // INSTALL_FAILED_CONFLICTING_PROVIDER error when installing the app. 3 | // 4 | // @link https://issues.apache.org/jira/browse/CB-10014 5 | def manifest = new XmlSlurper().parse(file("src/main/AndroidManifest.xml")) 6 | android.defaultConfig.applicationId manifest.@package.text() 7 | 8 | afterEvaluate { 9 | logIfIncorrectCompileSdkVersion() 10 | } 11 | 12 | private void logIfIncorrectCompileSdkVersion() { 13 | // this can be `{number}` or `android-{number}` 14 | // regex checks that it ends with a number between 16 and 26 inclusive 15 | if (cordovaConfig.SDK_VERSION != null && cordovaConfig.SDK_VERSION != 34) { 16 | throw new GradleException("Intercom Android Error: Your cordovaConfig.SDK_VERSION is [${cordovaConfig.SDK_VERSION}].\n"+ 17 | "You need to use a cordovaConfig.SDK_VERSION of 34\n"+ 18 | "See here for more: https://cordova.apache.org/docs/en/latest/guide/platforms/android/index.html#setting-gradle-properties\n") 19 | } 20 | } -------------------------------------------------------------------------------- /intercom-plugin/src/android/intercom.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | pushType = '' 4 | new XmlSlurper().parse(file('../app/src/main/res/xml/config.xml')).preference.each { 5 | if (it.@name.text() == 'intercom-android-push-type') { 6 | pushType = it.@value.text().toLowerCase() 7 | } 8 | } 9 | kotlin_version = '1.8.22' 10 | } 11 | repositories { 12 | google() 13 | mavenLocal() 14 | mavenCentral() 15 | maven { url 'https://maven.google.com' } 16 | } 17 | dependencies { 18 | classpath 'com.android.tools.build:gradle:8.0.2' 19 | if (pushType == 'fcm') { 20 | classpath 'com.google.gms:google-services:4.3.3' 21 | } 22 | // Need to add Kotlin classpath here to avoid an issue with accessing Compose from a Java only project 23 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 24 | } 25 | 26 | } 27 | 28 | repositories { 29 | google() 30 | mavenCentral() 31 | maven { url 'https://maven.google.com' } 32 | } 33 | 34 | dependencies { 35 | implementation 'io.intercom.android:intercom-sdk-base:15.13.0' 36 | implementation 'com.google.code.gson:gson:2.8.6' 37 | implementation 'com.intercom:twig:1.3.0' 38 | implementation 'org.jetbrains:annotations:13.0' 39 | implementation 'com.squareup.okhttp3:okhttp:4.9.0' 40 | if (pushType == 'fcm' || pushType == 'fcm-without-build-plugin') { 41 | implementation 'com.google.firebase:firebase-messaging:20.+' 42 | implementation 'io.intercom.android:intercom-sdk-fcm:15.13.0' 43 | } 44 | } 45 | 46 | // Need to add Kotlin plugin here to avoid an issue with accessing Compose from a Java only project 47 | apply plugin: 'kotlin-android' 48 | 49 | if (pushType == 'fcm') { 50 | apply plugin: com.google.gms.googleservices.GoogleServicesPlugin 51 | logger.info("Applying GoogleServicesPlugin") 52 | } else if (pushType == 'fcm-without-build-plugin') { 53 | logger.info("Not applying GoogleServicesPlugin from Intercom plugin, another plugin should do this") 54 | } 55 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/AppDelegate+IntercomPush.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | @interface AppDelegate (IntercomPush) 6 | @end 7 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/AppDelegate+IntercomPush.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate+IntercomPush.h" 2 | #import 3 | #import 4 | 5 | @implementation AppDelegate (IntercomPush) 6 | 7 | + (void)load { 8 | static dispatch_once_t onceToken; 9 | dispatch_once(&onceToken, ^{ 10 | [self swizzleDidRegisterForRemoteNotification]; 11 | [self swizzlePushPlugin]; 12 | }); 13 | } 14 | 15 | + (void)swizzleDidRegisterForRemoteNotification { 16 | __block Class originalClass = [AppDelegate class]; 17 | if (!originalClass) { 18 | return; 19 | } 20 | 21 | SEL originalSelector = @selector(application:didRegisterForRemoteNotificationsWithDeviceToken:); 22 | __block IMP originalImp = NULL; 23 | 24 | //Replacement IMP for original method 25 | IMP replacement = imp_implementationWithBlock(^void (id _self, UIApplication *application, NSData *deviceToken) { 26 | [Intercom setDeviceToken:deviceToken failure:nil]; 27 | 28 | //perform host app push logic here 29 | if (originalImp != NULL) { 30 | ((void(*)(id, SEL, UIApplication *, NSData *))originalImp)(_self, _cmd, application, deviceToken); 31 | } 32 | }); 33 | 34 | //Swizzling 35 | Method method = class_getInstanceMethod(originalClass, originalSelector); 36 | if (method) { 37 | const char *type = method_getTypeEncoding(method); 38 | originalImp = class_replaceMethod(originalClass, originalSelector, replacement, type); 39 | if (!originalImp) { 40 | originalImp = method_getImplementation(method); 41 | } 42 | } else { 43 | class_addMethod(originalClass, originalSelector, replacement, "v@:@@"); 44 | } 45 | } 46 | 47 | #pragma clang diagnostic push 48 | #pragma clang diagnostic ignored "-Wundeclared-selector" 49 | + (void)swizzlePushPlugin { 50 | __block Class originalClass = [self class]; 51 | if (!originalClass) { 52 | return; 53 | } 54 | 55 | SEL originalSelector = @selector(setLaunchNotification:); 56 | __block IMP originalImp = NULL; 57 | 58 | //Replacement IMP for original method 59 | IMP replacement = imp_implementationWithBlock(^void (id _self, NSDictionary *launchNotification) { 60 | if (launchNotification && [Intercom isIntercomPushNotification:launchNotification]) { 61 | [Intercom handleIntercomPushNotification:launchNotification]; 62 | } else if (originalImp != NULL) { 63 | ((void(*)(id, SEL, NSDictionary *))originalImp)(_self, _cmd, launchNotification); 64 | } 65 | }); 66 | 67 | //Swizzling 68 | Method method = class_getInstanceMethod(originalClass, originalSelector); 69 | if (method) { 70 | const char *type = method_getTypeEncoding(method); 71 | originalImp = class_replaceMethod(originalClass, originalSelector, replacement, type); 72 | if (!originalImp) { 73 | originalImp = method_getImplementation(method); 74 | } 75 | } 76 | } 77 | #pragma clang diagnostic pop 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/ICMHelpCenterArticle+DictionaryConversion.h: -------------------------------------------------------------------------------- 1 | // 2 | // ICMHelpCenterArticle+DictionaryConversion.h 3 | // Sample 4 | // 5 | // Created by Michael McNamara on 25/06/2021. 6 | // Copyright © 2021 Intercom. All rights reserved. 7 | // 8 | 9 | #import "Intercom/Intercom.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ICMHelpCenterArticle (DictionaryConversion) 14 | 15 | - (NSDictionary *)toDictionary; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/ICMHelpCenterArticle+DictionaryConversion.m: -------------------------------------------------------------------------------- 1 | // 2 | // ICMHelpCenterArticle+DictionaryConversion.m 3 | // Sample 4 | // 5 | // Created by Michael McNamara on 25/06/2021. 6 | // Copyright © 2021 Intercom. All rights reserved. 7 | // 8 | 9 | #import "ICMHelpCenterArticle+DictionaryConversion.h" 10 | 11 | @implementation ICMHelpCenterArticle (DictionaryConversion) 12 | 13 | - (NSDictionary *)toDictionary { 14 | NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; 15 | [dictionary setValue:self.articleId forKey:@"articleId"]; 16 | [dictionary setValue:self.title forKey:@"title"]; 17 | return [dictionary copy]; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/ICMHelpCenterArticleSearchResult+DictionaryConversion.h: -------------------------------------------------------------------------------- 1 | // 2 | // ICMHelpCenterArticleSearchResult+DictionaryConversion.h 3 | // Sample 4 | // 5 | // Created by Michael McNamara on 25/06/2021. 6 | // Copyright © 2021 Intercom. All rights reserved. 7 | // 8 | 9 | #import "Intercom/Intercom.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ICMHelpCenterArticleSearchResult (DictionaryConversion) 14 | 15 | - (NSDictionary *)toDictionary; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/ICMHelpCenterArticleSearchResult+DictionaryConversion.m: -------------------------------------------------------------------------------- 1 | // 2 | // ICMHelpCenterArticleSearchResult+DictionaryConversion.m 3 | // Sample 4 | // 5 | // Created by Michael McNamara on 25/06/2021. 6 | // Copyright © 2021 Intercom. All rights reserved. 7 | // 8 | 9 | #import "ICMHelpCenterArticleSearchResult+DictionaryConversion.h" 10 | 11 | @implementation ICMHelpCenterArticleSearchResult (DictionaryConversion) 12 | 13 | - (NSDictionary *)toDictionary { 14 | NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; 15 | [dictionary setValue:self.articleId forKey:@"articleId"]; 16 | [dictionary setValue:self.title forKey:@"title"]; 17 | [dictionary setValue:self.summary forKey:@"summary"]; 18 | [dictionary setValue:self.matchingSnippet forKey:@"matchingSnippet"]; 19 | return [dictionary copy]; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/ICMHelpCenterCollection+DictionaryConversion.h: -------------------------------------------------------------------------------- 1 | // 2 | // ICMHelpCenterCollection+DictionaryConversion.h 3 | // Sample 4 | // 5 | // Created by Michael McNamara on 25/06/2021. 6 | // Copyright © 2021 Intercom. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ICMHelpCenterCollection (DictionaryConversion) 14 | 15 | - (NSMutableDictionary *)toDictionary; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/ICMHelpCenterCollection+DictionaryConversion.m: -------------------------------------------------------------------------------- 1 | // 2 | // ICMHelpCenterCollection+DictionaryConversion.m 3 | // Sample 4 | // 5 | // Created by Michael McNamara on 25/06/2021. 6 | // Copyright © 2021 Intercom. All rights reserved. 7 | // 8 | 9 | #import "ICMHelpCenterCollection+DictionaryConversion.h" 10 | 11 | @implementation ICMHelpCenterCollection (DictionaryConversion) 12 | 13 | - (NSDictionary *)toDictionary { 14 | NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; 15 | [dictionary setValue:self.collectionId forKey:@"collectionId"]; 16 | [dictionary setValue:self.title forKey:@"title"]; 17 | [dictionary setValue:self.summary forKey:@"summary"]; 18 | return [dictionary copy]; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/ICMHelpCenterCollectionContent+DictionaryConversion.h: -------------------------------------------------------------------------------- 1 | // 2 | // ICMHelpCenterCollectionContent+DictionaryConversion.h 3 | // Sample 4 | // 5 | // Created by Michael McNamara on 25/06/2021. 6 | // Copyright © 2021 Intercom. All rights reserved. 7 | // 8 | 9 | #import "Intercom/Intercom.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ICMHelpCenterCollectionContent (DictionaryConversion) 14 | 15 | - (NSDictionary *)toDictionary; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/ICMHelpCenterCollectionContent+DictionaryConversion.m: -------------------------------------------------------------------------------- 1 | // 2 | // ICMHelpCenterCollectionContent+DictionaryConversion.m 3 | // Sample 4 | // 5 | // Created by Michael McNamara on 25/06/2021. 6 | // Copyright © 2021 Intercom. All rights reserved. 7 | // 8 | 9 | #import "ICMHelpCenterCollection+DictionaryConversion.h" 10 | #import "ICMHelpCenterArticle+DictionaryConversion.h" 11 | #import "ICMHelpCenterCollectionContent+DictionaryConversion.h" 12 | 13 | @implementation ICMHelpCenterCollectionContent (DictionaryConversion) 14 | 15 | - (NSDictionary *)toDictionary { 16 | NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; 17 | [dictionary setValue:self.collectionId forKey:@"collectionId"]; 18 | [dictionary setValue:self.title forKey:@"title"]; 19 | [dictionary setValue:self.summary forKey:@"summary"]; 20 | 21 | NSMutableArray *arrayOfArticleDictionaries = [@[] mutableCopy]; 22 | for (ICMHelpCenterArticle *article in self.articles) { 23 | NSDictionary *articleDictionary = [article toDictionary]; 24 | [arrayOfArticleDictionaries addObject:articleDictionary]; 25 | } 26 | [dictionary setValue:arrayOfArticleDictionaries forKey:@"articles"]; 27 | 28 | NSMutableArray *arrayOfCollectionDictionaries = [@[] mutableCopy]; 29 | for (ICMHelpCenterCollection *collection in self.collections) { 30 | NSDictionary *collectionDictionary = [collection toDictionary]; 31 | [arrayOfCollectionDictionaries addObject:collectionDictionary]; 32 | } 33 | [dictionary setValue:arrayOfCollectionDictionaries forKey:@"collections"]; 34 | 35 | return [dictionary copy]; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/ICMUserAttributes+DictionaryConversion.h: -------------------------------------------------------------------------------- 1 | // 2 | // ICMUserAttributes+DictionaryConversion.h 3 | // Sample 4 | // 5 | // Created by Matthew Pierce on 11/12/2024. 6 | // Copyright © 2024 Intercom. All rights reserved. 7 | // 8 | 9 | #import "Intercom/Intercom.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ICMUserAttributes (DictionaryConversion) 14 | 15 | - (NSDictionary *)toDictionary; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/ICMUserAttributes+DictionaryConversion.m: -------------------------------------------------------------------------------- 1 | // 2 | // ICMUserAttributes+DictionaryConversion.h 3 | // Sample 4 | // 5 | // Created by Matthew Pierce on 11/12/2024. 6 | // Copyright © 2024 Intercom. All rights reserved. 7 | // 8 | 9 | #import "ICMUserAttributes+DictionaryConversion.h" 10 | 11 | @implementation ICMUserAttributes (DictionaryConversion) 12 | 13 | - (NSDictionary *)toDictionary { 14 | NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; 15 | if (self.email) { 16 | dictionary[@"email"] = self.email; 17 | } 18 | if (self.userId) { 19 | dictionary[@"userId"] = self.userId; 20 | } 21 | return [dictionary copy]; 22 | } 23 | 24 | @end -------------------------------------------------------------------------------- /intercom-plugin/src/ios/IntercomBridge.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | @interface IntercomBridge : CDVPlugin 6 | 7 | #pragma mark - User Login 8 | 9 | - (void)loginUserWithUserAttributes:(CDVInvokedUrlCommand*)command; 10 | - (void)loginUnidentifiedUser:(CDVInvokedUrlCommand*)command; 11 | - (void)logout:(CDVInvokedUrlCommand*)command; 12 | - (void)setUserHash:(CDVInvokedUrlCommand*)command; 13 | - (void)updateUser:(CDVInvokedUrlCommand*)command; 14 | 15 | #pragma mark - Logged in status 16 | 17 | - (void)isUserLoggedIn:(CDVInvokedUrlCommand*)command; 18 | - (void)fetchLoggedInUserAttributes:(CDVInvokedUrlCommand*)command; 19 | 20 | #pragma mark - Events 21 | 22 | - (void)logEvent:(CDVInvokedUrlCommand*)command; 23 | 24 | #pragma mark - Present Intercom UI 25 | 26 | - (void)present:(CDVInvokedUrlCommand*)command; 27 | - (void)presentIntercomSpace:(CDVInvokedUrlCommand*)command; 28 | - (void)presentContent:(CDVInvokedUrlCommand*)command; 29 | - (void)presentMessageComposer:(CDVInvokedUrlCommand*)command; 30 | 31 | #pragma mark - Help Center Data API 32 | 33 | - (void)fetchHelpCenterCollections:(CDVInvokedUrlCommand*)command; 34 | - (void)fetchHelpCenterCollection:(CDVInvokedUrlCommand*)command; 35 | - (void)searchHelpCenter:(CDVInvokedUrlCommand*)command; 36 | 37 | #pragma mark - Intercom UI Visibility 38 | 39 | - (void)setLauncherVisibility:(CDVInvokedUrlCommand*)command; 40 | - (void)setBottomPadding:(CDVInvokedUrlCommand*)command; 41 | - (void)setInAppMessageVisibility:(CDVInvokedUrlCommand*)command; 42 | - (void)hideIntercom:(CDVInvokedUrlCommand*)command; 43 | 44 | #pragma mark - Unread Conversation Count 45 | 46 | - (void)unreadConversationCount:(CDVInvokedUrlCommand*)command; 47 | 48 | #pragma mark - Push Notifications 49 | 50 | - (void)registerForPush:(CDVInvokedUrlCommand*)command; 51 | @end 52 | -------------------------------------------------------------------------------- /intercom-plugin/src/ios/IntercomBridge.m: -------------------------------------------------------------------------------- 1 | #import "IntercomBridge.h" 2 | #import "AppDelegate+IntercomPush.h" 3 | #import "ICMHelpCenterCollection+DictionaryConversion.h" 4 | #import "ICMHelpCenterArticleSearchResult+DictionaryConversion.h" 5 | #import "ICMHelpCenterCollectionContent+DictionaryConversion.h" 6 | #import "ICMUserAttributes+DictionaryConversion.h" 7 | #import 8 | 9 | @interface Intercom (Cordoava) 10 | + (void)setCordovaVersion:(NSString *)v; 11 | @end 12 | 13 | @implementation IntercomBridge : CDVPlugin 14 | 15 | 16 | #pragma mark - Intercom Initialisation 17 | 18 | - (void)pluginInitialize { 19 | [Intercom setCordovaVersion:@"14.0.0"]; 20 | #ifdef DEBUG 21 | [Intercom enableLogging]; 22 | #endif 23 | 24 | //Get app credentials from config.xml or the info.plist if they can't be found 25 | NSString* apiKey = self.commandDelegate.settings[@"intercom-ios-api-key"] ?: [[NSBundle mainBundle] objectForInfoDictionaryKey:@"IntercomApiKey"]; 26 | NSString* appId = self.commandDelegate.settings[@"intercom-app-id"] ?: [[NSBundle mainBundle] objectForInfoDictionaryKey:@"IntercomAppId"]; 27 | 28 | [Intercom setApiKey:apiKey forAppId:appId]; 29 | } 30 | 31 | - (void)setUserHash:(CDVInvokedUrlCommand*)command { 32 | NSString *hmac = command.arguments[0]; 33 | 34 | [Intercom setUserHash:hmac]; 35 | [self sendSuccess:command]; 36 | } 37 | 38 | #pragma mark - User Login 39 | 40 | - (void)loginUserWithUserAttributes:(CDVInvokedUrlCommand*)command { 41 | NSDictionary* options = command.arguments[0]; 42 | NSString* userId = options[@"userId"]; 43 | NSString* userEmail = options[@"email"]; 44 | 45 | if ([userId isKindOfClass:[NSNumber class]]) { 46 | userId = [(NSNumber *)userId stringValue]; 47 | } 48 | 49 | ICMUserAttributes *userAttributes = [ICMUserAttributes new]; 50 | 51 | if (userId.length > 0 && userEmail.length > 0) { 52 | userAttributes.userId = userId; 53 | userAttributes.email = userEmail; 54 | } else if (userId.length > 0) { 55 | userAttributes.userId = userId; 56 | } else if (userEmail.length > 0) { 57 | userAttributes.email = userEmail; 58 | } else { 59 | NSLog(@"[Intercom-Cordova] ERROR - No user registered. You must supply an email, a userId or both"); 60 | [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR] 61 | callbackId:command.callbackId]; 62 | return; 63 | } 64 | 65 | [Intercom loginUserWithUserAttributes:userAttributes success:^{ 66 | [self sendSuccess:command]; 67 | } failure:^(NSError * _Nonnull error) { 68 | [self sendFailure:command withError:error]; 69 | }]; 70 | [self sendSuccess:command]; 71 | } 72 | 73 | - (void)loginUnidentifiedUser:(CDVInvokedUrlCommand*)command { 74 | [Intercom loginUnidentifiedUserWithSuccess:^{ 75 | [self sendSuccess:command]; 76 | } failure:^(NSError * _Nonnull error) { 77 | [self sendFailure:command withError:error]; 78 | }]; 79 | } 80 | 81 | - (void)logout:(CDVInvokedUrlCommand*)command { 82 | [Intercom logout]; 83 | [self sendSuccess:command]; 84 | } 85 | 86 | - (void)isUserLoggedIn:(CDVInvokedUrlCommand*)command { 87 | BOOL loggedIn = [Intercom isUserLoggedIn]; 88 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:loggedIn]; 89 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 90 | } 91 | 92 | - (void)fetchLoggedInUserAttributes:(CDVInvokedUrlCommand*)command { 93 | ICMUserAttributes *attributes = [Intercom fetchLoggedInUserAttributes]; 94 | if (attributes) { 95 | NSString *jsonString = [self stringValueForDictionary:[attributes toDictionary]]; 96 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:jsonString]; 97 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 98 | } else { 99 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsNSInteger:command.callbackId]; 100 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 101 | } 102 | } 103 | 104 | - (void)updateUser:(CDVInvokedUrlCommand*)command { 105 | NSDictionary* attributesDict = command.arguments[0]; 106 | [Intercom updateUser:[self userAttributesForDictionary:attributesDict] success:^{ 107 | [self sendSuccess:command]; 108 | } failure:^(NSError * _Nonnull error) { 109 | [self sendFailure:command withError:error]; 110 | }]; 111 | [self sendSuccess:command]; 112 | } 113 | 114 | #pragma mark - Events 115 | 116 | - (void)logEvent:(CDVInvokedUrlCommand*)command { 117 | NSString *eventName = command.arguments[0]; 118 | NSDictionary *metaData = command.arguments[1]; 119 | 120 | if ([metaData isKindOfClass:[NSDictionary class]] && metaData.count > 0) { 121 | [Intercom logEventWithName:eventName metaData:metaData]; 122 | } else { 123 | [Intercom logEventWithName:eventName]; 124 | } 125 | [self sendSuccess:command]; 126 | } 127 | 128 | 129 | #pragma mark - Present Intercom UI 130 | 131 | - (void)present:(CDVInvokedUrlCommand*)command { 132 | [Intercom presentIntercom]; 133 | [self sendSuccess:command]; 134 | } 135 | 136 | - (void)presentIntercomSpace:(CDVInvokedUrlCommand*)command { 137 | NSString *space = command.arguments[0]; 138 | Space selectedSpace = home; 139 | if ([space isEqualToString:@"HOME"]) { 140 | selectedSpace = home; 141 | } else if ([space isEqualToString:@"HELP_CENTER"]) { 142 | selectedSpace = helpCenter; 143 | } else if ([space isEqualToString:@"MESSAGES"]) { 144 | selectedSpace = messages; 145 | } else if ([space isEqualToString:@"TICKETS"]) { 146 | selectedSpace = tickets; 147 | } 148 | [Intercom presentIntercom:selectedSpace]; 149 | [self sendSuccess:command]; 150 | } 151 | 152 | - (void)presentContent:(CDVInvokedUrlCommand*)command { 153 | NSDictionary *content = command.arguments[0]; 154 | IntercomContent *intercomContent; 155 | NSString *contentType = content[@"type"]; 156 | if ([contentType isEqualToString:@"ARTICLE"]) { 157 | intercomContent = [IntercomContent articleWithId:content[@"id"]]; 158 | } else if ([contentType isEqualToString:@"CAROUSEL"]) { 159 | intercomContent = [IntercomContent carouselWithId:content[@"id"]]; 160 | } else if ([contentType isEqualToString:@"SURVEY"]) { 161 | intercomContent = [IntercomContent surveyWithId:content[@"id"]]; 162 | } else if ([contentType isEqualToString:@"HELP_CENTER_COLLECTIONS"]) { 163 | NSArray *collectionIds = content[@"ids"]; 164 | intercomContent = [IntercomContent helpCenterCollectionsWithIds:collectionIds]; 165 | } else if ([contentType isEqualToString:@"CONVERSATION"]) { 166 | intercomContent = [IntercomContent conversationWithId:content[@"id"]]; 167 | } 168 | if (intercomContent) { 169 | [Intercom presentContent:intercomContent]; 170 | [self sendSuccess:command]; 171 | } 172 | } 173 | 174 | - (void)presentMessageComposer:(CDVInvokedUrlCommand*)command { 175 | NSString *initialMessage = command.arguments[0]; 176 | [Intercom presentMessageComposer:initialMessage]; 177 | [self sendSuccess:command]; 178 | } 179 | 180 | #pragma mark - Help Center Data API 181 | 182 | - (void)fetchHelpCenterCollections:(CDVInvokedUrlCommand*)command { 183 | [Intercom fetchHelpCenterCollectionsWithCompletion:^(NSArray * _Nullable collections, NSError * _Nullable error) { 184 | if (error) { 185 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsNSInteger:error.code]; 186 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 187 | } else { 188 | NSMutableArray *array = [[NSMutableArray alloc] init]; 189 | for (ICMHelpCenterCollection *collection in collections) { 190 | [array addObject:[collection toDictionary]]; 191 | } 192 | NSString *jsonString = [self stringValueForDictionaries:(NSArray *)array]; 193 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:jsonString]; 194 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 195 | } 196 | }]; 197 | } 198 | 199 | - (void)fetchHelpCenterCollection:(CDVInvokedUrlCommand*)command { 200 | NSString *collectionId = command.arguments[0]; 201 | [Intercom fetchHelpCenterCollection:collectionId withCompletion:^(ICMHelpCenterCollectionContent * _Nullable collectionContent, NSError * _Nullable error) { 202 | if (error) { 203 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsNSInteger:error.code]; 204 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 205 | } else { 206 | NSString *jsonString = [self stringValueForDictionary:[collectionContent toDictionary]]; 207 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:jsonString]; 208 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 209 | } 210 | }]; 211 | } 212 | 213 | - (void)searchHelpCenter:(CDVInvokedUrlCommand*)command { 214 | NSString *searchTerm = command.arguments[0]; 215 | [Intercom searchHelpCenter:searchTerm withCompletion:^(NSArray * _Nullable articleSearchResults, NSError * _Nullable error) { 216 | if (error) { 217 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsNSInteger:error.code]; 218 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 219 | } else { 220 | NSMutableArray *array = [[NSMutableArray alloc] init]; 221 | for (ICMHelpCenterArticleSearchResult *articleSearchResult in articleSearchResults) { 222 | [array addObject:[articleSearchResult toDictionary]]; 223 | } 224 | NSString *jsonString = [self stringValueForDictionaries:(NSArray *)array]; 225 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:jsonString]; 226 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 227 | } 228 | }]; 229 | } 230 | 231 | 232 | #pragma mark - Intercom UI Visibility 233 | 234 | - (void)hideIntercom:(CDVInvokedUrlCommand*)command { 235 | [Intercom hideIntercom]; 236 | [self sendSuccess:command]; 237 | } 238 | 239 | - (void)setLauncherVisibility:(CDVInvokedUrlCommand*)command { 240 | NSString *visibilityString = command.arguments[0]; 241 | BOOL visible = NO; 242 | if ([visibilityString isEqualToString:@"VISIBLE"]) { 243 | visible = YES; 244 | } 245 | [Intercom setLauncherVisible:visible]; 246 | [self sendSuccess:command]; 247 | } 248 | 249 | - (void)setInAppMessageVisibility:(CDVInvokedUrlCommand*)command { 250 | NSString *visibilityString = command.arguments[0]; 251 | BOOL visible = NO; 252 | if ([visibilityString isEqualToString:@"VISIBLE"]) { 253 | visible = YES; 254 | } 255 | [Intercom setInAppMessagesVisible:visible]; 256 | [self sendSuccess:command]; 257 | } 258 | 259 | - (void)setBottomPadding:(CDVInvokedUrlCommand*)command { 260 | double bottomPadding = [[command.arguments objectAtIndex:0] doubleValue]; 261 | [Intercom setBottomPadding:bottomPadding]; 262 | [self sendSuccess:command]; 263 | } 264 | 265 | #pragma mark - Unread Conversation Count 266 | 267 | - (void)unreadConversationCount:(CDVInvokedUrlCommand*)command { 268 | NSUInteger count = [Intercom unreadConversationCount]; 269 | CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsNSUInteger:count]; 270 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 271 | } 272 | 273 | 274 | #pragma mark - Push Notifications 275 | 276 | - (void)registerForPush:(CDVInvokedUrlCommand*)command { 277 | UIApplication *application = [UIApplication sharedApplication]; 278 | [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionAlert 279 | | UNAuthorizationOptionBadge 280 | | UNAuthorizationOptionSound) 281 | completionHandler:^(BOOL granted, NSError * _Nullable error) {}]; 282 | [application registerForRemoteNotifications]; 283 | [self sendSuccess:command]; 284 | } 285 | 286 | - (void)sendPushTokenToIntercom:(CDVInvokedUrlCommand*)command { 287 | NSLog(@"[Intercom-Cordova] INFO - sendPushTokenToIntercom called. Ignored by iOS as we automatically send the token when the app is registered for push."); 288 | } 289 | 290 | 291 | 292 | 293 | 294 | #pragma mark - User attributes 295 | 296 | - (ICMUserAttributes *)userAttributesForDictionary:(NSDictionary *)attributesDict { 297 | ICMUserAttributes *attributes = [ICMUserAttributes new]; 298 | if ([self stringValueForKey:@"email" inDictionary:attributesDict]) { 299 | attributes.email = [self stringValueForKey:@"email" inDictionary:attributesDict]; 300 | } 301 | if ([self stringValueForKey:@"user_id" inDictionary:attributesDict]) { 302 | attributes.userId = [self stringValueForKey:@"user_id" inDictionary:attributesDict]; 303 | } 304 | if ([self stringValueForKey:@"name" inDictionary:attributesDict]) { 305 | attributes.name = [self stringValueForKey:@"name" inDictionary:attributesDict]; 306 | } 307 | if ([self stringValueForKey:@"phone" inDictionary:attributesDict]) { 308 | attributes.phone = [self stringValueForKey:@"phone" inDictionary:attributesDict]; 309 | } 310 | if ([self stringValueForKey:@"language_override" inDictionary:attributesDict]) { 311 | attributes.languageOverride = [self stringValueForKey:@"language_override" inDictionary:attributesDict]; 312 | } 313 | if ([self dateValueForKey:@"signed_up_at" inDictionary:attributesDict]) { 314 | attributes.signedUpAt = [self dateValueForKey:@"signed_up_at" inDictionary:attributesDict]; 315 | } 316 | if ([self stringValueForKey:@"unsubscribed_from_emails" inDictionary:attributesDict]) { 317 | attributes.unsubscribedFromEmails = [self stringValueForKey:@"unsubscribed_from_emails" inDictionary:attributesDict]; 318 | } 319 | if (attributesDict[@"custom_attributes"]) { 320 | attributes.customAttributes = attributesDict[@"custom_attributes"]; 321 | } 322 | if (attributesDict[@"companies"]) { 323 | NSMutableArray *companies = [NSMutableArray new]; 324 | for (NSDictionary *companyDict in attributesDict[@"companies"]) { 325 | [companies addObject:[self companyForDictionary:companyDict]]; 326 | } 327 | attributes.companies = companies; 328 | } 329 | return attributes; 330 | } 331 | 332 | - (ICMCompany *)companyForDictionary:(NSDictionary *)attributesDict { 333 | ICMCompany *company = [ICMCompany new]; 334 | if ([self stringValueForKey:@"company_id" inDictionary:attributesDict]) { 335 | company.companyId = [self stringValueForKey:@"company_id" inDictionary:attributesDict]; 336 | } 337 | if ([self stringValueForKey:@"name" inDictionary:attributesDict]) { 338 | company.name = [self stringValueForKey:@"name" inDictionary:attributesDict]; 339 | } 340 | if ([self dateValueForKey:@"created_at" inDictionary:attributesDict]) { 341 | company.createdAt = [self dateValueForKey:@"created_at" inDictionary:attributesDict]; 342 | } 343 | if ([self numberValueForKey:@"monthly_spend" inDictionary:attributesDict]) { 344 | company.monthlySpend = [self numberValueForKey:@"monthly_spend" inDictionary:attributesDict]; 345 | } 346 | if ([self stringValueForKey:@"plan" inDictionary:attributesDict]) { 347 | company.plan = [self stringValueForKey:@"plan" inDictionary:attributesDict]; 348 | } 349 | if (attributesDict[@"custom_attributes"]) { 350 | company.customAttributes = attributesDict[@"custom_attributes"]; 351 | } 352 | return company; 353 | } 354 | 355 | - (NSString *)stringValueForKey:(NSString *)key inDictionary:(NSDictionary *)dictionary { 356 | NSString *value = dictionary[key]; 357 | if ([value isKindOfClass:[NSString class]]) { 358 | return value; 359 | } 360 | if ([value isKindOfClass:[NSNumber class]]) { 361 | return [NSString stringWithFormat:@"%@", value]; 362 | } 363 | if ([value isKindOfClass:[NSNull class]]) { 364 | return [ICMUserAttributes nullStringAttribute]; 365 | } 366 | return nil; 367 | } 368 | 369 | - (NSString *)stringValueForDictionaries:(NSArray *)dictionaries { 370 | NSError *error; 371 | NSString *jsonString; 372 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionaries options:0 error:&error]; 373 | if (!jsonData) { 374 | NSLog(@"Got an error: %@", error); 375 | } else { 376 | jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 377 | } 378 | return jsonString; 379 | } 380 | 381 | 382 | - (NSString *)stringValueForDictionary:(NSDictionary *)dictionary { 383 | NSError *error; 384 | NSString *jsonString; 385 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error]; 386 | if (!jsonData) { 387 | NSLog(@"Got an error: %@", error); 388 | } else { 389 | jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 390 | } 391 | return jsonString; 392 | } 393 | 394 | - (NSNumber *)numberValueForKey:(NSString *)key inDictionary:(NSDictionary *)dictionary { 395 | NSNumber *value = dictionary[key]; 396 | if ([value isKindOfClass:[NSNumber class]]) { 397 | return value; 398 | } 399 | if ([value isKindOfClass:[NSNull class]]) { 400 | return [ICMUserAttributes nullNumberAttribute]; 401 | } 402 | return nil; 403 | } 404 | 405 | - (NSDate *)dateValueForKey:(NSString *)key inDictionary:(NSDictionary *)dictionary { 406 | NSNumber *value = dictionary[key]; 407 | if ([value isKindOfClass:[NSNumber class]]) { 408 | return [NSDate dateWithTimeIntervalSince1970:[value doubleValue]]; 409 | } 410 | if ([value isKindOfClass:[NSNull class]]) { 411 | return [ICMUserAttributes nullDateAttribute]; 412 | } 413 | return nil; 414 | } 415 | 416 | 417 | #pragma mark - Private methods 418 | 419 | - (void)sendSuccess:(CDVInvokedUrlCommand*)command { 420 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; 421 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 422 | } 423 | 424 | - (void)sendFailure:(CDVInvokedUrlCommand*)command withError:(NSError *)error { 425 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR 426 | messageAsNSInteger:error.code]; 427 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 428 | } 429 | 430 | @end 431 | -------------------------------------------------------------------------------- /intercom-plugin/www/intercom.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const Space = { 4 | Home: "HOME", 5 | HelpCenter: "HELP_CENTER", 6 | Messages: "MESSAGES", 7 | Tickets: "TICKETS", 8 | }; 9 | 10 | var intercom = { 11 | 12 | /** 13 | * Login a user with identifiable information. 14 | * Valid identifiers are `userId` and `email` which must be set in an object. 15 | * @param options The object that contains the user's `email` or `userId`. 16 | */ 17 | loginUserWithUserAttributes: function(options, success, error) { 18 | cordova.exec(success, error, 'Intercom', 'loginUserWithUserAttributes', [options]); 19 | }, 20 | 21 | /** 22 | * Login a unidentified user. 23 | * This is a user that doesn't have any identifiable information such as a `userId` or `email`. 24 | */ 25 | loginUnidentifiedUser: function(options, success, error) { 26 | cordova.exec(success, error, 'Intercom', 'loginUnidentifiedUser', []); 27 | }, 28 | 29 | /** 30 | * Log a user out of their Intercom session. 31 | * This will dismiss any Intercom UI and clear Intercom's local cache. 32 | */ 33 | logout: function(success, error) { 34 | cordova.exec(success, error, 'Intercom', 'logout', []); 35 | }, 36 | 37 | /** 38 | * Determines if there is currently a user logged in. 39 | */ 40 | isUserLoggedIn: function(success, error) { 41 | cordova.exec(success, error, 'Intercom', 'isUserLoggedIn', []); 42 | }, 43 | 44 | /** 45 | * Fetches the user attribtues of the currently logged in user. 46 | * 47 | * @return A user registration object. 48 | */ 49 | fetchLoggedInUserAttributes: function(success, error) { 50 | cordova.exec(success, error, 'Intercom', 'fetchLoggedInUserAttributes', []); 51 | }, 52 | 53 | /** 54 | * Set `hash` string if you are using Identity Verification for your Intercom workspace. 55 | * @note This should be called before any user login takes place. 56 | * 57 | * Identity Verification helps to make sure that conversations between you and your users are kept private, and that one 58 | * user can't impersonate another. If Identity Verification is enabled for your app, Intercom will sign all requests 59 | * going to the Intercom servers with tokens. It requires your mobile application to have its own server which authenticates the app's users, 60 | * and which can store a secret. 61 | * 62 | * @see More information on Identity Verification can be found {@link https://developers.intercom.com/installing-intercom/cordova-phonegap/identity-verification/ here} 63 | * @param secureHash A HMAC digest of the user ID or email. 64 | */ 65 | setUserHash: function(secureHash, success, error) { 66 | cordova.exec(success, error, 'Intercom', 'setUserHash', [secureHash]); 67 | }, 68 | 69 | /** 70 | * Update a user in Intercom with data specified in an object. 71 | * 72 | * @param attributes The object with the user data. 73 | */ 74 | updateUser: function(attributes, success, error) { 75 | cordova.exec(success, error, 'Intercom', 'updateUser', [attributes]); 76 | }, 77 | 78 | /** 79 | * Log an event with a given name and metaData. 80 | * You can log events in Intercom based on user actions in your app. 81 | * 82 | * @param eventName The name of the event. 83 | * @param metaData Metadata Objects support a few simple types that Intercom can present on your behalf, 84 | * see the @{https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Data-Events/data_event/ Intercom API docs} 85 | */ 86 | logEvent: function(eventName, metaData, success, error) { 87 | cordova.exec(success, error, 'Intercom', 'logEvent', [eventName, metaData]); 88 | }, 89 | 90 | /** 91 | * Present Intercom as a modal overlay in your app. 92 | * The `Home` space is displayed by default. 93 | */ 94 | present: function(success, error) { 95 | cordova.exec(success, error, 'Intercom', 'present', []); 96 | }, 97 | 98 | /** 99 | * Present an Intercom `space` as a modal overlay in your app 100 | * @see {@link Space} for a list of valid spaces. 101 | * 102 | * @param space The Intercom space to be presented. 103 | */ 104 | presentSpace: function(space, success, error) { 105 | cordova.exec(success, error, 'Intercom', 'presentIntercomSpace', [space]); 106 | }, 107 | 108 | /** 109 | * Present Intercom content. 110 | * 111 | * An IntercomContent object. 112 | */ 113 | presentContent: function(content, success, error) { 114 | cordova.exec(success, error, 'Intercom', 'presentContent', [content]); 115 | }, 116 | 117 | /** 118 | * Present the message composer. 119 | * 120 | * @param initialMessage An optional message that is used to pre-populate the composer with some text. 121 | */ 122 | presentMessageComposer: function(initialMessage, success, error) { 123 | cordova.exec(success, error, 'Intercom', 'presentMessageComposer', [initialMessage]); 124 | }, 125 | 126 | /** 127 | * Fetch all Help Center collections. 128 | * 129 | * @return An array of HelpCenterCollection objects. 130 | */ 131 | fetchHelpCenterCollections: function(success, error) { 132 | cordova.exec(success, error, 'Intercom', 'fetchHelpCenterCollections', []); 133 | }, 134 | 135 | /** 136 | * Fetch the contents of a Help Center collection. 137 | * 138 | * @param collectionId The ID of the Help Center collection. 139 | * 140 | * @return A HelpCenterCollectionContent object. 141 | */ 142 | fetchHelpCenterCollection: function(collectionId, success, error) { 143 | cordova.exec(success, error, 'Intercom', 'fetchHelpCenterCollection', [collectionId]); 144 | }, 145 | 146 | /** 147 | * Search the Help Center. 148 | * 149 | * @param searchTerm The search term. 150 | * 151 | * @return An array of HelpCenterArticleSearchResult objects. 152 | */ 153 | searchHelpCenter: function(searchTerm, success, error) { 154 | cordova.exec(success, error, 'Intercom', 'searchHelpCenter', [searchTerm]); 155 | }, 156 | 157 | 158 | /** 159 | * Fetch the current number of unread conversations for the logged in User. 160 | * @return The number of unread conversations. 161 | */ 162 | unreadConversationCount: function(success, error) { 163 | cordova.exec(success, error, 'Intercom', 'unreadConversationCount', []); 164 | }, 165 | 166 | VISIBLE : "VISIBLE", 167 | GONE : "GONE", 168 | 169 | /** 170 | * Show or hide the Intercom Launcher in your app. 171 | * @note The Launcher is hidden by default. 172 | * 173 | * @param visibility A boolean indicating if the Intercom Launcher should be visible. 174 | */ 175 | setLauncherVisibility: function(visibility, success, error) { 176 | cordova.exec(success, error, 'Intercom', 'setLauncherVisibility', [visibility]); 177 | }, 178 | 179 | /** 180 | * Show or hide the Intercom InApp Messages in your app. 181 | * @note All InApp Messages are visible by default. 182 | * 183 | * @param visibility A boolean indicating if the InApps should be visible. 184 | */ 185 | setInAppMessageVisibility: function(visibility, success, error) { 186 | cordova.exec(success, error, 'Intercom', 'setInAppMessageVisibility', [visibility]); 187 | }, 188 | 189 | /** 190 | * Hide all Intercom windows that are currently displayed. 191 | * This will hide the Messenger, Help Center, Articles, and in-product messages (eg. Mobile Carousels, chats, and posts). 192 | */ 193 | hideIntercom: function(success, error) { 194 | cordova.exec(success, error, 'Intercom', 'hideIntercom', []); 195 | }, 196 | 197 | /** 198 | * Set a fixed bottom padding for in app messages and the Intercom Launcher. 199 | * @param bottomPadding The size of the bottom padding in points. 200 | */ 201 | setBottomPadding: function(bottomPadding, success, error) { 202 | cordova.exec(success, error, 'Intercom', 'setBottomPadding', [bottomPadding]); 203 | }, 204 | 205 | /** 206 | * Register for push notifications 207 | * @note This function is only available for iOS. 208 | */ 209 | registerForPush: function(success, error) { 210 | cordova.exec(success, error, 'Intercom', 'registerForPush', []); 211 | }, 212 | 213 | /** 214 | * Send a device token to Intercom to enable push notifications to be sent to the User. 215 | * @param token The device token to send to the server. 216 | * 217 | * @note This function is only available for Android. 218 | */ 219 | sendPushTokenToIntercom: function(token, success, error) { 220 | cordova.exec(success, error, 'Intercom', 'sendPushTokenToIntercom', [token]); 221 | }, 222 | 223 | 224 | /** 225 | * @deprecated 226 | */ 227 | registerIdentifiedUser: function(options, success, error) { 228 | cordova.exec(success, error, 'Intercom', 'loginUserWithUserAttributes', [options]); 229 | console.warn('registerIdentifiedUser() is deprecated and will be removed in a future release. Please use loginUserWithUserAttributes()'); 230 | }, 231 | 232 | /** 233 | * @deprecated 234 | */ 235 | registerUnidentifiedUser: function(options, success, error) { 236 | cordova.exec(success, error, 'Intercom', 'loginUnidentifiedUser', []); 237 | console.warn('registerUnidentifiedUser() is deprecated and will be removed in a future release. Please use loginUnidentifiedUser()'); 238 | }, 239 | 240 | /** 241 | * @deprecated 242 | */ 243 | reset: function(success, error) { 244 | cordova.exec(success, error, 'Intercom', 'logout', []); 245 | console.warn('reset() is deprecated and will be removed in a future release. Please use logout()'); 246 | }, 247 | 248 | /** 249 | * @deprecated 250 | */ 251 | displayMessenger: function(success, error) { 252 | cordova.exec(success, error, 'Intercom', 'present', []); 253 | console.warn('displayMessenger() is deprecated and will be removed in a future release. Please use present()'); 254 | }, 255 | 256 | /** 257 | * @deprecated 258 | */ 259 | displayHelpCenter: function(success, error) { 260 | cordova.exec(success, error, 'Intercom', 'presentIntercomSpace', [Space.HelpCenter]); 261 | console.warn('displayHelpCenter() is deprecated and will be removed in a future release. Please use present(intercom.Space.HelpCenter)'); 262 | }, 263 | 264 | /** 265 | * @deprecated 266 | */ 267 | displayMessageComposerWithInitialMessage: function(initialMessage, success, error) { 268 | cordova.exec(success, error, 'Intercom', 'presentMessageComposer', [initialMessage]); 269 | console.warn('displayMessageComposerWithInitialMessage(initialMessage) is deprecated and will be removed in a future release. Please use presentMessageComposer(initialMessage)') 270 | }, 271 | 272 | /** 273 | * @deprecated 274 | */ 275 | displayMessageComposer: function(success, error) { 276 | cordova.exec(success, error, 'Intercom', 'presentMessageComposer', []); 277 | console.warn('displayMessageComposer() is deprecated and will be removed in a future release. Please use presentMessageComposer()') 278 | }, 279 | 280 | /** 281 | * @deprecated 282 | */ 283 | displayHelpCenterCollections: function(collectionIds, success, error) { 284 | var collections = intercomContent.helpCenterCollectionsWithIds(collectionIds); 285 | cordova.exec(success, error, 'Intercom', 'presentContent', [collections]); 286 | console.warn('displayHelpCenterCollections() is deprecated and will be removed in a future release. Please use intercom.presentContent(intercomContent.helpCenterCollectionsWithIds([ids]))') 287 | }, 288 | 289 | /** 290 | * @deprecated 291 | */ 292 | displayCarousel: function(carouselId, success, error) { 293 | var carousel = intercomContent.carouselWithCarouselId(carouselId) 294 | cordova.exec(success, error, 'Intercom', 'presentContent', [carousel]); 295 | console.warn('displayCarousel() is deprecated and will be removed in a future release. Please use intercom.presentContent(intercomContent.carouselWithCarouselId(carouselId));'); 296 | }, 297 | 298 | /** 299 | * @deprecated 300 | */ 301 | displayArticle: function(articleId, success, error) { 302 | var article = intercomContent.articleWithArticleId(articleId) 303 | cordova.exec(success, error, 'Intercom', 'presentContent', [article]); 304 | console.warn('displayArticle() is deprecated and will be removed in a future release. Please use intercom.presentContent(intercomContent.articleWithArticleId(articleId));'); 305 | }, 306 | 307 | /** 308 | * @deprecated 309 | */ 310 | displaySurvey: function(surveyId, success, error) { 311 | var survey = intercomContent.surveyWithSurveyId(surveyId) 312 | cordova.exec(success, error, 'Intercom', 'presentContent', [survey]); 313 | console.warn('displaySurvey() is deprecated and will be removed in a future release. Please use intercom.presentContent(intercomContent.surveyWithSurveyId(surveyId));'); 314 | 315 | }, 316 | // Enable the Space constant to be used by `intercom.space.` 317 | space: Space 318 | } 319 | 320 | module.exports = intercom; 321 | 322 | -------------------------------------------------------------------------------- /intercom-plugin/www/intercomContent.js: -------------------------------------------------------------------------------- 1 | const ContentType = { 2 | Article: "ARTICLE", 3 | Carousel: "CAROUSEL", 4 | Survey: "SURVEY", 5 | HelpCenterCollections: "HELP_CENTER_COLLECTIONS", 6 | Conversation: "CONVERSATION", 7 | }; 8 | 9 | var IntercomContent = { 10 | articleWithArticleId(articleId) { 11 | let articleContent = {}; 12 | articleContent.type = ContentType.Article; 13 | articleContent.id = articleId; 14 | return articleContent; 15 | }, 16 | 17 | carouselWithCarouselId(carouselId) { 18 | let carouselContent = {}; 19 | carouselContent.type = ContentType.Carousel; 20 | carouselContent.id = carouselId; 21 | return carouselContent; 22 | }, 23 | 24 | surveyWithSurveyId(surveyId) { 25 | let surveyContent = {}; 26 | surveyContent.type = ContentType.Survey; 27 | surveyContent.id = surveyId; 28 | return surveyContent; 29 | }, 30 | 31 | helpCenterCollectionsWithIds(collectionIds) { 32 | let helpCenterCollectionsContent = {}; 33 | helpCenterCollectionsContent.type = ContentType.HelpCenterCollections; 34 | helpCenterCollectionsContent.ids = collectionIds; 35 | return helpCenterCollectionsContent; 36 | }, 37 | 38 | conversationWithConversationId(conversationId) { 39 | let conversationContent = {}; 40 | conversationContent.type = ContentType.Conversation; 41 | conversationContent.id = conversationId; 42 | return conversationContent; 43 | }, 44 | }; 45 | 46 | module.exports = IntercomContent; 47 | -------------------------------------------------------------------------------- /runAndroidSample.sh: -------------------------------------------------------------------------------- 1 | clear 2 | jenv global 1.8 3 | export ANDROID_SDK_ROOT=~/Library/Android/sdk 4 | export PATH=${PATH}:${ANDROID_HOME}/tools 5 | export PATH=${PATH}:${ANDROID_HOME}/platform-tools 6 | cd Example 7 | cordova plugin remove ../intercom-plugin 8 | cordova plugin add ../intercom-plugin 9 | cordova platform remove android 10 | cordova platform add android@13.0.0 --save 11 | cordova run android --stacktrace -------------------------------------------------------------------------------- /runiOSSample.sh: -------------------------------------------------------------------------------- 1 | clear 2 | cd Example 3 | cordova plugin remove ../intercom-plugin 4 | cordova plugin add ../intercom-plugin --link 5 | cordova platform remove ios 6 | cordova platform add ios --save 7 | cordova run ios --stacktrace 8 | --------------------------------------------------------------------------------