Skip to content

Integrating and Updating Entities

This page offers examples on integrating and updating products and content entities in Relewise.

Our SDK helps making requests against our API eaiser for you.
It works both with strongly-typed TypeScript and with JavaScript.
You can also use it direcly via a CDN provider. Read more about that here.


Install the @relewise/integrations

In order to make any entity updates and management with TS / JS, you need to install the @relewise/integrations. Managing entities lives in its package as it is never something you want to do in the browser for security reasons.

bash
npm install @relewise/integrations

Before going any further, make sure you have read the following:

  • Read about how to authenticate against our API here.
  • Read about handling different types of users here.

Integrating and Updating Products with TS/JS

To get products into Relewise, follow the template laid out below. Be aware of different data types and when to use the correct one.

Add whatever fields are necessary for your integration to be useful for your search and/or recommendation requirements.

If you are unsure of what entity-actions to take, refer to our list of entity-actions.


To update or import the details of a single product, you can use a ProductUpdateBuilder and use the integrator.updateProduct to send the update to Relewise.

The following request uses ReplaceProvidedProperties, which creates a new product if the product hasn't been tracked before, and otherwise updates the properties set in the request for that product.

ts
// Copy dataset id + API key + server URL from 
// my.relewise.com > Administration -> API Keys
const integrator = new Integrator('00000000-0000-0000-0000-000000000001', 
'your api key', { serverUrl: 'the server URL for the dataset'});
// This is the recommended "Push" method, for importing product data into Relewise.

// Create a timestamp to distinguish active and inactive entities
// Read more at
// https://docs.relewise.com/docs/developer/bestpractices/product-integration.html
const date: number = Date.now();

// Language can be any string, and doesnt have to be a valid iso-standard.
const english = 'en'; 
const dkk = 'dkk';


const productUpdates: Trackable[] = [];

// Foreach product that needs to be imported, do the following:
{
    // Foreach variant of this product
    const variants: ProductVariant[] = [];
    {
        const variant: ProductVariant = {
            // Variant Id only has to be unique within the product
            id: 'The variant id',
            data: {
                'Materials': DataValueFactory.multilingualCollection(
                    [{ values: ['Wood', 'Metal'], language: english }]),
                'Colors': DataValueFactory.multilingualCollection(
                    [{ values: ['Red', 'Green'], language: english }]),
                'PrimaryMaterial': DataValueFactory.multilingual(
                    [{value: 'Wood', language: english}]),
                'PrimaryColor': DataValueFactory.multilingual(
                    [{value: 'Red', language: english}]),
            },
        };

        variants.push(variant);
    }
    // Foreach variant END

    const product = new ProductUpdateBuilder({
        id: 'Product-SKU-01', // The Id should be the primary id of the product
        productUpdateKind: 'ReplaceProvidedProperties',
        variantUpdateKind: 'ReplaceProvidedProperties',
        replaceExistingVariants: true, 
        // Replace existing variants = true will delete all variants in Relewise
		// (for the listed products) not included in this update request.
    })
        .displayName([
            // We only set the English translation in this example 
	    	// but more can be set by parsing more MultilingualValue 
		    // to the Multilingual::create method.
            { language: english, value: 'The English display name' }, 
        ])
        .salesPrice([{currency: dkk, amount: 199}])
        .listPrice([{currency: dkk, amount: 199}])
        .brand({
            id: 'brandId',
            // Displayname can be left out, but Id is required
            displayName: 'Brand display name', 
        })
        .data({
            // We only set the English translation in this example 
	    	// but more can be set by parsing more MultilingualValue 
		    // to the Multilingual::create method.
            'ShortDescription': DataValueFactory.multilingual(
                [{language: english, value: 'The short english description'}]), 
            // Important to set this timestamp to
            // the exact same value for all products
            'ImportedAt': DataValueFactory.number(date), 
            'MinimumAge': DataValueFactory.number(4),
            'InStock': DataValueFactory.boolean(true),
            'USPs': DataValueFactory.stringCollection(
                ['first usp', 'second usp', 'third usp']),

		    // Add any additional fields you would want returned from Relewise
        })
        .categoryPaths(b => b
            .path(p => p
                .category({
                    id: '74',
                    displayName: [{ language: english, value: 'Play' }],
                })
                .category({
                    id: '2',
                    displayName: [{ language: english, value: 'Swings' }],
                })
                .category({
                    id: '529',
                    displayName: [{ language: english, value: 'Swing Seats' }],
                }),
            ))
        .variants(variants);

    productUpdates.push(product.build());
}
// Foreach product element END

// If this is a full-import (not delta), disable all non-included product entities
{
    const disableNonUpdatedProducts = new ProductAdministrativeActionBuilder({
        language: null,
        currency: null,
        filters(filterBuilder) {
            filterBuilder
                .addProductDataFilter(
                    'ImportedAt',
                    (conditionBuilder) => conditionBuilder.addEqualsCondition(
                        DataValueFactory.number(date), true),
                );
        },
        productUpdateKind: 'Disable',
    });
    productUpdates.push(disableNonUpdatedProducts.build());
}

const enableUpdatedProducts = new ProductAdministrativeActionBuilder({
    language: null,
    currency: null,
    filters(filterBuilder) {
        filterBuilder
            .addProductDataFilter(
                'ImportedAt',
                (conditionBuilder) => conditionBuilder.addEqualsCondition(
                    DataValueFactory.number(date), false),
            );
    },
    productUpdateKind: 'Enable',
});

productUpdates.push(enableUpdatedProducts.build());

// Send all product updates and actions as a single (or few) network request.
// The client will automatically send batches of 1.000 items per network request, 
// so you can pass as many as you like to the tracker.Track / TrackAsync method.
await integrator.batch(productUpdates);

Integrating and Updating Content with TS/JS

To get content into Relewise, follow the template laid out below. Be aware of different data types and when to use the correct one.

Add whatever fields are necessary for your integration to be useful for your search and/or recommendation requirements.

If you are unsure of what entity-actions to take, refer to our list of entity-actions.

ts
// Copy dataset id + API key + server URL from 
// my.relewise.com > Administration -> API Keys
const integrator = new Integrator('00000000-0000-0000-0000-000000000001', 
'your api key', { serverUrl: 'the server URL for the dataset'});
// This is the recommended "Push" method, for importing content data into Relewise.

// Create a timestamp to distinguish active and inactive entities
// Read more at
// https://docs.relewise.com/docs/developer/bestpractices/product-integration.html
const date: number = Date.now();
// Language can be any string, and doesn't have to be a valid iso-standard.
const english = 'en'; 

const contentUpdates: Trackable[] = [];

// Foreach content element that needs to be imported, do the following:
{
    const content = new ContentUpdateBuilder({
        // The Id should be the primary id of the content
        id: 'Content-ID-01', 
        updateKind: 'ReplaceProvidedProperties',
    })
        .displayName([
            // We only set the English translation in this example 
	    	// but more can be set by parsing more MultilingualValue 
		    // to the Multilingual::create method.
            { language: english, value: 'The English display name' }, 
        ])
        .data({
            // We only set the English translation in this example 
	    	// but more can be set by parsing more MultilingualValue 
		    // to the Multilingual::create method.
            'ShortDescription': DataValueFactory.multilingual(
                [{language: english, value: 'The short English description'}]), 
            // Important to set this timestamp to
            // the exact same value for all entities 
            'ImportedAt': DataValueFactory.number(date), 
            'ReadingTimeInMinutes': DataValueFactory.number(3),
            'News': DataValueFactory.boolean(true),
            'Badges': DataValueFactory.stringCollection(
                ['fun', 'current season', 'some other badge']),

		    // Add any additional fields you would want returned from Relewise
        })
        .categoryPaths(b => b
            .path(p => p
                .category({
                    id: '23',
                    displayName: [{ language: english, value: 'Outdoor' }],
                })
                .category({
                    id: '372',
                    displayName: [{ language: english, value: 'Hiking' }],
                }),
            ));

    contentUpdates.push(content.build());
}
// For each content element END

// If this is a full-import (not delta), disable all non-included content elements
{
    const disableNonUpdatedContent = new ContentAdministrativeActionBuilder({
        language: null,
        currency: null,
        filters(filterBuilder) {
            filterBuilder
                .addContentDataFilter(
                    'ImportedAt',
                    (conditionBuilder) => conditionBuilder.addEqualsCondition(
                        DataValueFactory.number(date), true),
                );
        },
        kind: 'Disable',
    });
    contentUpdates.push(disableNonUpdatedContent.build());
}

const enableUpdatedContent = new ContentAdministrativeActionBuilder({
    language: null,
    currency: null,
    filters(filterBuilder) {
        filterBuilder
            .addContentDataFilter(
                'ImportedAt',
                (conditionBuilder) => conditionBuilder.addEqualsCondition(
                    DataValueFactory.number(date), false),
            );
    },
    kind: 'Enable',
});
contentUpdates.push(enableUpdatedContent.build());

	// Send all content updates and actions as a single (or few) network request.
	// The client will automatically send batches of 1.000 items per network request, 
	// so you can pass as many as you like to the tracker.Track / TrackAsync method.
await integrator.batch(contentUpdates);

Don't know us? Don't worry - you can find more information about us, by visiting our main page www.relewise.com