Kigo Context - UI/UX Page Configuration

Kigo UI/UX Page Configuration System

Overview

The Kigo Page Configuration System enables SDK-hosted sites and white-label implementations using the Kigo TOP SDK to customize the components and content displayed on the homepage. This system supports injecting components into the existing layout or fully overriding it, without modifying core SDK functionality.

The configuration is defined under the uiuxOverride['page-configurations'] key within the SDK context and allows partners to tailor the homepage experience based on whether the user's location is available.


Priority & Structure

Each homepage variant (homepage-with-location and homepage-no-location) is resolved independently.

Configuration Priority

  1. SDK context override via uiuxOverride['page-configurations'] — fully_override replaces the configured layout; inject_at_index merges into it
  2. Program-level configuration (set by Kigo; program, then partner, then the Kigo base experience)

Leave a page key unset or set it to null (the SDK default) to use the program-level configuration as-is.


Page Configuration Structure

type PageOverrideMode = "fully_override" | "inject_at_index";

type PageConfigurationsContext = {
  "homepage-with-location": PageConfigurationContext;
  "homepage-no-location": PageConfigurationContext;
};

type PageConfigurationContext = {
  mode: PageOverrideMode;
  components: PageComponentOverride[];
} | null;

type PageComponentOverride = {
  page_component_configuration_id?: string; // Optional; generated when omitted
  title: string;
  show_title?: boolean; // Defaults to true
  component_code_type: PageComponentType;
  sorting_order: number; // Starts at 1
  generic_offer_carousel_metadata?: GenericOfferCarouselMetadata; // generic_offer_carousel, local_offers_with_integrated_map
  generic_category_grid?: GenericCategoryGridMetadata; // generic_category_grid
};

type PageComponentType =
  | "generic_offer_carousel"
  | "generic_category_grid"
  | "local_offers_with_integrated_map"
  | "component_share_location"
  | "component_user_survey"
  | "component_offer_map_no_location"
  | "component_hero_advertisement_carousel"
  | "component_premium_hero"
  | "component_standard_hero"
  | "component_dedicated_shelf"
  | "component_trending_merchants"
  | "component_sponsored_trending_merchants"
  | "component_just_for_you"
  | "popular_city_offers";

Components with an unrecognized component_code_type render nothing.

Common Properties

PropertyTypeDescription
titlestringSection title displayed above the component
show_titlebooleanSet to false to hide the section title. Supported by the premium hero, standard hero, dedicated shelf, and sponsored trending merchants components. Defaults to true
component_code_typePageComponentTypeWhich component to render (see Component Types)
sorting_ordernumberPosition of the component (see below)
page_component_configuration_idstringOptional identifier for the section. A unique ID is generated when omitted

Sorting Order

The sorting_order property determines the position of each component within its page configuration (homepage-with-location or homepage-no-location).

Key Points:

  • Starts at 1: The first position is sorting_order: 1
  • Ascending order: Components are displayed in ascending order (1, 2, 3, etc.)
  • Page-specific: Sorting is independent for each page type—homepage-with-location and homepage-no-location have their own sequences
  • Unique values: Use a unique sorting_order for each component
  • Mode-dependent: In fully_override mode only the relative order matters, so gaps (1, 3, 5) are fine. In inject_at_index mode, sorting_order is the exact slot the component claims (see below)

Example:

components: [
  { title: 'Featured Deals', sorting_order: 1 },  // Displays first
  { title: 'Near Me', sorting_order: 2 },         // Displays second
  { title: 'Categories', sorting_order: 3 },      // Displays third
]

Configuration Modes

1. Fully Override Mode

Mode: 'fully_override'

Completely replaces the program-level components with the components defined in the SDK context, sorted by sorting_order. This mode gives you full control over the page layout.

Use Cases:

  • Complete UI redesign for specific partners
  • Removing all default components
  • Creating a fully custom homepage experience

Example:

'homepage-with-location': {
  mode: 'fully_override',
  components: [
    // These components will replace ALL program-level components
  ]
}

2. Inject at Index Mode

Mode: 'inject_at_index'

Injects custom components at specific positions within the program-level layout:

  • Each context component claims the 1-based position given by its sorting_order
  • Program-level components fill the remaining positions in their original order
  • Hero components (component_hero_advertisement_carousel, component_premium_hero, component_standard_hero) appear only once: injecting one removes the program-level component of the same type
  • Other component types (e.g. generic_offer_carousel) can appear multiple times

Example: with program-level components [a1, a2, a3, a4, a5] and context components c2 (sorting_order: 2) and c4 (sorting_order: 4), the page renders a1, c2, a2, c4, a3, a4, a5.

Use Cases:

  • Adding promotional content to existing layouts
  • Inserting partner-specific components without losing default content
  • Testing new components alongside existing ones

Example:

'homepage-with-location': {
  mode: 'inject_at_index',
  components: [
    // These components will be injected at the position given by sorting_order
  ]
}

Page Types

1. Homepage with Location

Key: 'homepage-with-location'

Used when the user has shared their location or the SDK context includes location data. This configuration enables location-based features such as nearby offers, distance calculations, and geo-filtered content.

Location-Specific Features:

  • dynamic_query_filters with latitude, longitude, and radius are populated from the user's location
  • search_radius_unit can be set to 'MI' or 'KM' in static_query_filters
  • Proximity-based sorting and filtering

Example Configuration:

'homepage-with-location': {
  mode: 'fully_override',
  components: [
    {
      title: 'Lightning Deals',
      component_code_type: 'generic_offer_carousel',
      sorting_order: 1,  // First component
      generic_offer_carousel_metadata: {
        subtitle: null,
        minimum_required_offers_to_show: 1,
        show_integrated_offer_map: false,
        saved_offer_query: {
          static_query_filters: {
            filter: {
              catalog_filter_ids: ['<catalog-filter-id>'],
              single_offer_per_merchant: true,
              return_count_only: false,
            },
            search_radius_unit: 'MI',
            limit: 6,
          },
          dynamic_query_filters: {
            latitude: null,  // Populated from user location
            longitude: null, // Populated from user location
            radius: null,    // Populated from user location
          },
          online_fallback: false,
        },
        go_to_link_above: 'true',
        go_to_link_display_text: 'See all',
        go_to_link_url_parameters: '?catalog_filter_ids=<catalog-filter-id>',
      },
    },
  ],
}

2. Homepage without Location

Key: 'homepage-no-location'

Used when the user has not shared their location. This configuration displays content that doesn't require geographic data.

No-Location Characteristics:

  • No latitude, longitude, or radius filters
  • No search_radius_unit required
  • dynamic_query_filters typically empty
  • Focus on online offers or national campaigns
  • Selecting a "See all" link prompts the user to share their location before navigating

Example Configuration:

'homepage-no-location': {
  mode: 'fully_override',
  components: [
    {
      title: 'Online Deals',
      component_code_type: 'generic_offer_carousel',
      sorting_order: 1,  // First component
      generic_offer_carousel_metadata: {
        subtitle: null,
        minimum_required_offers_to_show: 3,
        show_integrated_offer_map: false,
        saved_offer_query: {
          static_query_filters: {
            filter: {
              catalog_filter_ids: ['<catalog-filter-id>'],
              redemption_types: ['online'],
              single_offer_per_merchant: true,
              return_count_only: false,
            },
            limit: 6,
            // No search_radius_unit for no-location page
          },
          dynamic_query_filters: {}, // Empty - no location values
          online_fallback: false,
        },
        go_to_link_above: 'true',
        go_to_link_display_text: 'See all',
        go_to_link_url_parameters: '?catalog_filter_ids=<catalog-filter-id>&redemption_types=online',
      },
    },
  ],
}

Component Types

The following component types are available for page configurations:

TypeDescriptionMetadata
generic_offer_carouselHorizontal carousel of offers from a querygeneric_offer_carousel_metadata (required)
generic_category_gridGrid of category tiles for navigationgeneric_category_grid (required)
local_offers_with_integrated_mapNearby offers with an integrated mapgeneric_offer_carousel_metadata (optional)
component_share_locationPrompts users to share their location—
component_user_surveyUser survey—
component_offer_map_no_locationOffer map that doesn't require user location—
component_hero_advertisement_carouselPromotional banners in a carousel (legacy hero)—
component_premium_heroPremium hero placement—
component_standard_heroStandard hero placement—
component_dedicated_shelfDedicated shelf placement—
component_trending_merchantsPopular or trending merchants—
component_sponsored_trending_merchantsSponsored trending merchants—
component_just_for_youPersonalized recommendations—
popular_city_offersPopular local offers across cities—

Metadata other than generic_offer_carousel_metadata and generic_category_grid is ignored.

Generic Offer Carousel

Type: 'generic_offer_carousel'

Displays a horizontal scrollable carousel of offers based on query filters.

📘

Metadata scope

The generic_offer_carousel_metadata object applies to generic_offer_carousel and local_offers_with_integrated_map. Other component types ignore it.

Metadata Structure:

generic_offer_carousel_metadata: {
  subtitle?: string | null;
  minimum_required_offers_to_show?: number | null;
  show_integrated_offer_map: boolean;
  saved_offer_query: SavedOfferQuery;  // See "Saved Offer Query" section below
  go_to_link_above?: 'true' | 'false' | null;
  go_to_link_display_text?: string | null;
  go_to_link_url_parameters?: string | null;
}

Metadata Properties:

PropertyTypeDescription
subtitlestring | nullOptional subtitle displayed below the carousel title
minimum_required_offers_to_shownumber | nullMinimum number of offers required to display the carousel. Defaults to 3 when omitted
show_integrated_offer_mapbooleanRequired by the schema. Not currently used by the carousel; set to false
saved_offer_queryobjectQuery configuration for fetching offers (see below)
go_to_link_above'true' | 'false' | nullPosition of the "go to" link: 'true' shows it above the carousel, 'false' below. Omit or null for no link
go_to_link_display_textstring | nullText for the "go to" link (e.g. "See all"). Required for the link to appear; there is no default text
go_to_link_url_parametersstring | nullQuery string for the offers page the link opens (e.g. "?catalog_filter_ids=<id>&redemption_types=online"). When omitted, the link uses the carousel's own query filters

Local Offers with Integrated Map

Type: 'local_offers_with_integrated_map'

Displays nearby offers with a map. Accepts an optional generic_offer_carousel_metadata, of which saved_offer_query and minimum_required_offers_to_show (default 3) are used. saved_offer_query.online_fallback defaults to true for this component: set it to false to disable falling back to online offers when no local offers are found.

Generic Category Grid

Type: 'generic_category_grid'

Displays a grid of category tiles for navigation.

Metadata Structure:

generic_category_grid: {
  generic_category_grid_configurations_id?: string; // Generated when omitted
  subtitle?: string | null;
  go_to_link_above?: 'true' | 'false' | null;
  go_to_link_display_text?: string | null;
  go_to_link_url_parameters?: string | null;
  grid_item_metadata: Array<{
    generic_category_grid_item_metadata_id?: string; // Generated when omitted
    category?: string | null;
    category_display_text?: string | null;
    category_image_url?: string | null;
    category_mui_icon_name?: string | null; // e.g. 'LunchDiningIcon'
    go_to_link_parameters?: string | null;  // e.g. '?redemption_types=online'
    sort_order: number;
  }>;
}

Saved Offer Query

The saved_offer_query object defines the query parameters used to fetch offers from the Kigo Offers API. It maps to the GET /api/v1/offers endpoint parameters.

Structure:

saved_offer_query: {
  static_query_filters: {
    filter?: {
      catalog_filter_ids?: string[];  // Curated offer collections
      single_offer_per_merchant?: boolean;
      return_count_only?: boolean;
      offer_types?: string[];
      redemption_types?: string[];
      // ...other GET /offers filter params
    };
    search_radius_unit?: 'MI' | 'KM';
    radius?: number;
    limit?: number;   // Defaults to 99
    offset?: number;  // Defaults to 0
    sort_by?: Array<{ field: string; direction: string }>;
  };
  dynamic_query_filters: {
    latitude?: number | null;
    longitude?: number | null;
    radius?: number | null;
  };
  online_fallback?: boolean;
}

Static Query Filters

These are fixed parameters that don't change based on user context.

Filter parameters (inside filter):

PropertyTypeDescription
catalog_filter_idsstring[]Catalog filter IDs for curated offer collections
single_offer_per_merchantbooleanIf true, only shows one offer per merchant to avoid duplicates
return_count_onlybooleanIf true, only returns the count (set to false for carousel display)
offer_typesstring[]e.g. bogo, free_with_purchase, percentage_savings, dollars_off, price_point, cash_back, merchandise, digital_gift_card, physical_gift_card, spend_and_get
redemption_typesstring[]e.g. in_store, print, online, purchase, spend_and_get

Other supported filter keys: categories, category_ids, commodities, commodity_groups, commodity_ids, country_code, eligibilities, exclude_offer_ids, is_available, lightning_deal, max_merchants, merchant_ids, merchant_source, search, tag_ids, tags.

Top-level parameters (beside filter):

PropertyTypeDescription
search_radius_unit'MI' | 'KM'Unit for radius-based searches (Miles or Kilometers)
radiusnumberSearch radius
limitnumberMaximum number of offers to fetch (default 99)
offsetnumberPagination offset (default 0)
sort_byArray<{ field, direction }>Sort order, e.g. [{ field: 'distance', direction: 'ascending' }]

Keys not listed above are ignored. Location parameters (latitude, longitude, radius, search_radius_unit) are only sent when dynamic_query_filters contains latitude or longitude.

Dynamic Query Filters

These filters are populated at runtime from the user's location. Set them to null to have the SDK fill them in:

PropertyTypeDescription
latitudenumber | nullUser's latitude (auto-populated from location)
longitudenumber | nullUser's longitude (auto-populated from location)
radiusnumber | nullSearch radius (auto-populated from the user's search radius, default 50)

A non-null value is used as-is instead of the user's value.

Online Fallback

PropertyTypeDescription
online_fallbackbooleanUsed by local_offers_with_integrated_map only. If true (the default for that component), falls back to online offers when no local offers are found

Catalog Filter IDs

The catalog_filter_ids array allows you to display curated collections of offers in your carousel. These IDs represent pre-configured offer sets that can be tailored for specific use cases.

What are Catalog Filter IDs?

Catalog filter IDs are unique identifiers for curated offer collections. They allow you to:

  • Display specific categories of offers (e.g., Pizza, Dining, Shopping)
  • Promote seasonal or featured deals
  • Create themed offer sections
  • Target specific merchant types

How to Get Catalog Filter IDs:

📘

Contact the Kigo team

Contact the Kigo team if you need custom catalog filter IDs for your implementation. We can create curated offer collections for specific sections like:

  • "Pizza Deals" - Only pizza-related offers
  • "Weekend Specials" - Curated weekend promotions
  • "New Merchants" - Recently added merchant offers
  • Custom collections based on your requirements

Example Usage:

saved_offer_query: {
  static_query_filters: {
    filter: {
      catalog_filter_ids: [
        '<pizza-deals-catalog-filter-id>',
        '<featured-merchants-catalog-filter-id>',
      ],
      single_offer_per_merchant: true,
      return_count_only: false,
    },
    search_radius_unit: 'MI',
  },
  dynamic_query_filters: {
    latitude: null,
    longitude: null,
    radius: null,
  },
}

Empty Catalog Filter IDs:

If you leave catalog_filter_ids as an empty array [] (or omit it), the carousel will display all available offers based on the other filter criteria (location, etc.):

filter: {
  catalog_filter_ids: [],  // Shows all offers (no specific collection filter)
}

Complete Integration Example

This example shows a complete configuration with multiple carousels sorted by sorting_order:

window.Kigo.setContext({
  uiuxOverride: {
    "welcome-modal": { enabled: true },
    "estimated-savings-count": { enabled: false },
    "wallet-icon": { enabled: true },
    "wallet-icon-url": {
      url: "https://cdn.example.com/icons/wallet.svg",
    },
    "page-configurations": {
      "homepage-with-location": {
        mode: "fully_override",
        components: [
          {
            title: "Lightning Deals",
            component_code_type: "generic_offer_carousel",
            sorting_order: 1,  // Displays first
            generic_offer_carousel_metadata: {
              subtitle: null,
              minimum_required_offers_to_show: 1,
              show_integrated_offer_map: false,
              saved_offer_query: {
                static_query_filters: {
                  filter: {
                    catalog_filter_ids: ["<catalog-filter-id>"],  // Contact Kigo for custom IDs
                    single_offer_per_merchant: true,
                    return_count_only: false,
                  },
                  search_radius_unit: "MI",
                  limit: 6,
                },
                dynamic_query_filters: {
                  latitude: null,   // Auto-populated from user location
                  longitude: null,  // Auto-populated from user location
                  radius: null,     // Auto-populated from user location
                },
              },
              go_to_link_above: "true",
              go_to_link_display_text: "See all",
              go_to_link_url_parameters: "?catalog_filter_ids=<catalog-filter-id>",
            },
          },
          {
            title: "Near Me",
            component_code_type: "generic_offer_carousel",
            sorting_order: 2,  // Displays second
            generic_offer_carousel_metadata: {
              subtitle: "Offers in your area",
              minimum_required_offers_to_show: 1,
              show_integrated_offer_map: false,
              saved_offer_query: {
                static_query_filters: {
                  filter: {
                    catalog_filter_ids: [],  // Empty = all offers
                    single_offer_per_merchant: true,
                    return_count_only: false,
                  },
                  search_radius_unit: "MI",
                  limit: 6,
                  sort_by: [{ field: "distance", direction: "ascending" }],
                },
                dynamic_query_filters: {
                  latitude: null,
                  longitude: null,
                  radius: null,
                },
              },
              go_to_link_above: "true",
              go_to_link_display_text: "See all",
              // No go_to_link_url_parameters: the link uses this carousel's query
            },
          },
        ],
      },
      "homepage-no-location": {
        mode: "fully_override",
        components: [
          {
            title: "Share your location",
            component_code_type: "component_share_location",
            sorting_order: 1,
          },
          {
            title: "Online Deals",
            component_code_type: "generic_offer_carousel",
            sorting_order: 2,
            generic_offer_carousel_metadata: {
              subtitle: null,
              minimum_required_offers_to_show: 3,
              show_integrated_offer_map: false,
              saved_offer_query: {
                static_query_filters: {
                  filter: {
                    catalog_filter_ids: ["<catalog-filter-id>"],
                    redemption_types: ["online"],
                    single_offer_per_merchant: true,
                    return_count_only: false,
                  },
                  limit: 6,
                  // No search_radius_unit for no-location page
                },
                dynamic_query_filters: {},  // Empty for no-location
              },
              go_to_link_above: "true",
              go_to_link_display_text: "See all",
              go_to_link_url_parameters: "?catalog_filter_ids=<catalog-filter-id>&redemption_types=online",
            },
          },
        ],
      },
    },
  },
});
📘

Catalog filter IDs

For custom catalog_filter_ids (e.g., "Pizza Deals", "Featured Merchants"), contact the Kigo team. We can create curated offer collections tailored to your needs.


Best Practices

1. Choose the Right Mode

  • Use fully_override when you need complete control over the page layout
  • Use inject_at_index when you want to preserve existing components and add new ones

2. Sorting Order Management

  • Start with sorting_order: 1 for the first component
  • Use unique, sequential numbering (1, 2, 3...) for clear ordering
  • In fully_override mode, you can leave gaps (1, 3, 5) to allow for future insertions without renumbering
  • In inject_at_index mode, sorting_order is the exact position the component takes on the page
  • Remember: sorting is independent for each page type—components in homepage-with-location are sorted separately from homepage-no-location

3. Location Awareness

  • Provide both homepage-with-location and homepage-no-location configurations when overriding the layout (an unset page uses the program-level layout)
  • Ensure location-based queries are only used in the homepage-with-location configuration
  • Include latitude/longitude keys in dynamic_query_filters for any query that should use the user's location

4. Component Metadata

  • generic_offer_carousel_metadata applies to generic_offer_carousel and local_offers_with_integrated_map; generic_category_grid applies to generic_category_grid
  • Set minimum_required_offers_to_show to control visibility thresholds
  • Use single_offer_per_merchant: true (inside filter) to avoid merchant duplication
  • Set appropriate search_radius_unit for your target audience ('MI' for US, 'KM' for international)

5. Query Optimization

  • The saved_offer_query maps to the GET /offers API; filter parameters go inside filter
  • Use catalog_filter_ids to target specific offer collections (contact Kigo team for custom IDs)
  • Set return_count_only: false to retrieve full offer details for display
  • Set a limit to control how many offers each carousel fetches (default 99)
  • Use empty catalog_filter_ids: [] to show all offers without collection filtering

6. Navigation Links

  • Set both go_to_link_above and go_to_link_display_text to show a "See all" link
  • Keep go_to_link_display_text concise and actionable
  • Use go_to_link_url_parameters as an offers-page query string (e.g. ?catalog_filter_ids=<id>), or omit it to reuse the carousel's own filters

Troubleshooting

Common Issues

  1. Components not appearing:

    • Verify mode is set correctly (fully_override or inject_at_index)
    • Check that component_code_type is one of the supported types
    • Ensure component metadata structure matches expected schema (generic_offer_carousel requires generic_offer_carousel_metadata; generic_category_grid requires generic_category_grid)
  2. Location-based queries not working:

    • Confirm user has shared location or SDK context includes location data
    • Verify dynamic_query_filters includes latitude and longitude keys
    • Verify search_radius_unit is set in static_query_filters
  3. Offers not showing in carousel:

    • Verify catalog_filter_ids are valid
    • Check the minimum_required_offers_to_show threshold (default 3)
    • Ensure filter parameters such as single_offer_per_merchant and return_count_only are inside filter
    • Ensure return_count_only is set to false
  4. "See all" link not showing:

    • Set go_to_link_above to 'true' or 'false' and provide go_to_link_display_text
  5. Override not taking effect:

    • Verify configuration is in the correct format
    • Check browser console for validation errors
  6. Wrong page configuration loading:

    • Confirm location detection is working properly
    • Verify both configurations are defined

Summary

The page configuration system provides partners and hosted sites with powerful tools to customize homepage layouts and content. By supporting both location-aware and location-free configurations, partners can deliver optimized experiences regardless of user location sharing preferences. The dual-mode system (fully_override vs inject_at_index) enables everything from complete redesigns to subtle enhancements—all without modifying core SDK logic.

This flexibility allows partners to align the user experience with their brand guidelines, business objectives, and user engagement strategies while maintaining consistency with the Kigo platform's core functionality.


Did this page help you?