Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Sep 13, 2025

This PR introduces an extensible async createContext template method to the Campaign component, allowing subclasses and future variations to customize context data before template rendering with support for asynchronous operations.

Problem

Previously, the Campaign component called getContext(...) directly during template rendering, making it impossible for subclasses to extend or modify the context without duplicating the entire render logic. This prevented scenarios like:

  • Adding custom context enrichment
  • Injecting feature flags or A/B test metadata
  • Transforming data for specific use cases
  • Fetching external data like Shopify side product data

Solution

Added an async createContext(raw: JSONResult): Promise<object> method to the Campaign class that:

  • Serves as an extension point for context creation
  • Is called with await instead of the direct getContext usage in loadCampaign
  • Supports asynchronous operations for external data fetching
  • Maintains full backward compatibility
  • Includes comprehensive TypeDoc documentation with usage examples
  • Uses proper Promise<object> return type for better type safety

Usage Example

class CustomCampaign extends Campaign {
  async createContext(raw) {
    const context = await super.createContext(raw);
    return { 
      ...context, 
      customProperty: 'value',
      featureFlags: await this.getFeatureFlags(),
      shopifyData: await this.fetchShopifyData()
    };
  }
}

Changes

  • Added async createContext method to Campaign class with detailed documentation
  • Modified loadCampaign function to use await with the instance method instead of direct getContext call
  • Added test coverage verifying subclass override functionality using JSX syntax with async support
  • Used proper Promise<object> return type for better type safety
  • All existing tests continue to pass (161/161)

The implementation is minimal and surgical - only one line changed in the rendering logic to add await and one async method added to the class.

Fixes #314.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@Copilot Copilot AI changed the title [WIP] feat(Campaign): make context creation extensible via overridable template method feat(Campaign): make context creation extensible via overridable template method Sep 13, 2025
@Copilot Copilot AI requested a review from timowestnosto September 13, 2025 11:24
Copilot finished work on behalf of timowestnosto September 13, 2025 11:24
Copy link
Contributor

@timowestnosto timowestnosto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot act on feedback

@timowestnosto timowestnosto marked this pull request as ready for review September 13, 2025 11:28
@Copilot Copilot AI review requested due to automatic review settings September 13, 2025 11:28
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces an extensible createContext template method to the Campaign component, enabling subclasses to customize context data before template rendering while maintaining full backward compatibility.

  • Adds a new createContext method to the Campaign class as an overridable extension point
  • Modifies the loadCampaign function to use the instance method instead of calling getContext directly
  • Includes comprehensive test coverage for the subclass override functionality

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/components/Campaign/Campaign.ts Adds the createContext template method and updates loadCampaign to use it
test/components/Campaign.spec.tsx Adds test coverage for subclass override behavior with custom context properties

@Copilot Copilot AI requested a review from timowestnosto September 13, 2025 11:33
Copilot finished work on behalf of timowestnosto September 13, 2025 11:33
* }
* ```
*/
createContext(raw: JSONResult): object {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what scenarios this will be useful? A custom campaign can only override context data?
Also, JSON recommendation results are of Nested objects. I am not sure if extending it at the top level is needed. Or am I missing something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized that I need to make this asynchronous, but the intended use cases are

  • add utility functions to context
  • use Shopify side product data instead

@Copilot Copilot AI changed the title feat(Campaign): make context creation extensible via overridable template method feat(Campaign): make context creation extensible via async overridable template method Sep 15, 2025
@Copilot Copilot AI requested a review from timowestnosto September 15, 2025 10:24
Copilot finished work on behalf of timowestnosto September 15, 2025 10:24
Copilot finished work on behalf of timowestnosto September 15, 2025 10:28
* class CustomCampaign extends Campaign {
* async createContext(raw) {
* const context = await super.createContext(raw);
* return { ...context, customProperty: 'value' };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still not understanding.

  1. add utility functions - Can you elaborate on what kind of utility functions we are planning to expose to, for e.g., merchant's template? Are we going to create these CustomCampaign elements case-by-case basis and expose utility functions specific to every case?
  2. Use Shopify product data - How/Why do we mix Shopify product data into Nosto's recommendation data?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functions that could be useful are

  • formatting functions
  • event listener functions

We replace Nosto recommendation data with Shopify data for alignment

*
* @example
* ```typescript
* class CustomCampaign extends Campaign {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the cases where we would extend the Campaign custom element? Wouldn't it make it complex trying to promote inheritance?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see good alternatives for inheritance here, since registration of custom functionality into custom element classes is also not something that is available as a standard pattern

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat(Campaign): make context creation extensible via overridable template method
3 participants