chore(inbox): re-enable Instagram inbox creation (#15042)

Instagram inbox creation is available again on Chatwoot Cloud. Users can
discover and connect Instagram during onboarding or from Add Inbox,
while WhatsApp restrictions and existing-inbox Instagram advisories
remain unchanged.

Closes https://linear.app/chatwoot/issue/CW-7549/enable-instagram

## How to test

1. On Chatwoot Cloud, open Add Inbox and confirm Instagram can be
selected.
2. Confirm **Continue with Instagram** is enabled and starts the OAuth
flow.
3. In onboarding, confirm Instagram is displayed and can start OAuth.
4. Confirm WhatsApp embedded signup remains restricted.

## What changed

- Removed the Cloud-only Instagram filter and OAuth guard from
onboarding.
- Re-enabled the regular Instagram inbox creation action on Cloud.
- Removed the obsolete “Instagram inbox creation is temporarily
unavailable” copy.
- Updated the onboarding expectation for Chatwoot Cloud.

---------

Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com>
This commit is contained in:
Muhsin Keloth
2026-07-16 20:28:49 +04:00
committed by GitHub
co-authored by Muhsin
parent 9749a3dc96
commit 5e811eab99
5 changed files with 30 additions and 45 deletions
@@ -59,7 +59,6 @@
"ERROR_AUTH": "There was an error connecting to Instagram, please try again",
"NEW_INBOX_SUGGESTION": "This Instagram account was previously linked to a different inbox and has now been migrated here. All new messages will appear here. The old inbox will no longer be able to send or receive messages for this account.",
"DUPLICATE_INBOX_BANNER": "This Instagram account was migrated to the new Instagram channel inbox. You wont be able to send/receive Instagram messages from this inbox anymore.",
"RESTRICTED_WARNING": "Instagram inbox creation is temporarily unavailable due to current Instagram platform restrictions. Well restore support as soon as possible.",
"SETTINGS_RESTRICTED_WARNING": "Instagram is currently restricted. Some messages or actions may be delayed or unavailable while we restore full support.",
"STATUS_LINK": "View status update"
},
@@ -1,4 +1,6 @@
import { useMapGetter } from 'dashboard/composables/store';
import { useAccount } from 'dashboard/composables/useAccount';
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
// OAuth/SDK channels need installation-level app credentials to be usable. When
// the credential is missing the channel is "not configured" and is hidden from
@@ -8,6 +10,7 @@ import { useMapGetter } from 'dashboard/composables/store';
export function useChannelConfig() {
const globalConfig = useMapGetter('globalConfig/get');
const isOnChatwootCloud = useMapGetter('globalConfig/isOnChatwootCloud');
const { isCloudFeatureEnabled } = useAccount();
const installationConfig = window.chatwootConfig || {};
const CHANNEL_CONFIGURED = {
@@ -20,7 +23,8 @@ export function useChannelConfig() {
Boolean(installationConfig.whatsappConfigurationId),
facebook: () => Boolean(installationConfig.fbAppId),
instagram: () =>
!isOnChatwootCloud.value && Boolean(installationConfig.instagramAppId),
Boolean(installationConfig.instagramAppId) &&
isCloudFeatureEnabled(FEATURE_FLAGS.CHANNEL_INSTAGRAM),
tiktok: () => Boolean(installationConfig.tiktokAppId),
gmail: () => Boolean(installationConfig.googleOAuthClientId),
outlook: () => Boolean(globalConfig.value.azureAppId),
@@ -1,7 +1,6 @@
import { useI18n } from 'vue-i18n';
import { useAlert } from 'dashboard/composables';
import { useStore } from 'dashboard/composables/store';
import { useAccount } from 'dashboard/composables/useAccount';
import { useWhatsappEmbeddedSignup } from 'dashboard/composables/useWhatsappEmbeddedSignup';
import { parseAPIErrorResponse } from 'dashboard/store/utils/api';
import googleClient from 'dashboard/api/channel/googleClient';
@@ -24,17 +23,11 @@ export function useChannelConnect() {
const { t } = useI18n();
const store = useStore();
const { runEmbeddedSignup } = useWhatsappEmbeddedSignup();
const { isOnChatwootCloud } = useAccount();
const connectViaOAuth = async provider => {
const client = OAUTH_CLIENTS[provider];
if (!client) return;
if (provider === 'instagram' && isOnChatwootCloud.value) {
useAlert(t('INBOX_MGMT.ADD.INSTAGRAM.RESTRICTED_WARNING'));
return;
}
try {
const {
data: { url },
@@ -13,6 +13,7 @@ vi.mock('vue-router');
// channel_type, social ordering) derived from CHANNEL_LIST.
const mountComposable = ({
brandInfo,
features = { channel_instagram: true },
inboxes = [],
isOnChatwootCloud = false,
} = {}) => {
@@ -30,8 +31,11 @@ const mountComposable = ({
getters: {
getAccount: () => () => ({
id: 1,
features,
custom_attributes: { brand_info: brandInfo },
}),
isFeatureEnabledonAccount: () => (_accountId, feature) =>
Boolean(features[feature]),
},
},
inboxes: {
@@ -207,7 +211,7 @@ describe('useDetectedChannels', () => {
]);
});
it('hides Instagram from onboarding on Chatwoot Cloud', () => {
it('keeps Instagram available on Chatwoot Cloud when enabled for the account', () => {
const { displayedChannels } = mountComposable({
isOnChatwootCloud: true,
brandInfo: {
@@ -218,6 +222,24 @@ describe('useDetectedChannels', () => {
},
});
expect(displayedChannels.value.map(channel => channel.type)).toEqual([
'instagram',
'tiktok',
]);
});
it('hides Instagram when disabled for the account', () => {
const { displayedChannels } = mountComposable({
features: { channel_instagram: false },
isOnChatwootCloud: true,
brandInfo: {
socials: [
{ type: 'instagram', url: 'https://instagram.com/acme' },
{ type: 'tiktok', url: 'https://tiktok.com/@acme' },
],
},
});
expect(displayedChannels.value.map(channel => channel.type)).toEqual([
'tiktok',
]);
@@ -1,23 +1,15 @@
<script setup>
import { computed, ref, onMounted } from 'vue';
import { ref, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import instagramClient from 'dashboard/api/channel/instagramClient';
import Button from 'dashboard/components-next/button/Button.vue';
import Banner from 'dashboard/components-next/banner/Banner.vue';
import Icon from 'dashboard/components-next/icon/Icon.vue';
import { useAccount } from 'dashboard/composables/useAccount';
import { META_RESTRICTION_STATUS_URL } from 'dashboard/constants/globals';
const { t } = useI18n();
const { isOnChatwootCloud } = useAccount();
const hasError = ref(false);
const errorStateMessage = ref('');
const errorStateDescription = ref('');
const isRequestingAuthorization = ref(false);
const isInstagramConnectionRestricted = computed(() => {
return isOnChatwootCloud.value;
});
onMounted(() => {
const urlParams = new URLSearchParams(window.location.search);
@@ -76,36 +68,11 @@ const requestAuthorization = async () => {
class="text-white !rounded-full !px-6 bg-gradient-to-r from-[#833AB4] via-[#FD1D1D] to-[#FCAF45]"
lg
icon="i-ri-instagram-line"
:disabled="
isRequestingAuthorization || isInstagramConnectionRestricted
"
:disabled="isRequestingAuthorization"
:is-loading="isRequestingAuthorization"
:label="$t('INBOX_MGMT.ADD.INSTAGRAM.CONTINUE_WITH_INSTAGRAM')"
@click="requestAuthorization()"
/>
<Banner
v-if="isInstagramConnectionRestricted"
color="amber"
class="w-full max-w-2xl mt-6"
>
<div class="flex items-start gap-3 text-left">
<Icon
icon="i-lucide-triangle-alert"
class="flex-shrink-0 size-4 mt-0.5"
/>
<span>
{{ $t('INBOX_MGMT.ADD.INSTAGRAM.RESTRICTED_WARNING') }}
<a
:href="META_RESTRICTION_STATUS_URL"
class="link underline"
rel="noopener noreferrer nofollow"
target="_blank"
>
{{ $t('INBOX_MGMT.ADD.INSTAGRAM.STATUS_LINK') }}
</a>
</span>
</div>
</Banner>
</div>
</div>
</div>