Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 0.61.0 #1184

Merged
merged 9 commits into from
Oct 25, 2024
32 changes: 16 additions & 16 deletions docs/INTEGRATION_LEGACY_RECOMMENDATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ For integrations using Snap `v0.60.0` and newer, please reference the updated [`
It is recommended to utilize the [`RecommendationInstantiator`](https://github.com/searchspring/snap/blob/main/packages/snap-preact/src/Instantiators/README.md) for integration of product recommendations. This method allows recommendations to be placed anywhere on the site with a single script block (requires the `bundle.js` script also).

```html
<script type="searchspring/recommend" profile="recently-viewed">
<script type="searchspring/personalized-recommendations" profile="recently-viewed">
// context variables go here
</script>
```
Expand Down Expand Up @@ -45,28 +45,28 @@ In most cases batching is the best practice, however for profiles like a mini ca
The example below shows how to manually specify the order of the profiles and how to dedupe them. In the example the 'bundle' profile in the batch receives the best suggestions because it has the lowest order, and the 'quick-cart' profile is not deduplicating products at all.

```html
<script type="searchspring/recommend" profile="customers-also-bought">
<script type="searchspring/personalized-recommendations" profile="customers-also-bought">
products = ['product123'];
options = {
order: 2
};
</script>

<script type="searchspring/recommend" profile="customers-also-viewed">
<script type="searchspring/personalized-recommendations" profile="customers-also-viewed">
products = ['product123'];
options = {
order: 3
};
</script>

<script type="searchspring/recommend" profile="bundle">
<script type="searchspring/personalized-recommendations" profile="bundle">
products = ['product123'];
options = {
order: 1
};
</script>

<script type="searchspring/recommend" profile="quick-cart">
<script type="searchspring/personalized-recommendations" profile="quick-cart">
products = ['product123'];
options = {
dedupe: false
Expand All @@ -77,11 +77,11 @@ The example below shows how to manually specify the order of the profiles and ho
Alternatively, a profile can be placed in it's own batch via the `batched: false` value. The example below shows how to place the 'quick-cart' profile into it's own batch.

```html
<script type="searchspring/recommend" profile="bundle">
<script type="searchspring/personalized-recommendations" profile="bundle">
products = ['product123'];
</script>

<script type="searchspring/recommend" profile="quick-cart">
<script type="searchspring/personalized-recommendations" profile="quick-cart">
products = ['product123'];
options = {
batched: false
Expand All @@ -96,23 +96,23 @@ The examples below assume that profiles used have been setup in the Searchspring
A typical "similar" profile that would display products similar to the product passed in via the `product` context variable.

```html
<script type="searchspring/recommend" profile="similar">
<script type="searchspring/personalized-recommendations" profile="similar">
products = ['sku123'];
</script>
```

If tracking scripts are not in place, "also bought" profiles may require the cart contents to be provided.

```html
<script type="searchspring/recommend" profile="view-cart">
<script type="searchspring/personalized-recommendations" profile="view-cart">
cart = ['sku456'];
</script>
```

If the shopper identifier is not beeing captured by the `bundle.js` context, it must be provided for proper personalization.

```html
<script type="searchspring/recommend" profile="similar">
<script type="searchspring/personalized-recommendations" profile="similar">
shopper = {
id: '[email protected]'
};
Expand All @@ -122,16 +122,16 @@ If the shopper identifier is not beeing captured by the `bundle.js` context, it
Having multiple scripts batched using the order context variable

```html
<script type="searchspring/recommend" profile="view-cart">
<script type="searchspring/personalized-recommendations" profile="view-cart">
options = {
<!-- this will be added 2nd -->
order: 2,
};
</script>
<script type="searchspring/recommend" profile="customers-also-viewed">
<script type="searchspring/personalized-recommendations" profile="customers-also-viewed">
<!-- this will be added 3rd -->
</script>
<script type="searchspring/recommend" profile="customers-also-bought">
<script type="searchspring/personalized-recommendations" profile="customers-also-bought">
options = {
<!-- this will be added 1st -->
order: 1
Expand All @@ -143,7 +143,7 @@ Having multiple scripts batched using the order context variable
The example shown below will filter the recommendations for products matching field `color` with a value `blue` and `red`, as well as a field `price` with a range from `0` to `20`.

```html
<script type="searchspring/recommend" profile="customers-also-bought">
<script type="searchspring/personalized-recommendations" profile="customers-also-bought">
options = {
filters: [
{
Expand All @@ -169,7 +169,7 @@ The example shown below will filter the recommendations for products matching fi
The next example shows a global filter being used, this will filter all of the profiles in the batch for products matching the field `onSale` with a value `true`; the 'similar' profile will additionally apply a filter using the field `price` with a range from `0` to `20`.

```html
<script type="searchspring/recommend" profile="customers-also-bought">
<script type="searchspring/personalized-recommendations" profile="customers-also-bought">
filters = [
{
type: 'value',
Expand All @@ -179,7 +179,7 @@ The next example shows a global filter being used, this will filter all of the p
];
</script>

<script type="searchspring/recommend" profile="similar">
<script type="searchspring/personalized-recommendations" profile="similar">
options = {
filters: [
{
Expand Down
22 changes: 11 additions & 11 deletions docs/INTEGRATION_RECOMMENDATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The block below uses the `recently-viewed` profile which would typically be setu
};
profiles = [
{
profile: 'recently-viewed',
tag: 'recently-viewed',
selector: '.ss__recs__recently-viewed',
options: {
limit: 5
Expand All @@ -28,7 +28,7 @@ The block below uses the `recently-viewed` profile which would typically be setu
<div class="ss__recs__recently-viewed" style="min-height: 100vh;"><!-- recommendations will render here --></div>
```

The `RecommendationInstantiator` will look for these script blocks on the page and attempt to inject components based on the `selector` specified in each profile. In the example above, the profile specified is the `recently-viewed` profile, and is set to render inside the `.ss__recs__recently-viewed` element just below the script block. The targeted element could exist anywhere on the page - but it is recommended to group elements with script blocks whenever possible (for easy integration identification). The component to render into the targeted `selector` is setup within the `RecommendationInstantiator` configuration. The targeted element should be given a `min-height` inline style to prevent cumulative layout shift.
The `RecommendationInstantiator` will look for these script blocks on the page and attempt to inject components based on the `selector` specified in each profile. In the example above, the profile specified (via tag) is the `recently-viewed` profile, and is set to render inside the `.ss__recs__recently-viewed` element just below the script block. The targeted element could exist anywhere on the page - but it is recommended to group elements with script blocks whenever possible (for easy integration identification). The component to render into the targeted `selector` is setup within the `RecommendationInstantiator` configuration. The targeted element should be given a `min-height` inline style to prevent cumulative layout shift.


## Recommendation Context Variables
Expand All @@ -47,7 +47,7 @@ Context variables are set within the script blocks and can be used to set either
### Profile Specific Variables
| Option | Value | Placement | Description | Required
|---|---|:---:|---|:---:|
| profile | string | all | profile name to use | ✔️ |
| tag | string | all | profile tag name to use | ✔️ |
| selector | string | all | CSS selector to render component inside | ✔️ |
| options.siteId | global siteId overwrite | all | optional global siteId overwrite | |
| options.categories | array of category path strings | all | optional category identifiers used in category trending recommendation profiles | |
Expand Down Expand Up @@ -85,23 +85,23 @@ Here's an example that demonstrates deduping:
```html
<script type="searchspring/recommendations">
globals = {
products: ['product123'];
products: ['product123']
};
profiles = [
{
profile: 'customers-also-bought',
tag: 'customers-also-bought',
selector: '.ss__recs__crosssell',
options: {
limit: 5
}
},
{
profile: 'customers-also-viewed',
tag: 'customers-also-viewed',
selector: '.ss__recs__similar'
},
// same batch, but dedupe false
{
profile: 'customers-also-like',
tag: 'customers-also-like',
selector: '.ss__recs__alsoliked',
options: {
dedupe: false
Expand All @@ -124,7 +124,7 @@ A typical "similar" profile that would display products similar to the product p
};
profiles = [
{
profile: 'customers-also-viewed',
tag: 'customers-also-viewed',
selector: '.ss__recs__similar'
}
];
Expand All @@ -140,7 +140,7 @@ If tracking scripts are not in place, "crosssell" profiles may require the cart
};
profiles = [
{
profile: 'customers-also-bought',
tag: 'customers-also-bought',
selector: '.ss__recs__crosssell'
}
];
Expand All @@ -158,7 +158,7 @@ If the shopper identifier is not beeing captured by the `bundle.js` context, it
};
profiles = [
{
profile: 'view-cart',
tag: 'view-cart',
selector: '.ss__recs__cart'
}
];
Expand All @@ -172,7 +172,7 @@ The example shown below will filter the recommendations for products matching fi
<script type="searchspring/recommendations">
profiles = [
{
profile: 'customers-also-bought',
tag: 'customers-also-bought',
selector: '.ss__recs__crosssell',
options: {
filters: [
Expand Down
2 changes: 0 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
function modifyLinks(markdown) {
var replaces = [
{ a: "(https://searchspring.github.io/snap/#/start-setup)", b: "(#/start-setup)"},
{ a: "(https://snapi.kube.searchspring.io/api/v1/#tag/Meta)", b: "(#/api-docs#Meta)"},
{ a: "(https://snapi.kube.searchspring.io/api/v1/)", b: "(#/api-docs)"},
{ a: "(https://searchspring.github.io/snapi-explorer/)", b: "(#/api-explorer)"},

{ a: "(https://github.com/searchspring/snap/blob/main/docs/SEARCH.md)", b: "(#/advanced-search)"},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"build:feed": "node ./docs/generateFeed.js",
"build:metrics": "node ./metrics/generate",
"test": "jest",
"posttest": "npm run test --workspace=@searchspring/snap-preact-demo",
"posttest": "npm run test --workspace=@searchspring/snap-preact-demo && npm run cypress:headless --workspace=@searchspring/snap-preact-components",
"dev": "lerna exec --parallel --stream 'npm run dev'",
"dev:docs": "http-server ./ -p 1111 -c-1",
"lint": "lerna run lint",
Expand Down
8 changes: 0 additions & 8 deletions packages/snap-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@

Simple Javascript client for communicating with the Searchspring Snap API.

## Quick Links

[Snap API docs](https://snapi.kube.searchspring.io/api/v1/) - Search & Autocomplete API documentation

[Snapi Explorer](https://searchspring.github.io/snapi-explorer/) - a tool for making requests to Searchspring's API

## Installation

```bash
Expand All @@ -34,8 +28,6 @@ const globals = {

Any other keys defined here will be passed to the API request

For a full list of parameters please see the [Snap API docs](https://snapi.kube.searchspring.io/api/v1/)

For example, with background filter:

```typescript
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,70 @@ describe('Autocomplete Controller', () => {
});
});

it('closes autocomplete via `setFocused` call when the document click events are made', async () => {
acConfig.selector = '.ss-ac';
document.body.innerHTML = '<div class="click-me"><input type="text" class="ss-ac"/></div>';

const inputEl: HTMLInputElement = document.querySelectorAll('.ss-ac')[0] as HTMLInputElement;

const controller = new AutocompleteController(acConfig, {
client: new MockClient(globals, {}),
store: new AutocompleteStore(acConfig, services),
urlManager,
eventManager: new EventManager(),
profiler: new Profiler(),
logger: new Logger(),
tracker: new Tracker(globals),
});

const setFocusedSpy = jest.spyOn(controller, 'setFocused');

await controller.bind();
const query = 'bumpers';
inputEl.value = query;
inputEl.dispatchEvent(new Event('input'));

document.querySelector('.click-me')?.dispatchEvent(new Event('click', { bubbles: true }));

expect(setFocusedSpy).toHaveBeenCalled();
});

it('disables document click (settings.disableClickOutside)', async () => {
acConfig.selector = '.ss-ac';
document.body.innerHTML = '<div class="click-me"><input type="text" class="ss-ac"/></div>';

const config = {
...acConfig,
settings: {
...acConfig.settings,
disableClickOutside: true,
},
};

const inputEl: HTMLInputElement = document.querySelectorAll('.ss-ac')[0] as HTMLInputElement;

const controller = new AutocompleteController(config, {
client: new MockClient(globals, {}),
store: new AutocompleteStore(acConfig, services),
urlManager,
eventManager: new EventManager(),
profiler: new Profiler(),
logger: new Logger(),
tracker: new Tracker(globals),
});

const setFocusedSpy = jest.spyOn(controller, 'setFocused');

await controller.bind();
const query = 'bumpers';
inputEl.value = query;
inputEl.dispatchEvent(new Event('input'));

document.querySelector('.click-me')?.dispatchEvent(new Event('click', { bubbles: true }));

expect(setFocusedSpy).not.toHaveBeenCalled();
});

it('does not serialize other form input elements normally (settings.serializeForm)', async () => {
document.body.innerHTML =
'<div><form action="/search.html"><input type="hidden" name="view" value="shop"/><input type="text" id="search_query"/></form></div>';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,10 @@ export class AutocompleteController extends AbstractController {
this.searchTrending();
}

document.addEventListener('click', this.handlers.document.click);
// if we are not preventing via `disableClickOutside` setting
if (!this.config.settings?.disableClickOutside) {
document.addEventListener('click', this.handlers.document.click);
}
}

searchTrending = async (): Promise<void> => {
Expand Down
3 changes: 2 additions & 1 deletion packages/snap-controller/src/Autocomplete/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ The `AutocompleteController` is used when making queries to the API `autocomplet
| id | unique identifier for this controller | ➖ | ✔️ |
| selector | css selector for input elements that DOM events should be bound to | ➖ | ✔️ |
| action | optional way to override the form action or provide one when it does not exist | ➖ | |
| globals | keys defined here will be passed to the [API request](https://snapi.kube.searchspring.io/api/v1/) (can overwrite global config)| ➖ | |
| globals | keys defined here will be passed to the API request (can overwrite global config)| ➖ | |
| settings.integratedSpellCorrection | integrated spell correction feature flag | false | |
| settings.initializeFromUrl | initialize the controller with query parameter from URL (pre-fill input with current search) | true | |
| settings.disableClickOutside | prevent the autocomplete from closing on clicks to the document | false | |
| settings.syncInputs | if the selector targets multiple inputs, the value of those inputs will be synced | true | |
| settings.serializeForm | if no action is specified in the config and a form element is found for the input, additional elements that are found will be added to the generated URLs (eg. hidden form input) | false | |
| settings.facets.trim | facets that do not change results will be removed | true | |
Expand Down
2 changes: 1 addition & 1 deletion packages/snap-controller/src/Finder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The `FinderController` should be used for building product finders. It makes que
|---|---|:---:|:---:|
| id | unique identifier for this controller | ➖ | ✔️ |
| url | URL to be redirected to upon clicking finder's 'find' button | ➖ | ✔️ |
| globals | keys defined here will be passed to the [API request](https://snapi.kube.searchspring.io/api/v1/) (can overwrite global config)| ```{ pagination: { pageSize: 0 } }``` | |
| globals | keys defined here will be passed to the API request (can overwrite global config)| ```{ pagination: { pageSize: 0 } }``` | |
| fields | an array of finder field configurations | ➖ | ✔️ |
| fields.field | required field name | ➖ | ✔️ |
| fields.label | optional finder label | ➖ | |
Expand Down
2 changes: 1 addition & 1 deletion packages/snap-controller/src/Recommendation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The `RecommendationController` is used when making queries to the API `recommend
| realtime | update recommendations if cart contents change (requires [cart attribute tracking](https://github.com/searchspring/snap/blob/main/docs/INTEGRATION.md)) | ➖ | |
| batched | batch multiple recommendations into a single network request | true | |
| limit | maximum number of results to display, can also be set globally via globals | 20 | |
| globals | keys defined here will be passed to the [API request](https://snapi.kube.searchspring.io/api/v1/) (can overwrite global config)| ➖ | |
| globals | keys defined here will be passed to the API request (can overwrite global config)| ➖ | |
| settings.variants.field | used to set the field in which to grab the variant data from | ➖ | |
| settings.variants.realtime.enabled | enable real time variant updates | ➖ | |
| settings.variants.realtime.filters | specify which filters to use to determine which results are updated | ➖ | |
Expand Down
2 changes: 1 addition & 1 deletion packages/snap-controller/src/Search/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ The `SearchController` is used when making queries to the API `search` endpoint.
| option | description | default value | required |
|---|---|:---:|:---:|
| id | unique identifier for this controller | ➖ | ✔️ |
| globals | keys defined here will be passed to the [API request](https://snapi.kube.searchspring.io/api/v1/) (can overwrite global config)| ➖ | |
| globals | keys defined here will be passed to the API request (can overwrite global config)| ➖ | |
| settings.redirects.merchandising | enable merchandising redirects | true | |
| settings.redirects.singleResult | enable redirect to product detail page if search yields 1 result count | true | |
| settings.facets.pinFiltered | selected facet options move to the top of the options array | true | |
Expand Down
2 changes: 1 addition & 1 deletion packages/snap-preact-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"storybook": "start-storybook -p 6006",
"cypress": "cypress open --project tests",
"cypress:headless": "cypress run --component --project tests",
"test": "jest; npm run cypress:headless",
"test": "jest",
"test:watch": "jest --watch"
},
"dependencies": {
Expand Down
Loading
Loading