-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduces CustomerSegmentationTemplate for ui-extensions and ui-exte…
…nsions-react Adds changeset Updates comment Fixes typo Moves CustomerSegmentationTemplateComponent to extension-points file Moves I18n to shared utility, Renamed extension points Properly re-export I18n and I18nTranslate Fixes examples, Renames prop to icon Uses a type instead of an enum. Adds comments on enabled features Drops Polaris from comment Uses single extension point Returns null Better examples Fixes conditional in example Fixes QL string in examples Uses render instead of show Marks enabledFeatures as private and add __ prefix Moves I18n to API Uses camelCase for categories, Make categories private Uses camelCase for enabled features type
- Loading branch information
Showing
13 changed files
with
259 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'@shopify/ui-extensions': patch | ||
'@shopify/ui-extensions-react': patch | ||
--- | ||
|
||
Introduces CustomerSegmentationTemplate component |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
...rc/surfaces/admin/components/CustomerSegmentationTemplate/CustomerSegmentationTemplate.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import {CustomerSegmentationTemplate as BaseCustomerSegmentationTemplate} from '@shopify/ui-extensions/admin'; | ||
import {createRemoteReactComponent} from '@remote-ui/react'; | ||
|
||
export const CustomerSegmentationTemplate = createRemoteReactComponent( | ||
BaseCustomerSegmentationTemplate, | ||
); | ||
export type {CustomerSegmentationTemplateProps} from '@shopify/ui-extensions/admin'; |
42 changes: 42 additions & 0 deletions
42
...components/CustomerSegmentationTemplate/examples/CustomerSegmentationTemplate.example.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import React from 'react'; | ||
import { | ||
reactExtension, | ||
CustomerSegmentationTemplate, | ||
} from '@shopify/ui-extensions-react/admin'; | ||
|
||
function App({i18n, enabledFeatures, category}) { | ||
if (category == 'reEngageCustomers') { | ||
const productsPurchasedOnTagsEnabled = enabledFeatures.includes('productsPurchasedByTags'); | ||
const templateQuery = productsPurchasedOnTagsEnabled | ||
? 'products_purchased(tag: (product_tag)) = true' | ||
: 'products_purchased(id: (product_id)) = true'; | ||
const templateQueryToInsert = productsPurchasedOnTagsEnabled | ||
? 'products_purchased(tag:' | ||
: 'products_purchased(id:'; | ||
|
||
return ( | ||
<CustomerSegmentationTemplate | ||
title={i18n.translate('product.title')} | ||
description={i18n.translate('product.description')} | ||
icon='productsMajor' | ||
templateQuery={templateQuery} | ||
templateQueryToInsert={templateQueryToInsert} | ||
/> | ||
); | ||
} | ||
|
||
if (category == 'location') { | ||
return ( | ||
<CustomerSegmentationTemplate | ||
title={i18n.translate('location.title')} | ||
description={i18n.translate('location.description')} | ||
icon='locationMajor' | ||
templateQuery="customer_cities CONTAINS 'US-NY-NewYorkCity'" | ||
/> | ||
); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
reactExtension('admin.customers.segmentation-templates.render', ({i18n, __category, __enabledFeatures}) => <App i18n={i18n} enabledFeatures={__enabledFeatures} category={__category} />); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,76 @@ | ||
export interface StandardApi { | ||
readonly extensionPoint: string; | ||
} | ||
|
||
/** | ||
* This defines the i18n.translate() signature. | ||
*/ | ||
export interface I18nTranslate { | ||
/** | ||
* This returns a translated string matching a key in a locale file. | ||
* | ||
* @example translate("banner.title") | ||
*/ | ||
<ReplacementType = string>( | ||
key: string, | ||
options?: {[placeholderKey: string]: ReplacementType | string | number}, | ||
): ReplacementType extends string | number | ||
? string | ||
: (string | ReplacementType)[]; | ||
} | ||
|
||
export interface I18n { | ||
/** | ||
* Returns a localized number. | ||
* | ||
* This function behaves like the standard `Intl.NumberFormat()` | ||
* with a style of `decimal` applied. It uses the buyer's locale by default. | ||
* | ||
* @param options.inExtensionLocale - if true, use the extension's locale | ||
*/ | ||
formatNumber: ( | ||
number: number | bigint, | ||
options?: {inExtensionLocale?: boolean} & Intl.NumberFormatOptions, | ||
) => string; | ||
|
||
/** | ||
* Returns a localized currency value. | ||
* | ||
* This function behaves like the standard `Intl.NumberFormat()` | ||
* with a style of `currency` applied. It uses the buyer's locale by default. | ||
* | ||
* @param options.inExtensionLocale - if true, use the extension's locale | ||
*/ | ||
formatCurrency: ( | ||
number: number | bigint, | ||
options?: {inExtensionLocale?: boolean} & Intl.NumberFormatOptions, | ||
) => string; | ||
|
||
/** | ||
* Returns a localized date value. | ||
* | ||
* This function behaves like the standard `Intl.DateTimeFormatOptions()` and uses | ||
* the buyer's locale by default. Formatting options can be passed in as | ||
* options. | ||
* | ||
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat0 | ||
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#using_options | ||
* | ||
* @param options.inExtensionLocale - if true, use the extension's locale | ||
*/ | ||
formatDate: ( | ||
date: Date, | ||
options?: {inExtensionLocale?: boolean} & Intl.DateTimeFormatOptions, | ||
) => string; | ||
|
||
/** | ||
* Returns translated content in the buyer's locale, | ||
* as supported by the extension. | ||
* | ||
* - `options.count` is a special numeric value used in pluralization. | ||
* - The other option keys and values are treated as replacements for interpolation. | ||
* - If the replacements are all primitives, then `translate()` returns a single string. | ||
* - If replacements contain UI components, then `translate()` returns an array of elements. | ||
*/ | ||
translate: I18nTranslate; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
export type {I18n, I18nTranslate} from '../../api'; | ||
export type {StandardApi} from './api/standard/standard'; | ||
export type {CustomerSegmentationTemplateApi} from './api/customer-segmentation-template/customer-segmentation-template'; |
30 changes: 30 additions & 0 deletions
30
...s/src/surfaces/admin/api/customer-segmentation-template/customer-segmentation-template.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import type {StandardApi} from '../standard/standard'; | ||
import type {I18n} from '../../../../api'; | ||
import type {ExtensionPoint as AnyExtensionPoint} from '../../extension-points'; | ||
|
||
/* List of enabled query language features during a progressive rollout */ | ||
type CustomerSegmentationFeature = | ||
/* Allows merchants to segment on products purchased by tags. For example: products_purchased(tag: 'Red hats') = true */ | ||
| 'productsPurchasedByTags' | ||
/* Enables count aggregates on functions. For example: shopify_email.opened(count_at_least: 5) = true */ | ||
| 'aggregateFilters'; | ||
|
||
type TemplateCategory = | ||
| 'all' | ||
| 'firstTimeBuyers' | ||
| 'highValueCustomers' | ||
| 'reEngageCustomers' | ||
| 'abandonedCheckout' | ||
| 'purchaseBehaviour' | ||
| 'location'; | ||
|
||
export interface CustomerSegmentationTemplateApi< | ||
ExtensionPoint extends AnyExtensionPoint, | ||
> extends StandardApi<ExtensionPoint> { | ||
/* Utilities for translating content according to the current `localization` of the admin. */ | ||
i18n: I18n; | ||
/** @private */ | ||
__category: TemplateCategory; | ||
/** @private */ | ||
__enabledFeatures: CustomerSegmentationFeature[]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
...rc/surfaces/admin/components/CustomerSegmentationTemplate/CustomerSegmentationTemplate.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import {createRemoteComponent} from '@remote-ui/core'; | ||
|
||
type Source = | ||
| 'categoriesMajor' | ||
| 'firstVisitMajor' | ||
| 'heartMajor' | ||
| 'marketingMajor' | ||
| 'checkoutMajor' | ||
| 'ordersMajor' | ||
| 'locationMajor' | ||
| 'emailNewsletterMajor' | ||
| 'firstOrderMajor' | ||
| 'billingStatementDollarMajor' | ||
| 'diamondAlertMajor' | ||
| 'abandonedCartMajor' | ||
| 'calendarMajor' | ||
| 'productsMajor' | ||
| 'globeMajor' | ||
| 'flagMajor' | ||
| 'uploadMajor' | ||
| 'buyButtonMajor' | ||
| 'followUpEmailMajor'; | ||
|
||
export interface CustomerSegmentationTemplateProps { | ||
/** Localized title of the template. */ | ||
title: string; | ||
/** Localized description of the template. */ | ||
description: string; | ||
/** Icon identifier for the template. This property is ignored for non-1P Segmentation templates as we fallback to the app icon */ | ||
icon?: Source; | ||
/** ShopifyQL code snippet to render in the template with syntax highlighting **/ | ||
templateQuery: string; | ||
/** ShopifyQL code snippet to insert in the segment editor. If missing, `templateQuery` will be used. */ | ||
templateQueryToInsert?: string; | ||
} | ||
|
||
/** | ||
* Customer segmentation templates are used to give merchants a starting point to create segments. | ||
*/ | ||
export const CustomerSegmentationTemplate = createRemoteComponent< | ||
'CustomerSegmentationTemplate', | ||
CustomerSegmentationTemplateProps | ||
>('CustomerSegmentationTemplate'); |
39 changes: 39 additions & 0 deletions
39
.../components/CustomerSegmentationTemplate/examples/CustomerSegmentationTemplate.example.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { | ||
extension, | ||
CustomerSegmentationTemplate, | ||
} from '@shopify/ui-extensions/admin'; | ||
|
||
export default extension( | ||
'admin.customers.segmentation-templates.render', | ||
(root, {i18n, __category, __enabledFeatures}) => { | ||
if (__category === 'reEngageCustomers') { | ||
const productsPurchasedOnTagsEnabled = __enabledFeatures.includes('productsPurchasedByTags'); | ||
const productTemplate = root.createComponent(CustomerSegmentationTemplate, { | ||
title: i18n.translate('product.title'), | ||
description: i18n.translate('product.description'), | ||
icon: 'productsMajor', | ||
templateQuery: productsPurchasedOnTagsEnabled | ||
? 'products_purchased(tag: (product_tag)) = true' | ||
: 'products_purchased(id: (product_id)) = true', | ||
templateQueryToInsert: productsPurchasedOnTagsEnabled | ||
? 'products_purchased(tag:' | ||
: 'products_purchased(id:', | ||
}); | ||
|
||
root.appendChild(productTemplate); | ||
} | ||
|
||
if (__category === 'location') { | ||
const locationTemplate = root.createComponent(CustomerSegmentationTemplate, { | ||
title: i18n.translate('location.title'), | ||
description: i18n.translate('location.description'), | ||
icon: 'locationMajor', | ||
templateQuery: "customer_cities CONTAINS 'US-NY-NewYorkCity'", | ||
}); | ||
|
||
root.appendChild(locationTemplate); | ||
} | ||
|
||
root.mount(); | ||
}, | ||
); |
13 changes: 11 additions & 2 deletions
13
packages/ui-extensions/src/surfaces/admin/extension-points.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters