diff --git a/ee/app/assets/javascripts/integrations/edit/components/google_cloud_iam/constants.js b/ee/app/assets/javascripts/integrations/edit/components/google_cloud_iam/constants.js
new file mode 100644
index 0000000000000000000000000000000000000000..80b3e6ffd4953b357656e082916cde39b32d0d47
--- /dev/null
+++ b/ee/app/assets/javascripts/integrations/edit/components/google_cloud_iam/constants.js
@@ -0,0 +1,5 @@
+export const STATE_EMPTY = 'empty';
+export const STATE_FORM = 'form';
+export const STATE_GUIDED = 'guided';
+export const STATE_INITIAL = 'initial';
+export const STATE_MANUAL = 'manual';
diff --git a/ee/app/assets/javascripts/integrations/edit/components/google_cloud_iam/empty_state.vue b/ee/app/assets/javascripts/integrations/edit/components/google_cloud_iam/empty_state.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6f57128ddcaa3671228a30aa179ac138e469358e
--- /dev/null
+++ b/ee/app/assets/javascripts/integrations/edit/components/google_cloud_iam/empty_state.vue
@@ -0,0 +1,70 @@
+<script>
+import { GlButton, GlEmptyState, GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
+import EmptyAdminAppsSvg from '@gitlab/svgs/dist/illustrations/empty-state/empty-admin-apps-md.svg';
+import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
+import { STATE_GUIDED, STATE_MANUAL } from './constants';
+
+export default {
+  components: {
+    GlButton,
+    GlIcon,
+    GlEmptyState,
+    GlLink,
+    InviteMembersTrigger,
+    GlSprintf,
+  },
+  methods: {
+    show(type) {
+      this.$emit('show', type);
+    },
+  },
+  EmptyAdminAppsSvg,
+  STATE_GUIDED,
+  STATE_MANUAL,
+};
+</script>
+
+<template>
+  <gl-empty-state
+    :svg-path="$options.EmptyAdminAppsSvg"
+    :title="s__('GoogleCloudPlatformService|Connect to Google Cloud')"
+  >
+    <template #description>
+      <gl-sprintf
+        :message="
+          s__(
+            'GoogleCloudPlatformService|Connect to Google Cloud with workload identity federation. Select %{strongStart}Guided setup%{strongEnd} if you can manage workload identity federation in Google Cloud. %{linkStart}What are the required permissions?%{linkEnd}',
+          )
+        "
+      >
+        <template #strong="{ content }">
+          <strong>{{ content }}</strong>
+        </template>
+        <template #link="{ content }">
+          <gl-link
+            target="_blank"
+            rel="noopener noreferrer"
+            href="https://cloud.google.com/iam/docs/manage-workload-identity-pools-providers#required-roles"
+          >
+            {{ content }}
+            <gl-icon name="external-link" :aria-label="__('(external link)')" />
+          </gl-link>
+        </template>
+      </gl-sprintf>
+    </template>
+    <template #actions>
+      <div class="gl-display-flex gl-gap-3">
+        <gl-button variant="confirm" @click="show($options.STATE_GUIDED)">{{
+          s__('GoogleCloudPlatformService|Guided setup')
+        }}</gl-button>
+        <gl-button @click="show($options.STATE_MANUAL)">{{
+          s__('GoogleCloudPlatformService|Manual setup')
+        }}</gl-button>
+        <invite-members-trigger
+          :display-text="s__('GoogleCloudPlatformService|Invite member to set up')"
+          trigger-source="google_cloud_artifact_registry_setup"
+        />
+      </div>
+    </template>
+  </gl-empty-state>
+</template>
diff --git a/ee/app/assets/javascripts/integrations/edit/components/google_cloud_iam/guided_setup.vue b/ee/app/assets/javascripts/integrations/edit/components/google_cloud_iam/guided_setup.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6feddc337a37926e3f38f18cf4feb790d998e760
--- /dev/null
+++ b/ee/app/assets/javascripts/integrations/edit/components/google_cloud_iam/guided_setup.vue
@@ -0,0 +1,154 @@
+<script>
+import { GlButton, GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import { STATE_MANUAL } from './constants';
+
+export default {
+  components: {
+    GlButton,
+    GlIcon,
+    GlLink,
+    GlSprintf,
+    ClipboardButton,
+  },
+  curlLine: `export GL_PAT=<your_access_token>
+curl --request GET
+  --data 'google_cloud_project_id=<your_google_cloud_project_id>'
+  --header "PRIVATE-TOKEN: $GL_PAT"
+  --url "https://gitlab.com/api/v4/projects/<your_gitlab_project_id>/google_cloud/setup/wlif.sh"
+| bash`,
+  STATE_MANUAL,
+};
+</script>
+
+<template>
+  <div>
+    <h3>{{ s__('GoogleCloudPlatformService|Guided setup') }}</h3>
+    <p>
+      <gl-sprintf
+        :message="
+          s__(
+            'GoogleCloudPlatformService|%{linkStart}Switch to the manual setup%{linkEnd} if you cannot manage workload identity federation in Google Cloud. %{link2Start}What are the required permissions?%{link2End}',
+          )
+        "
+      >
+        <template #link="{ content }">
+          <gl-link @click="$emit('show', $options.STATE_MANUAL)">{{ content }}</gl-link>
+        </template>
+        >
+        <template #link2="{ content }">
+          <gl-link
+            target="_blank"
+            rel="noopener noreferrer"
+            href="https://cloud.google.com/iam/docs/manage-workload-identity-pools-providers#required-roles"
+          >
+            {{ content }}
+            <gl-icon name="external-link" :aria-label="__('(external link)')" />
+          </gl-link>
+        </template>
+      </gl-sprintf>
+    </p>
+
+    <h4>{{ s__('GoogleCloudPlatformService|Instructions') }}</h4>
+    <p>
+      <gl-sprintf
+        :message="
+          s__(
+            'GoogleCloudPlatformService|Before you begin, %{linkStart}install the Google Cloud CLI%{linkEnd}.',
+          )
+        "
+      >
+        <template #link="{ content }">
+          <gl-link
+            target="_blank"
+            rel="noopener noreferrer"
+            href="https://cloud.google.com/sdk/docs/install#installation_instructions"
+          >
+            {{ content }}
+            <gl-icon name="external-link" :aria-label="__('(external link)')" />
+          </gl-link>
+        </template>
+      </gl-sprintf>
+    </p>
+    <p>
+      {{
+        s__(
+          'GoogleCloudPlatformService|Run the following command to set up and connect to your Google Cloud project with workload identity federation.',
+        )
+      }}
+    </p>
+    <ul>
+      <li>
+        <gl-sprintf
+          :message="
+            s__(
+              'GoogleCloudPlatformService|Replace %{codeStart}your_access_token%{codeEnd} with a %{linkStart}new personal access token%{linkEnd} with the %{strongStart}api%{strongEnd} scope. This token sets up your Google Cloud IAM integration in GitLab.',
+            )
+          "
+        >
+          <template #code="{ content }">
+            <code>&lt;{{ content }}&gt;</code>
+          </template>
+          <template #link="{ content }">
+            <gl-link target="_blank" href="/-/user_settings/personal_access_tokens">{{
+              content
+            }}</gl-link>
+          </template>
+          <template #strong="{ content }">
+            <strong>{{ content }}</strong>
+          </template>
+        </gl-sprintf>
+      </li>
+      <li>
+        <gl-sprintf
+          :message="
+            s__(
+              'GoogleCloudPlatformService|Replace %{codeStart}your_google_cloud_project_id%{codeEnd} with your Google Cloud project ID. To improve security, use a dedicated project for identity management, separate from resources and CI/CD projects. %{linkStart}Where’s my project ID?%{linkEnd}',
+            )
+          "
+        >
+          <template #code="{ content }">
+            <code>&lt;{{ content }}&gt;</code>
+          </template>
+          <template #link="{ content }">
+            <gl-link
+              href="https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects"
+              target="_blank"
+              rel="noopener noreferrer"
+              >{{ content }}
+              <gl-icon name="external-link" :aria-label="__('(external link)')" />
+            </gl-link>
+          </template>
+        </gl-sprintf>
+      </li>
+      <li>{{ s__('GoogleCloudPlatformService|You might be prompted to sign in to Google.') }}</li>
+    </ul>
+    <div class="position-relative">
+      <pre class="gl-w-full">{{ $options.curlLine }}</pre>
+      <clipboard-button
+        :text="$options.curlLine"
+        :title="__('Copy')"
+        category="tertiary"
+        class="gl-display-none gl-md-display-flex position-absolute position-top-0 position-right-0 gl-m-3"
+      />
+    </div>
+    <p>
+      <gl-sprintf
+        :message="
+          s__(
+            'GoogleCloudPlatformService|After Google Cloud workload identity federation has been set up, select %{strongStart}Continue%{strongEnd}.',
+          )
+        "
+      >
+        <template #strong="{ content }">
+          <strong>{{ content }}</strong>
+        </template>
+      </gl-sprintf>
+    </p>
+
+    <div class="gl-mt-6 gl-display-flex gl-gap-3">
+      <gl-button variant="confirm" @click="$emit('show', 'form')">{{ __('Continue') }}</gl-button>
+      <gl-button @click="$emit('show', 'empty')">{{ __('Cancel') }}</gl-button>
+    </div>
+  </div>
+</template>
diff --git a/ee/app/assets/javascripts/integrations/edit/components/google_cloud_iam/manual_setup.vue b/ee/app/assets/javascripts/integrations/edit/components/google_cloud_iam/manual_setup.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7fd0709ffbfdbb7dd8f8fc4ef4f3e9c140562a01
--- /dev/null
+++ b/ee/app/assets/javascripts/integrations/edit/components/google_cloud_iam/manual_setup.vue
@@ -0,0 +1,88 @@
+<script>
+import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
+import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
+import { STATE_GUIDED } from './constants';
+
+export default {
+  components: {
+    GlIcon,
+    GlLink,
+    GlSprintf,
+    InviteMembersTrigger,
+  },
+  STATE_GUIDED,
+};
+</script>
+
+<template>
+  <div>
+    <h3>{{ s__('GoogleCloudPlatformService|Manual setup') }}</h3>
+    <p>
+      <gl-sprintf
+        :message="
+          s__(
+            'GoogleCloudPlatformService|%{linkStart}Switch to the guided setup%{linkEnd} if you can manage workload identity federation in Google Cloud. %{link2Start}What are the required permissions?%{link2End}',
+          )
+        "
+      >
+        <template #link="{ content }">
+          <gl-link @click="$emit('show', $options.STATE_GUIDED)">{{ content }}</gl-link>
+        </template>
+        >
+        <template #link2="{ content }">
+          <gl-link
+            target="_blank"
+            rel="noopener noreferrer"
+            href="https://cloud.google.com/iam/docs/manage-workload-identity-pools-providers#required-roles"
+          >
+            {{ content }}
+            <gl-icon name="external-link" :aria-label="__('(external link)')" />
+          </gl-link>
+        </template>
+      </gl-sprintf>
+    </p>
+    <h4>{{ s__('GoogleCloudPlatformService|Instructions') }}</h4>
+    <ol>
+      <li>
+        <gl-sprintf
+          :message="
+            s__(
+              'GoogleCloudPlatformService|Share the following information with someone that can manage Google Cloud workload identity federation. Or %{linkStart}invite them%{linkEnd} to set up.',
+            )
+          "
+        >
+          <template #link="{ content }">
+            <invite-members-trigger
+              :display-text="content"
+              class="gl-vertical-align-baseline"
+              variant="link"
+              trigger-source="google_cloud_artifact_registry_setup"
+            />
+          </template>
+          >
+        </gl-sprintf>
+      </li>
+      <ol type="a">
+        <li>
+          {{ s__('GoogleCloudPlatformService|The setup instructions page') }}
+        </li>
+        <li>
+          {{ s__('GoogleCloudPlatformService|Your GitLab project ID') }}
+        </li>
+        <li>
+          {{
+            s__('GoogleCloudPlatformService|Your workload identify federation (WLIF) issuer URL.')
+          }}
+        </li>
+      </ol>
+      <li>
+        {{
+          s__(
+            'GoogleCloudPlatformService|After Google Cloud workload identity federation has been set up, enter the details in the following form.',
+          )
+        }}
+      </li>
+    </ol>
+    <hr class="gl-border-gray-100" />
+  </div>
+</template>
diff --git a/ee/app/assets/javascripts/integrations/edit/components/sections/google_cloud_iam.vue b/ee/app/assets/javascripts/integrations/edit/components/sections/google_cloud_iam.vue
index 0492f3bea907795c1716800e941da414a2b6d56d..de067fc6ae2e501bf2801e9a606ec607df7bd259 100644
--- a/ee/app/assets/javascripts/integrations/edit/components/sections/google_cloud_iam.vue
+++ b/ee/app/assets/javascripts/integrations/edit/components/sections/google_cloud_iam.vue
@@ -1,24 +1,71 @@
 <script>
 // eslint-disable-next-line no-restricted-imports
 import { mapGetters } from 'vuex';
+import {
+  STATE_EMPTY,
+  STATE_FORM,
+  STATE_GUIDED,
+  STATE_INITIAL,
+  STATE_MANUAL,
+} from '../google_cloud_iam/constants';
+import EmptyState from '../google_cloud_iam/empty_state.vue';
 import GcIamForm from '../google_cloud_iam/form.vue';
+import GuidedSetup from '../google_cloud_iam/guided_setup.vue';
+import ManualSetup from '../google_cloud_iam/manual_setup.vue';
 
 export default {
   name: 'IntegrationSectionGoogleCloudIAM',
   components: {
+    EmptyState,
     GcIamForm,
+    GuidedSetup,
+    ManualSetup,
+  },
+  data() {
+    return {
+      show: STATE_INITIAL,
+    };
   },
   computed: {
     ...mapGetters(['propsSource']),
     dynamicFields() {
       return this.propsSource.fields;
     },
+    isEditable() {
+      return [STATE_FORM, STATE_MANUAL].includes(this.show);
+    },
+    isFormEmpty() {
+      return this.propsSource.fields.every((field) => !field.value);
+    },
+  },
+  watch: {
+    isEditable: {
+      handler(editable) {
+        this.propsSource.editable = editable;
+      },
+      immediate: true,
+    },
   },
+  created() {
+    this.show = this.isFormEmpty ? 'empty' : 'form';
+  },
+  methods: {
+    onShow(type) {
+      this.show = type;
+    },
+  },
+  STATE_EMPTY,
+  STATE_GUIDED,
+  STATE_MANUAL,
 };
 </script>
 
 <template>
-  <div>
-    <gc-iam-form :fields="dynamicFields" />
+  <div aria-live="polite">
+    <empty-state v-if="show === $options.STATE_EMPTY" @show="onShow" />
+    <guided-setup v-else-if="show === $options.STATE_GUIDED" @show="onShow" />
+    <manual-setup v-else-if="show === $options.STATE_MANUAL" @show="onShow" />
+
+    <gc-iam-form v-if="isEditable" :fields="dynamicFields" />
   </div>
 </template>
diff --git a/ee/spec/features/groups/integrations/google_cloud_platform/user_activates_workload_identity_federation_spec.rb b/ee/spec/features/groups/integrations/google_cloud_platform/user_activates_workload_identity_federation_spec.rb
index 4566df1aefd4c77038b005d82da5bbc7e20b0b2d..6b21207b6d6c6b130cdc9d632492785464831ba6 100644
--- a/ee/spec/features/groups/integrations/google_cloud_platform/user_activates_workload_identity_federation_spec.rb
+++ b/ee/spec/features/groups/integrations/google_cloud_platform/user_activates_workload_identity_federation_spec.rb
@@ -13,6 +13,7 @@
 
   it 'activates integration', :js do
     visit_group_integration(integration.title)
+    click_on s_('GoogleCloudPlatformService|Manual setup')
 
     fill_in(
       s_('GoogleCloudPlatformService|Project ID'),
diff --git a/ee/spec/features/projects/integrations/google_cloud_platform/user_activates_workload_identity_federation_spec.rb b/ee/spec/features/projects/integrations/google_cloud_platform/user_activates_workload_identity_federation_spec.rb
index 5fb107cdcc9df5a5210378ca7779c5d0bfb85be6..98cc0b5ebb400e847fcb98e12a5fdb54e9162cfa 100644
--- a/ee/spec/features/projects/integrations/google_cloud_platform/user_activates_workload_identity_federation_spec.rb
+++ b/ee/spec/features/projects/integrations/google_cloud_platform/user_activates_workload_identity_federation_spec.rb
@@ -13,6 +13,7 @@
 
   it 'activates integration', :js do
     visit_project_integration(integration.title)
+    click_on s_('GoogleCloudPlatformService|Manual setup')
 
     fill_in(
       s_('GoogleCloudPlatformService|Project ID'),
diff --git a/ee/spec/frontend/integrations/edit/components/google_cloud_iam/empty_state_spec.js b/ee/spec/frontend/integrations/edit/components/google_cloud_iam/empty_state_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..7a03fc284ce1c0a2ab2c1c3a0b4db43bbb72d436
--- /dev/null
+++ b/ee/spec/frontend/integrations/edit/components/google_cloud_iam/empty_state_spec.js
@@ -0,0 +1,102 @@
+import { GlButton, GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
+import EmptyAdminAppsSvg from '@gitlab/svgs/dist/illustrations/empty-state/empty-admin-apps-md.svg';
+import { shallowMount } from '@vue/test-utils';
+import {
+  STATE_GUIDED,
+  STATE_MANUAL,
+} from 'ee/integrations/edit/components/google_cloud_iam/constants';
+import EmptyState from 'ee/integrations/edit/components/google_cloud_iam/empty_state.vue';
+import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
+
+describe('EmptyState', () => {
+  let wrapper;
+  const createComponent = () => {
+    wrapper = shallowMount(EmptyState, {
+      stubs: {
+        GlEmptyState,
+        GlSprintf,
+      },
+    });
+  };
+
+  const findGlEmptyState = () => wrapper.findComponent(GlEmptyState);
+  const findDescription = () => wrapper.find('p');
+  const findLink = () => wrapper.findComponent(GlLink);
+  const findInviteMembersTrigger = () => wrapper.findComponent(InviteMembersTrigger);
+  const findButton = (variant) =>
+    wrapper.findAllComponents(GlButton).filter((button) => button.props('variant') === variant);
+
+  beforeEach(() => {
+    createComponent();
+  });
+
+  it('renders GlEmptyState', () => {
+    expect(findGlEmptyState().props()).toMatchObject({
+      svgPath: EmptyAdminAppsSvg,
+      title: 'Connect to Google Cloud',
+    });
+  });
+
+  it('renders description', () => {
+    expect(findDescription().text()).toContain(
+      'Connect to Google Cloud with workload identity federation. Select Guided setup if you can manage workload identity federation in Google Cloud.',
+    );
+  });
+
+  it('renders link to Google Cloud documentation', () => {
+    const link = findLink();
+    expect(link.attributes()).toMatchObject({
+      href:
+        'https://cloud.google.com/iam/docs/manage-workload-identity-pools-providers#required-roles',
+      rel: 'noopener noreferrer',
+      target: '_blank',
+    });
+    expect(link.text()).toBe('What are the required permissions?');
+  });
+
+  describe('Guided setup button', () => {
+    let guidedButton;
+
+    beforeEach(() => {
+      guidedButton = findButton('confirm').at(0);
+    });
+
+    it('renders variant confirm button', () => {
+      expect(guidedButton.text()).toBe('Guided setup');
+    });
+
+    it('emits `show` event', () => {
+      expect(wrapper.emitted().show).toBeUndefined();
+
+      guidedButton.vm.$emit('click');
+
+      expect(wrapper.emitted().show).toHaveLength(1);
+      expect(wrapper.emitted().show[0]).toContain(STATE_GUIDED);
+    });
+  });
+
+  describe('Manual setup button', () => {
+    let manualButton;
+
+    beforeEach(() => {
+      manualButton = findButton('default').at(0);
+    });
+
+    it('renders variant default button', () => {
+      expect(manualButton.text()).toBe('Manual setup');
+    });
+
+    it('emits `show` event', () => {
+      expect(wrapper.emitted().show).toBeUndefined();
+
+      manualButton.vm.$emit('click');
+
+      expect(wrapper.emitted().show).toHaveLength(1);
+      expect(wrapper.emitted().show[0]).toContain(STATE_MANUAL);
+    });
+  });
+
+  it('renders an InviteMembersTrigger component', () => {
+    expect(findInviteMembersTrigger().exists()).toBe(true);
+  });
+});
diff --git a/ee/spec/frontend/integrations/edit/components/google_cloud_iam/form_spec.js b/ee/spec/frontend/integrations/edit/components/google_cloud_iam/form_spec.js
index 033dc76e7559622206f0e106b29a976571b61141..ce4ec5bf4ffb758d398147b86f64fed63a87c7ee 100644
--- a/ee/spec/frontend/integrations/edit/components/google_cloud_iam/form_spec.js
+++ b/ee/spec/frontend/integrations/edit/components/google_cloud_iam/form_spec.js
@@ -1,5 +1,5 @@
 import { shallowMount } from '@vue/test-utils';
-import GcIamForm from 'ee_component/integrations/edit/components/google_cloud_iam/form.vue';
+import GcIamForm from 'ee/integrations/edit/components/google_cloud_iam/form.vue';
 import Configuration from '~/integrations/edit/components/sections/configuration.vue';
 import Connection from '~/integrations/edit/components/sections/connection.vue';
 import { createStore } from '~/integrations/edit/store';
diff --git a/ee/spec/frontend/integrations/edit/components/google_cloud_iam/guided_setup_spec.js b/ee/spec/frontend/integrations/edit/components/google_cloud_iam/guided_setup_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..3745af017e1997f3cdd5ce629867c7bff9fbc176
--- /dev/null
+++ b/ee/spec/frontend/integrations/edit/components/google_cloud_iam/guided_setup_spec.js
@@ -0,0 +1,82 @@
+import { GlButton, GlLink, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { STATE_MANUAL } from 'ee/integrations/edit/components/google_cloud_iam/constants';
+import GuidedSetup from 'ee/integrations/edit/components/google_cloud_iam/guided_setup.vue';
+
+describe('GuidedSetup', () => {
+  let wrapper;
+  const createComponent = () => {
+    wrapper = shallowMount(GuidedSetup, { stubs: { GlSprintf } });
+  };
+
+  const findFirstLink = () => wrapper.findAllComponents(GlLink).at(0);
+  const findButton = (variant) =>
+    wrapper.findAllComponents(GlButton).filter((button) => button.props('variant') === variant);
+
+  beforeEach(() => {
+    createComponent();
+  });
+
+  describe('Switch to manual setup link', () => {
+    let switchLink;
+
+    beforeEach(() => {
+      switchLink = findFirstLink();
+    });
+
+    it('renders link', () => {
+      expect(switchLink.text()).toBe('Switch to the manual setup');
+    });
+
+    it('emits `show` event', () => {
+      expect(wrapper.emitted().show).toBeUndefined();
+
+      switchLink.vm.$emit('click');
+
+      expect(wrapper.emitted().show).toHaveLength(1);
+      expect(wrapper.emitted().show[0]).toContain(STATE_MANUAL);
+    });
+  });
+
+  describe('Continue button', () => {
+    let continueButton;
+
+    beforeEach(() => {
+      continueButton = findButton('confirm').at(0);
+    });
+
+    it('renders variant confirm button', () => {
+      expect(continueButton.text()).toBe('Continue');
+    });
+
+    it('emits `show` event', () => {
+      expect(wrapper.emitted().show).toBeUndefined();
+
+      continueButton.vm.$emit('click');
+
+      expect(wrapper.emitted().show).toHaveLength(1);
+      expect(wrapper.emitted().show[0]).toContain('form');
+    });
+  });
+
+  describe('Cancel button', () => {
+    let cancelButton;
+
+    beforeEach(() => {
+      cancelButton = findButton('default').at(0);
+    });
+
+    it('renders variant confirm button', () => {
+      expect(cancelButton.text()).toBe('Cancel');
+    });
+
+    it('emits `show` event', () => {
+      expect(wrapper.emitted().show).toBeUndefined();
+
+      cancelButton.vm.$emit('click');
+
+      expect(wrapper.emitted().show).toHaveLength(1);
+      expect(wrapper.emitted().show[0]).toContain('empty');
+    });
+  });
+});
diff --git a/ee/spec/frontend/integrations/edit/components/google_cloud_iam/manual_setup_spec.js b/ee/spec/frontend/integrations/edit/components/google_cloud_iam/manual_setup_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..7aace69f03d84ad33a3f9b1598a87f79a0420eda
--- /dev/null
+++ b/ee/spec/frontend/integrations/edit/components/google_cloud_iam/manual_setup_spec.js
@@ -0,0 +1,38 @@
+import { GlLink, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { STATE_GUIDED } from 'ee/integrations/edit/components/google_cloud_iam/constants';
+import ManualSetup from 'ee/integrations/edit/components/google_cloud_iam/manual_setup.vue';
+
+describe('ManualSetup', () => {
+  let wrapper;
+  const createComponent = () => {
+    wrapper = shallowMount(ManualSetup, { stubs: { GlSprintf } });
+  };
+
+  const findFirstLink = () => wrapper.findAllComponents(GlLink).at(0);
+
+  beforeEach(() => {
+    createComponent();
+  });
+
+  describe('Switch to guided setup link', () => {
+    let switchLink;
+
+    beforeEach(() => {
+      switchLink = findFirstLink();
+    });
+
+    it('renders link', () => {
+      expect(switchLink.text()).toBe('Switch to the guided setup');
+    });
+
+    it('emits `show` event', () => {
+      expect(wrapper.emitted().show).toBeUndefined();
+
+      switchLink.vm.$emit('click');
+
+      expect(wrapper.emitted().show).toHaveLength(1);
+      expect(wrapper.emitted().show[0]).toContain(STATE_GUIDED);
+    });
+  });
+});
diff --git a/ee/spec/frontend/integrations/edit/components/sections/google_cloud_iam_spec.js b/ee/spec/frontend/integrations/edit/components/sections/google_cloud_iam_spec.js
index f937481068d4856a3d0da3cd3823f7327bf86c5a..648a3ee7d8577a5ee3f10ad4c0eaffbbfd5ae774 100644
--- a/ee/spec/frontend/integrations/edit/components/sections/google_cloud_iam_spec.js
+++ b/ee/spec/frontend/integrations/edit/components/sections/google_cloud_iam_spec.js
@@ -1,15 +1,24 @@
+import { nextTick } from 'vue';
 import { shallowMount } from '@vue/test-utils';
 import IntegrationSectionGoogleCloudIAM from 'ee_component/integrations/edit/components/sections/google_cloud_iam.vue';
-import GcIamForm from 'ee_component/integrations/edit/components/google_cloud_iam/form.vue';
+import {
+  STATE_EMPTY,
+  STATE_GUIDED,
+  STATE_MANUAL,
+} from 'ee/integrations/edit/components/google_cloud_iam/constants';
+import EmptyState from 'ee/integrations/edit/components/google_cloud_iam/empty_state.vue';
+import GcIamForm from 'ee/integrations/edit/components/google_cloud_iam/form.vue';
+import GuidedSetup from 'ee/integrations/edit/components/google_cloud_iam/guided_setup.vue';
+import ManualSetup from 'ee/integrations/edit/components/google_cloud_iam/manual_setup.vue';
 import { createStore } from '~/integrations/edit/store';
 
 describe('IntegrationSectionGoogleCloudIAM', () => {
   let wrapper;
 
-  const createComponent = () => {
+  const createComponent = ({ fields = [] } = {}) => {
     const store = createStore({
       customState: {
-        fields: [],
+        fields,
       },
     });
 
@@ -18,11 +27,61 @@ describe('IntegrationSectionGoogleCloudIAM', () => {
     });
   };
 
+  const findEmptyState = () => wrapper.findComponent(EmptyState);
   const findGcIamForm = () => wrapper.findComponent(GcIamForm);
+  const findGuidedSetup = () => wrapper.findComponent(GuidedSetup);
+  const findManualSetup = () => wrapper.findComponent(ManualSetup);
 
-  it('renders Google Cloud IAM form', () => {
-    createComponent();
+  describe('when Google Cloud IAM form is empty', () => {
+    it('renders the empty state', () => {
+      createComponent();
 
-    expect(findGcIamForm().exists()).toBe(true);
+      expect(findEmptyState().exists()).toBe(true);
+      expect(findGcIamForm().exists()).toBe(false);
+    });
+  });
+
+  describe('when Google Cloud IAM form is not empty', () => {
+    it('renders the Google Cloud IAM form', () => {
+      createComponent({ fields: [{ value: '' }, { value: '1' }] });
+
+      expect(findEmptyState().exists()).toBe(false);
+      expect(findGcIamForm().exists()).toBe(true);
+    });
+  });
+
+  describe('when `show` events are emitted', () => {
+    it.each`
+      initialState    | event           | componentEmitting  | hasEmptyState | hasGuidedSetup | hasManualSetup | hasGcIamForm
+      ${STATE_EMPTY}  | ${STATE_GUIDED} | ${findEmptyState}  | ${false}      | ${true}        | ${false}       | ${false}
+      ${STATE_EMPTY}  | ${STATE_MANUAL} | ${findEmptyState}  | ${false}      | ${false}       | ${true}        | ${true}
+      ${STATE_GUIDED} | ${STATE_MANUAL} | ${findGuidedSetup} | ${false}      | ${false}       | ${true}        | ${true}
+      ${STATE_MANUAL} | ${STATE_GUIDED} | ${findManualSetup} | ${false}      | ${true}        | ${false}       | ${false}
+    `(
+      "render correct components for the '$event' event",
+      async ({
+        initialState,
+        event,
+        componentEmitting,
+        hasEmptyState,
+        hasGuidedSetup,
+        hasManualSetup,
+        hasGcIamForm,
+      }) => {
+        createComponent();
+
+        // Initial state
+        findEmptyState().vm.$emit('show', initialState);
+        await nextTick();
+
+        componentEmitting().vm.$emit('show', event);
+        await nextTick();
+
+        expect(findEmptyState().exists()).toBe(hasEmptyState);
+        expect(findGuidedSetup().exists()).toBe(hasGuidedSetup);
+        expect(findManualSetup().exists()).toBe(hasManualSetup);
+        expect(findGcIamForm().exists()).toBe(hasGcIamForm);
+      },
+    );
   });
 });
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 5b5783df36c5d8dc65afaf1a65ad24dc21520f5b..8ddbfd173f1fc09a77deb3171cdaff869bea70ce 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -23619,12 +23619,33 @@ msgstr ""
 msgid "GoogleArtifactRegistry|Your Google Cloud project must have specific Identity and Access Management (IAM) policies to use the Artifact Registry repository in this GitLab project."
 msgstr ""
 
+msgid "GoogleCloudPlatformService|%{linkStart}Switch to the guided setup%{linkEnd} if you can manage workload identity federation in Google Cloud. %{link2Start}What are the required permissions?%{link2End}"
+msgstr ""
+
+msgid "GoogleCloudPlatformService|%{linkStart}Switch to the manual setup%{linkEnd} if you cannot manage workload identity federation in Google Cloud. %{link2Start}What are the required permissions?%{link2End}"
+msgstr ""
+
 msgid "GoogleCloudPlatformService|%{link_start}Explore Google Cloud integration with GitLab%{link_end}, for CI/CD and more."
 msgstr ""
 
+msgid "GoogleCloudPlatformService|After Google Cloud workload identity federation has been set up, enter the details in the following form."
+msgstr ""
+
+msgid "GoogleCloudPlatformService|After Google Cloud workload identity federation has been set up, select %{strongStart}Continue%{strongEnd}."
+msgstr ""
+
+msgid "GoogleCloudPlatformService|Before you begin, %{linkStart}install the Google Cloud CLI%{linkEnd}."
+msgstr ""
+
+msgid "GoogleCloudPlatformService|Connect to Google Cloud"
+msgstr ""
+
 msgid "GoogleCloudPlatformService|Connect to Google Cloud with workload identity federation for secure access without accounts or keys."
 msgstr ""
 
+msgid "GoogleCloudPlatformService|Connect to Google Cloud with workload identity federation. Select %{strongStart}Guided setup%{strongEnd} if you can manage workload identity federation in Google Cloud. %{linkStart}What are the required permissions?%{linkEnd}"
+msgstr ""
+
 msgid "GoogleCloudPlatformService|Example: %{code_open}314053285323%{code_close}"
 msgstr ""
 
@@ -23649,6 +23670,9 @@ msgstr ""
 msgid "GoogleCloudPlatformService|Google Cloud project number for the Workload Identity Federation."
 msgstr ""
 
+msgid "GoogleCloudPlatformService|Guided setup"
+msgstr ""
+
 msgid "GoogleCloudPlatformService|ID of the Workload Identity Pool provider."
 msgstr ""
 
@@ -23658,6 +23682,12 @@ msgstr ""
 msgid "GoogleCloudPlatformService|Identify the Google Cloud project with the workload identity pool and provider. %{linkStart}Where are my project ID and project number?%{linkEnd}"
 msgstr ""
 
+msgid "GoogleCloudPlatformService|Instructions"
+msgstr ""
+
+msgid "GoogleCloudPlatformService|Invite member to set up"
+msgstr ""
+
 msgid "GoogleCloudPlatformService|Manage permissions for Google Cloud resources with Identity and Access Management (IAM)."
 msgstr ""
 
@@ -23667,6 +23697,9 @@ msgstr ""
 msgid "GoogleCloudPlatformService|Manage your artifacts in Google Artifact Registry."
 msgstr ""
 
+msgid "GoogleCloudPlatformService|Manual setup"
+msgstr ""
+
 msgid "GoogleCloudPlatformService|Pool ID"
 msgstr ""
 
@@ -23682,6 +23715,12 @@ msgstr ""
 msgid "GoogleCloudPlatformService|Provider ID"
 msgstr ""
 
+msgid "GoogleCloudPlatformService|Replace %{codeStart}your_access_token%{codeEnd} with a %{linkStart}new personal access token%{linkEnd} with the %{strongStart}api%{strongEnd} scope. This token sets up your Google Cloud IAM integration in GitLab."
+msgstr ""
+
+msgid "GoogleCloudPlatformService|Replace %{codeStart}your_google_cloud_project_id%{codeEnd} with your Google Cloud project ID. To improve security, use a dedicated project for identity management, separate from resources and CI/CD projects. %{linkStart}Where’s my project ID?%{linkEnd}"
+msgstr ""
+
 msgid "GoogleCloudPlatformService|Repository location"
 msgstr ""
 
@@ -23691,6 +23730,12 @@ msgstr ""
 msgid "GoogleCloudPlatformService|Repository name"
 msgstr ""
 
+msgid "GoogleCloudPlatformService|Run the following command to set up and connect to your Google Cloud project with workload identity federation."
+msgstr ""
+
+msgid "GoogleCloudPlatformService|Share the following information with someone that can manage Google Cloud workload identity federation. Or %{linkStart}invite them%{linkEnd} to set up."
+msgstr ""
+
 msgid "GoogleCloudPlatformService|The Google Cloud Identity and Access Management integration is not configured for this project"
 msgstr ""
 
@@ -23700,12 +23745,24 @@ msgstr ""
 msgid "GoogleCloudPlatformService|The google_cloud_support feature is not available"
 msgstr ""
 
+msgid "GoogleCloudPlatformService|The setup instructions page"
+msgstr ""
+
 msgid "GoogleCloudPlatformService|To improve security, use a dedicated project for resources, separate from CI/CD and identity management projects. %{link_start}Where’s my project ID? %{icon}%{link_end}"
 msgstr ""
 
 msgid "GoogleCloudPlatformService|Workload identity federation"
 msgstr ""
 
+msgid "GoogleCloudPlatformService|You might be prompted to sign in to Google."
+msgstr ""
+
+msgid "GoogleCloudPlatformService|Your GitLab project ID"
+msgstr ""
+
+msgid "GoogleCloudPlatformService|Your workload identify federation (WLIF) issuer URL."
+msgstr ""
+
 msgid "GoogleCloud|Cancel"
 msgstr ""