diff --git a/code_samples/ai_actions/config/packages/ibexa_connector_gemini.yaml b/code_samples/ai_actions/config/packages/ibexa_connector_gemini.yaml new file mode 100644 index 0000000000..09803c9e8f --- /dev/null +++ b/code_samples/ai_actions/config/packages/ibexa_connector_gemini.yaml @@ -0,0 +1,20 @@ +ibexa_connector_gemini: + text_to_text: + models: + gemini-pro-latest: + label: 'Gemini Pro Latest' + max_tokens: 4096 + gemini-flash-latest: + label: 'Gemini Flash Latest' + max_tokens: 4096 + default_model: gemini-pro-latest + default_max_tokens: 4096 # Must be <= the model’s max_tokens + default_temperature: 0.8 + image_to_text: + models: + gemini-flash-latest: + label: 'Gemini Flash Latest' + max_tokens: 4096 + default_model: gemini-flash-latest + default_max_tokens: 4096 + default_temperature: 1.0 diff --git a/code_samples/back_office/product_tour/config/general_scenario.yaml b/code_samples/back_office/product_tour/config/general_scenario.yaml new file mode 100644 index 0000000000..75a9d526c8 --- /dev/null +++ b/code_samples/back_office/product_tour/config/general_scenario.yaml @@ -0,0 +1,40 @@ +ibexa: + system: + admin_group: + product_tour: + my_general_scenario: + type: 'general' + scenario_title_translation_key: tour.my_general_scenario.title + steps: + welcome_step: + step_title_translation_key: title + background_image: /public/img/background.jpg + blocks: + - type: title + params: + text_translation_key: subtitle + - type: text + params: + text_translation_key: tour.step.description + - type: link + params: + url: https://doc.ibexa.co + text_translation_key: tour.link.documentation + - type: image + params: + src: /public/img/diagram.jpg + alt_translation_key: tour.image.alt + - type: video + params: + # 'Big Buck Bunny' licensed under CC 3.0 by the Blender foundation. Hosted by archive.org + url: https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4 + - type: list + params: + title_translation_key: tour.list.title + items_translation_keys: + - tour.list.item1 + - tour.list.item2 + - tour.list.item3 + - type: twig_template + params: + template: custom_template.html.twig diff --git a/code_samples/back_office/product_tour/config/targetable_scenario.yaml b/code_samples/back_office/product_tour/config/targetable_scenario.yaml new file mode 100644 index 0000000000..a09af8b609 --- /dev/null +++ b/code_samples/back_office/product_tour/config/targetable_scenario.yaml @@ -0,0 +1,40 @@ +ibexa: + system: + admin_group: + product_tour: + targetable_dashboard_scenario: + type: 'targetable' + scenario_title_translation_key: tour.targetable_dashboard_scenario.title + steps: + dashboard_options: + step_title_translation_key: Open Dashboard options + target: ".ibexa-db-header__more" + # No interaction_mode specified or the value is set to null + blocks: + - type: text + params: + text_translation_key: Learn how to customize the blocks displayed on your dashboard + open_dashboard_options: + step_title_translation_key: Open Dashboard options + target: '.ibexa-db-header__more' + interaction_mode: clickable + blocks: + - type: text + params: + text_translation_key: Click here to customize your dashboard + customize_dashboard: + step_title_translation_key: Customize Dashboard + target: '.ibexa-db-actions-popup-menu' + interaction_mode: clickable + blocks: + - type: text + params: + text_translation_key: Choose "Customize dashboard" + drag_and_drop_step: + step_title_translation_key: Drag-and-drop blocks + target: ".c-pb-toolbox-blocks-group__blocks > * .c-pb-toolbox-block__content:first-of-type" + interaction_mode: draggable + blocks: + - type: text + params: + text_translation_key: Drag-and-drop blocks from the sidebar to the dashboard to customize it diff --git a/code_samples/back_office/product_tour/src/EventSubscriber/NotificationScenarioSubscriber.php b/code_samples/back_office/product_tour/src/EventSubscriber/NotificationScenarioSubscriber.php new file mode 100644 index 0000000000..78ae51c261 --- /dev/null +++ b/code_samples/back_office/product_tour/src/EventSubscriber/NotificationScenarioSubscriber.php @@ -0,0 +1,62 @@ + ['onRenderScenario'], + ]; + } + + public function onRenderScenario(RenderProductTourScenarioEvent $event): void + { + $scenario = $event->getScenario(); + $steps = $scenario->getSteps(); + + if ($scenario->getIdentifier() !== 'notifications') { + return; + } + + foreach ($steps as $step) { + $scenario->removeStep($step); + } + + if (!$this->hasUnreadNotifications()) { + return; + } + + $customStep = new ProductTourStep(); + $customStep->setIdentifier('custom_step_identifier'); + $customStep->setInteractionMode('clickable'); + $customStep->setTarget('.ibexa-header-user-menu__notifications-toggler'); + $customStep->setTitle('You have unread notifications'); + $customStep->addBlock(new TextBlock('Click here to preview your unread notifications.')); + $customStep->addBlock(new LinkBlock( + 'https://doc.ibexa.co/projects/userguide/en/latest/getting_started/notifications/', + 'Learn more about notifications' + )); + + $scenario->addStep($customStep); + } + + private function hasUnreadNotifications(): bool + { + return $this->notificationService->getPendingNotificationCount() > 0; + } +} diff --git a/code_samples/back_office/search/src/Query/ProductCategorySubtreeQuery.php b/code_samples/back_office/search/src/Query/ProductCategorySubtreeQuery.php new file mode 100644 index 0000000000..d050f96bed --- /dev/null +++ b/code_samples/back_office/search/src/Query/ProductCategorySubtreeQuery.php @@ -0,0 +1,12 @@ +setQuery($criteria); +$results = $productService->findProducts($productQuery); diff --git a/code_samples/back_office/search/src/Query/UpdatedAtQuery.php b/code_samples/back_office/search/src/Query/UpdatedAtQuery.php new file mode 100644 index 0000000000..e30aeecc40 --- /dev/null +++ b/code_samples/back_office/search/src/Query/UpdatedAtQuery.php @@ -0,0 +1,16 @@ +setQuery($criteria); +$results = $productService->findProducts($productQuery); diff --git a/code_samples/back_office/search/src/Query/UpdatedAtRangeQuery.php b/code_samples/back_office/search/src/Query/UpdatedAtRangeQuery.php new file mode 100644 index 0000000000..49c5461ecb --- /dev/null +++ b/code_samples/back_office/search/src/Query/UpdatedAtRangeQuery.php @@ -0,0 +1,15 @@ +setQuery($criteria); +$results = $productService->findProducts($productQuery); diff --git a/code_samples/data_migration/examples/sql_execute.yaml b/code_samples/data_migration/examples/sql_execute.yaml new file mode 100644 index 0000000000..c11ca0bb4a --- /dev/null +++ b/code_samples/data_migration/examples/sql_execute.yaml @@ -0,0 +1,13 @@ +- + type: sql + mode: execute + query: + - + driver: mysql + sql: 'INSERT INTO test_table (test_value) VALUES ("foo");' + - + driver: sqlite + sql: 'INSERT INTO test_table (test_value) VALUES ("foo");' + - + driver: postgresql + sql: "INSERT INTO test_table (test_value) VALUES ('foo');" diff --git a/code_samples/data_migration/examples/try_catch_step.yaml b/code_samples/data_migration/examples/try_catch_step.yaml new file mode 100644 index 0000000000..0cb8206beb --- /dev/null +++ b/code_samples/data_migration/examples/try_catch_step.yaml @@ -0,0 +1,14 @@ +- + type: try_catch + mode: execute + allowed_exceptions: + - Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException + stop_after_first_exception: true + steps: + - + type: language + mode: create + metadata: + languageCode: ger-DE + name: German + enabled: true diff --git a/code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php b/code_samples/product_catalog/Symbol/Format/Checksum/LuhnChecksum.php similarity index 100% rename from code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php rename to code_samples/product_catalog/Symbol/Format/Checksum/LuhnChecksum.php diff --git a/code_samples/product_catalog/src/EventSubscriber/MyAttributeRenderSubscriber.php b/code_samples/product_catalog/src/EventSubscriber/MyAttributeRenderSubscriber.php new file mode 100644 index 0000000000..44d61854c2 --- /dev/null +++ b/code_samples/product_catalog/src/EventSubscriber/MyAttributeRenderSubscriber.php @@ -0,0 +1,18 @@ +addTemplateBefore( + 'templates/product/attributes/integer_attribute.html.twig', + '@ibexadesign/product_catalog/product/attributes/attribute_blocks.html.twig', + ); + } +} diff --git a/code_samples/recommendations/EventData.php b/code_samples/recommendations/EventData.php new file mode 100644 index 0000000000..4825ed6114 --- /dev/null +++ b/code_samples/recommendations/EventData.php @@ -0,0 +1,28 @@ +getCode(), + productName: $product->getName(), + categoryPath: '25#Electronics;26#Smartphones', // Build manually + currency: 'USD', + itemPrice: '999.99' + ); + + $this->trackingDispatcher->dispatch($eventData); + } +} diff --git a/code_samples/recommendations/EventMapper.php b/code_samples/recommendations/EventMapper.php new file mode 100644 index 0000000000..cf0bd3bd8e --- /dev/null +++ b/code_samples/recommendations/EventMapper.php @@ -0,0 +1,29 @@ +eventMapper->map(EventType::VISIT, $product, [ + EventContext::CATEGORY_IDENTIFIER => 'electronics', + ]); + + // Send tracking event + $this->trackingDispatcher->dispatch($eventData); + } +} diff --git a/code_samples/recommendations/EventSubscriber.php b/code_samples/recommendations/EventSubscriber.php new file mode 100644 index 0000000000..175784efc4 --- /dev/null +++ b/code_samples/recommendations/EventSubscriber.php @@ -0,0 +1,42 @@ + ['onResponse', -10]]; + } + + public function onResponse(ResponseEvent $event): void + { + if (!$event->isMainRequest()) { + return; + } + + $request = $event->getRequest(); + + // Example: track only if request has specific attribute + $product = $request->attributes->get('product'); + if (null === $product) { + return; + } + + $eventData = $this->eventMapper->map(EventType::VISIT, $product); + $this->trackingDispatcher->dispatch($eventData); + } +} diff --git a/code_samples/recommendations/config/packages/ibexa_connector_raptor.yaml b/code_samples/recommendations/config/packages/ibexa_connector_raptor.yaml new file mode 100644 index 0000000000..61c90252b1 --- /dev/null +++ b/code_samples/recommendations/config/packages/ibexa_connector_raptor.yaml @@ -0,0 +1,16 @@ +ibexa: + system: + : + connector_raptor: + enabled: true + customer_id: ~ # Required + tracking_type: client # One of: "client" or "server" + + # Raptor Recommendations API key + recommendations_api_key: ~ # Required + + # Raptor Recommendations API URL, optional, set by default + recommendations_api_url: '%ibexa.connector.raptor.recommendations.api_url%' +ibexa_connector_raptor: + # When enabled, tracking exceptions are thrown instead of being silently handled + strict_exceptions: true diff --git a/code_samples/recommendations/custom_integration.html b/code_samples/recommendations/custom_integration.html new file mode 100644 index 0000000000..339dcd8be7 --- /dev/null +++ b/code_samples/recommendations/custom_integration.html @@ -0,0 +1,31 @@ +``` html + + + + + +``` diff --git a/code_samples/recommendations/events/basket_event.html.twig b/code_samples/recommendations/events/basket_event.html.twig new file mode 100644 index 0000000000..11df19b560 --- /dev/null +++ b/code_samples/recommendations/events/basket_event.html.twig @@ -0,0 +1,25 @@ +{# templates/cart/add_confirmation.html.twig #} +{% extends 'base.html.twig' %} + +{% block content %} +
+

Product "{{ product.name }}" has been added to your cart!

+

Quantity: {{ addedQuantity }}

+
+ + {# Build basket content string: "product-code:quantity;product-code:quantity" #} + {% set basketContent = [] %} + {% for entry in cart.entries %} + {% set basketContent = basketContent|merge([entry.product.code ~ ':' ~ entry.quantity]) %} + {% endfor %} + {# Track basket addition #} + {% set basketContext = { + 'basketContent': basketContent|join(';'), + 'basketId': cart.id, + 'quantity': addedQuantity + } %} + + {{ ibexa_tracking_track_event('basket', product, basketContext) }} + + View Cart +{% endblock %} diff --git a/code_samples/recommendations/events/buy_event.html.twig b/code_samples/recommendations/events/buy_event.html.twig new file mode 100644 index 0000000000..47c97212dd --- /dev/null +++ b/code_samples/recommendations/events/buy_event.html.twig @@ -0,0 +1,6 @@ +{% set buyContext = { + 'subtotal': '10.00', + 'currency': 'EUR', + 'quantity': 1 +} %} +{{ ibexa_tracking_track_event('buy', product, buyContext) }} diff --git a/code_samples/recommendations/events/content_visit_event.html.twig b/code_samples/recommendations/events/content_visit_event.html.twig new file mode 100644 index 0000000000..8723147fe6 --- /dev/null +++ b/code_samples/recommendations/events/content_visit_event.html.twig @@ -0,0 +1,7 @@ +{# templates/bundles/IbexaCoreBundle/default/content/full.html.twig #} +{% extends '@!IbexaCore/default/content/full.html.twig' %} + +{% block content %} + {{ parent() }} + {{ ibexa_tracking_track_event('contentvisit', content) }} +{% endblock %} diff --git a/code_samples/recommendations/events/itemclicked_event.html.twig b/code_samples/recommendations/events/itemclicked_event.html.twig new file mode 100644 index 0000000000..fc3cf42dfb --- /dev/null +++ b/code_samples/recommendations/events/itemclicked_event.html.twig @@ -0,0 +1,4 @@ +{{ ibexa_tracking_track_event('itemclick', product.code, { + 'moduleName': 'homepage-recommendations', + 'redirectUrl': path('ibexa.product.view', {'productCode': product.code}) +}) }} diff --git a/code_samples/recommendations/events/product_visit_event.html.twig b/code_samples/recommendations/events/product_visit_event.html.twig new file mode 100644 index 0000000000..be2c149064 --- /dev/null +++ b/code_samples/recommendations/events/product_visit_event.html.twig @@ -0,0 +1,13 @@ +# templates/product/view.html.twig #} +{% extends 'base.html.twig' %} + +{% block content %} +
+

{{ product.name }}

+

{{ product.description }}

+
{{ product.price }}
+
+ + {# Track product visit #} + {{ ibexa_tracking_track_event('visit', product) }} +{% endblock %} diff --git a/code_samples/recommendations/templates/themes/standard/ibexa/tracking/script.html.twig b/code_samples/recommendations/templates/themes/standard/ibexa/tracking/script.html.twig new file mode 100644 index 0000000000..40eedecb7d --- /dev/null +++ b/code_samples/recommendations/templates/themes/standard/ibexa/tracking/script.html.twig @@ -0,0 +1,4 @@ +{% extends '@IbexaConnectorRaptor/themes/standard/ibexa/tracking/script.html.twig' %} +{% block ibexa_tracking_script %} + console.log('My custom tracking script, but relying on loadTracking function.'); +{% endblock %} diff --git a/code_samples/recommendations/templates/themes/standard/ibexa/tracking/script.js.twig b/code_samples/recommendations/templates/themes/standard/ibexa/tracking/script.js.twig new file mode 100644 index 0000000000..c9f3ecddae --- /dev/null +++ b/code_samples/recommendations/templates/themes/standard/ibexa/tracking/script.js.twig @@ -0,0 +1,5 @@ + diff --git a/code_samples/recommendations/templates/themes/standard/pagelayout.html.twig b/code_samples/recommendations/templates/themes/standard/pagelayout.html.twig new file mode 100644 index 0000000000..33fc86b155 --- /dev/null +++ b/code_samples/recommendations/templates/themes/standard/pagelayout.html.twig @@ -0,0 +1,13 @@ +{# templates/pagelayout.html.twig #} + + + + {# ... other head content ... #} + + {# Initialize Raptor tracking - must be called before any tracking events #} + {{ ibexa_tracking_script() }} + + + {# ... page content ... #} + + diff --git a/code_samples/recommendations/templates/tracking/custom_visit.html.twig b/code_samples/recommendations/templates/tracking/custom_visit.html.twig new file mode 100644 index 0000000000..9214e47f3b --- /dev/null +++ b/code_samples/recommendations/templates/tracking/custom_visit.html.twig @@ -0,0 +1,33 @@ +{# templates/tracking/custom_visit.html.twig #} + +{# +# Custom visit tracking template +# +# Available variables, passed to the template by `ibexa_tracking_track_event`: +# - parameters: array of Raptor tracking parameters (p1, p2, p3, etc.) +# - debug: boolean flag to enable debug console messages +#} + + diff --git a/code_samples/search/content/taxonomy_no_entries_criterion.php b/code_samples/search/content/taxonomy_no_entries_criterion.php new file mode 100644 index 0000000000..048006d41c --- /dev/null +++ b/code_samples/search/content/taxonomy_no_entries_criterion.php @@ -0,0 +1,19 @@ +query = new LogicalAnd( + [ + new TaxonomyNoEntries('tags'), + new ContentTypeIdentifier('article'), + ] +); + +/** @var \Ibexa\Contracts\Core\Repository\SearchService $searchService */ +$results = $searchService->findContent($query); diff --git a/code_samples/search/content/taxonomy_subtree_criterion.php b/code_samples/search/content/taxonomy_subtree_criterion.php new file mode 100644 index 0000000000..c13f94ed70 --- /dev/null +++ b/code_samples/search/content/taxonomy_subtree_criterion.php @@ -0,0 +1,19 @@ +query = new LogicalAnd( + [ + new TaxonomySubtree(42), + new ContentTypeIdentifier('article'), + ] +); + +/** @var \Ibexa\Contracts\Core\Repository\SearchService $searchService */ +$results = $searchService->findContent($query); diff --git a/composer.json b/composer.json index 1f8cb44b1e..e9415fc8fd 100644 --- a/composer.json +++ b/composer.json @@ -78,11 +78,14 @@ "ibexa/messenger": "~5.0.x-dev", "ibexa/collaboration": "~5.0.x-dev", "ibexa/share": "~5.0.x-dev", - "ibexa/shopping-list": "~5.0.x-dev", "ibexa/phpstan": "~5.0.-dev", + "ibexa/connector-quable": "5.0.x-dev", + "ibexa/shopping-list": "~5.0.x-dev", "deptrac/deptrac": "^3.0", "ibexa/cdp": "~5.0.x-dev", - "ibexa/image-editor": "~5.0.x-dev" + "ibexa/connector-raptor": "~5.0.x-dev", + "ibexa/image-editor": "~5.0.x-dev", + "ibexa/integrated-help": "~5.0.x-dev" }, "scripts": { "fix-cs": "php-cs-fixer fix --config=.php-cs-fixer.php -v --show-progress=dots", diff --git a/deptrac.baseline.yaml b/deptrac.baseline.yaml index fe87eb8465..85f245e75f 100644 --- a/deptrac.baseline.yaml +++ b/deptrac.baseline.yaml @@ -131,6 +131,10 @@ deptrac: App\EventSubscriber\MyMenuSubscriber: - Ibexa\AdminUi\Menu\Event\ConfigureMenuEvent - Ibexa\AdminUi\Menu\MainMenuBuilder + App\EventSubscriber\NotificationScenarioSubscriber: + - Ibexa\IntegratedHelp\ProductTour\Block\LinkBlock + - Ibexa\IntegratedHelp\ProductTour\Block\TextBlock + - Ibexa\IntegratedHelp\ProductTour\ProductTourStep App\Event\RandomBlockListener: - Ibexa\FieldTypePage\FieldType\Page\Block\Renderer\BlockRenderEvents - Ibexa\FieldTypePage\FieldType\Page\Block\Renderer\Event\PreRenderEvent diff --git a/docs/administration/back_office/back_office_elements/custom_components.md b/docs/administration/back_office/back_office_elements/custom_components.md index c7e95e0c85..04a3ef8df1 100644 --- a/docs/administration/back_office/back_office_elements/custom_components.md +++ b/docs/administration/back_office/back_office_elements/custom_components.md @@ -78,6 +78,10 @@ For more information, see [this example using few of those components](component |`admin-ui-product-edit-form-header-actions`| `vendor/ibexa/product-catalog/src/bundle/Resources/views/themes/admin/product_catalog/product/edit.html.twig` | |`admin-ui-product-edit-form-after`| `vendor/ibexa/product-catalog/src/bundle/Resources/views/themes/admin/product_catalog/product/edit.html.twig` | |`admin-ui-product-block`| `vendor/ibexa/product-catalog/src/bundle/Resources/views/themes/admin/product_catalog/product/view.html.twig` | +|`admin-ui-product-translation-modal-footer`| `vendor/ibexa/product-catalog/src/bundle/Resources/views/themes/admin/product_catalog/product/modal/add_translation.html.twig` | +|`admin-ui-product-translations-actions-modal`| `vendor/ibexa/product-catalog/src/bundle/Resources/views/themes/admin/product_catalog/product/tab/translations.html.twig` | +|`admin-ui-product-translations-actions`| `vendor/ibexa/product-catalog/src/bundle/Resources/views/themes/admin/product_catalog/product/tab/translations.html.twig` | +|`admin-ui-product-translations-row-actions`| `vendor/ibexa/product-catalog/src/bundle/Resources/views/themes/admin/product_catalog/product/tab/translations.html.twig` | |`admin-ui-product-type-block`| `vendor/ibexa/product-catalog/src/bundle/Resources/views/themes/admin/product_catalog/product_type/view.html.twig` | ## Taxonomy diff --git a/docs/administration/back_office/configure_product_tour.md b/docs/administration/back_office/configure_product_tour.md new file mode 100644 index 0000000000..d5e4aada2b --- /dev/null +++ b/docs/administration/back_office/configure_product_tour.md @@ -0,0 +1,299 @@ +--- +description: Configure custom product tour scenarios with steps, blocks, and interaction modes. +edition: lts-update +month_change: true +--- + +# Configure product tour scenarios + +You can configure the product tour scenarios to adapt it to your project needs, covering different onboarding scenarios. + +Product tour scenarios are configured with YAML configuration files. +Configuration is SiteAccess-aware, allowing you to create separate onboarding experiences for different back offices in [multisite setups](multisite.md). + +For more advanced customization cases that require PHP code, see [Customize product tour](customize_product_tour.md). + +Use the default provided configuration, available in `config/packages/ibexa_integrated_help_tours.yaml`, as a starting point that you can adjust to your needs. + +## Configuration structure + +You configure product tour scenarios under the `ibexa.system..product_tour` key. +Each scenario has a unique identifier and contains steps, which in turn contain blocks. + +The basic configuration structure of a scenario is as follows: + +```yaml +ibexa: + system: + >: # For example, admin or admin_group + product_tour: + : + type: + scenario_title_translation_key: # Optional + user_groups_excluded: [, ...] # Optional + steps: + : # Scenario step, unique within a scenario + step_title_translation_key: + background_image: # Only for general type, optional + target: # Only for targetable type, required + interaction_mode: # Only for targetable type, optional + blocks: + - type: + params: + # Block-specific parameters + # ... +``` + +The product tour scenarios are meant to be translatable. +[[= product_name_base =]] recommends using translation keys instead of literal values in the YAML configuration, and providing the translations separately. +Use the `ibexa_integrated_help` translation domain. + +For all the examples below, you can provide the translations by creating a `translations/ibexa_integrated_help.en.yaml` file with the following content: + +``` yaml +tour.my_general_scenario.title: "My general scenario" +title: "Welcome!" +subtitle: "This is the subtitle" +tour.step.description: "This is the description of the step, you can use it to explain what to do in this step." +tour.link.documentation: "Documentation link" +tour.list.title: "This is the list title" +tour.list.item1: "First item" +tour.list.item2: "Second item" +tour.list.item3: "Third item" +``` + +To insert a line break into a translation, HTML encode the `
` entities to `<br/>`. + +## Scenario configuration + +Each scenario must specify its type and can optionally restrict access by user groups. + +### Scenario display order + +The order of scenarios in the configuration file determines the order in which they are evaluated and, if the right conditions are met, displayed. + +There are two [scenario types](product_tour.md#scenario-types): + +- `general` scenarios appear at the earliest opportunity (on any page after logging in), with an exception of the user settings area +- `targetable` scenarios begin if their `target` element is found in the DOM when the page is loaded. +Targetable scenarios don't trigger in the user settings area as well. + +To control where a targetable tour appears, ensure that the first step targets an element unique to that specific page. +You can target elements that appear after a user action, for example, modals like [content browser](browser.md), but the first step's target must be present in the DOM when the page is loaded. + +Once a scenario ends, the system evaluates the next scenario from the configuration and, if applicable, displays it. + +### Scenario title + +Use the optional `scenario_title_translation_key` field to provide a human-readable label for a scenario. +This label is displayed in the user settings page where users can reset their product tour progress. + +```yaml +product_tour: + welcome_tour: + type: general + scenario_title_translation_key: tour.welcome_tour.title +``` + +If the translation key is not set, the raw scenario identifier is used as the label. + +Translations must be provided in the `ibexa_integrated_help` translation domain, for example, in `translations/ibexa_integrated_help.en.yaml`. + +### User group restrictions + +Restrict scenario visibility by excluding specific user groups by using their content remote IDs: + +```yaml +product_tour: + my_scenario: + user_groups_excluded: ['user_group_content_remote_id_1', 'user_group_content_remote_id_2'] # Exclude specific user groups +``` + +When creating new [back office user groups](user_registration.md#user-types), decide whether the existing product tour scenarios should be available for these new user groups. +If not, add the new group to the exclusion list. + +!!! warning + + If a scenario contains information meant only for specific group of users, always use the `user_groups_excluded` setting to exclude other groups. + Don't rely only on UI access restrictions to control the access to scenarios, as a malicious internal user could trigger and preview them outside of the intended place. + +## Step configuration + +Steps define individual instructions within a scenario. +The configuration differs based on scenario type: + +### General scenario steps + +General scenario steps display centered modals and support the `background_image` setting, allowing you to set a shared background image for each step. +For the background, you can use an absolute URL or place your image in the `public` directory and provide the path relative to it. +To resolve the path relative to the site root, [prefix it with `/`](https://developer.mozilla.org/en-US/docs/Web/API/URL_API/Resolving_relative_references#root_relative). + +```yaml hl_lines="6 11" +[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 0, 14) =]] +``` + +### Targetable tour steps + +Targetable tour steps highlight specific UI elements by using CSS selectors. +You can select a specific element by using the `target` setting. + +```yaml hl_lines="6 11" +[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml', 0, 15) =]] +``` + +If a step's target element doesn't exist on the page, the step isn't displayed and the scenario is stopped. +Ensure your configuration matches the actual DOM structure to avoid broken scenarios. +Use unique selectors to avoid triggering your scenarios on other pages. + +#### Interaction modes + +Select how the scenario step interacts with the target element by using the `interaction_mode` setting. +Targetable steps support [three interaction modes](product_tour.md#targetable-scenarios): + +!!! note + + Clickable and draggable modes are designed for single actions only (buttons, links). + You can't select an entire form. + If the interaction with the highlighted element results in redirection to a new page or opening a modal window where the previous target element can't be found, the "Previous" navigation button won't be displayed. + +**Standard mode**: + +The default value. +A tooltip attached to a specific element on the page is displayed. +Users continue the scenario with **Previous**/**Next** buttons: + +```yaml +[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml', 8, 16) =]] +``` + +![Standard interaction mode](img/product_tour/standard_mode.png "Standard interaction mode") + +**Clickable mode**: + +A tooltip attached to a specific element on the page is displayed. +Users continue the scenario by clicking the highlighted element. + +```yaml +[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml', 16, 24) =]] +``` + +![Clickable interaction mode](img/product_tour/clickable_mode.png "Clickable interaction mode") + +**Draggable mode**: + +A tooltip attached to a specific element on the page is displayed. +Users continue the scenario by [dragging](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API#draggable_items) the highlighted element. + +```yaml +[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml', 32, 40) =]] +``` + +You can use this mode only with HTML elements that have the [`draggable` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/draggable) set to `true`. + +![Draggable interaction mode](img/product_tour/draggable_mode.png "Draggable interaction mode") + +## Block types + +Blocks are content elements that make up each step, available both for `general` and `targetable` scenarios. +Seven block types are available for building step content, and a scenario step must contain at least one. +If multiple blocks are defined for a step, they are displayed one after the other. + +### Title block + +Display bold, prominent titles: + +```yaml +[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 12, 15) =]] +``` + +### Text block + +Display regular text content: + +```yaml +[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 15, 18) =]] +``` + +### Link block + +Add external or internal links: + +```yaml +[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 18, 22) =]] +``` + +### List block + +Create bulleted lists with title: + +```yaml +[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 30, 37) =]] +``` + +The `title_translation_key` property is optional. + +### Media blocks + +To provide data to the media block, provide absolute URLs or place your image or video files in the `public` directory and provide the path relative to it. +To resolve the path relative to the site root, [prefix it with `/`](https://developer.mozilla.org/en-US/docs/Web/API/URL_API/Resolving_relative_references#root_relative). + +#### Image block + +Embed images inside the step. +You can provide alternative text by using the `alt_translation_key` property. + +Assuming a `public/img/diagram.jpg` image exists, set the configuration value to `/img/diagram.jpg`. + +```yaml +[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 22, 26) =]] +``` + +#### Video block + +Embed video content by using the [`video` HTML element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/video): + +```yaml +[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 26, 30) =]] +``` + +### Custom Twig template block + +For advanced content, use custom Twig templates that allows you to fully control the styling of the block: + +```yaml +[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 37, 40) =]] +``` + +Create the dedicated template, for example in `templates/custom_template.html.twig`. + +``` html+twig +{% trans_default_domain 'app' %} + +{{ 'custom_step_description'|trans }} +``` + +and provide the required translations in `translations/app.en.yaml`: + +``` yaml +custom_step_description: "This is a description coming from a custom template." +``` + +## Configuration examples + +### Example 1: General welcome tour + +The following example showcases all the built-in block types for a `general` scenario consisting of a single step. + +```yaml +[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml') =]] +``` + +### Example 2: Targetable feature tour with interactive steps + +The following example showcases how the three interaction modes of a `targetable` scenario can be used to build an onboarding tour for the [customizable dashboard](customize_dashboard.md): + +```yaml +[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml') =]] +``` + +To learn how to customize your scenarios even further with PHP code, see [Customize product tour](customize_product_tour.md). diff --git a/docs/administration/back_office/customize_integrated_help.md b/docs/administration/back_office/customize_integrated_help.md index 8f25cf67ea..a6ce5fbd61 100644 --- a/docs/administration/back_office/customize_integrated_help.md +++ b/docs/administration/back_office/customize_integrated_help.md @@ -9,22 +9,37 @@ month_change: false The integrated help menu is part of the Integrated help introduced as an [LTS Update](editions.md#lts-updates). By default, it provides editors and developers with convenient access to documentation, training and other resources directly from the back office. -You can extend or modify the integrated menu in two ways: +You can extend or modify the integrated menu in the following ways: - by disabling it for all users - by modifying a link to user documentation - by subscribing to the `ibexa_integrated_help.menu_configure.help_menu` event -## Disable integrated help for all users +## Disable integrated help functionalities -After you have installed the integrated help package, you may still want to disable it globally, for example, to run UI tests in a `dev` [environment](environments.md). -To do it, in `config/packages` create the `ibexa_integrated_help.yaml` file, with the following configuration: +After you have installed the integrated help package, you can disable the entire feature or specific functionalities on the system level. + +### Disable all functionalities + +To disable both the Help center and the Product tour globally, for example, to run UI tests in a `dev` [environment](environments.md), in `config/packages`, create the `ibexa_integrated_help.yaml` file with the following configuration: ``` yaml ibexa_integrated_help: enabled: false ``` +### Disable functionalities independently + +To disable only the Help center or only the Product tour functionalities, use the dedicated flags as in the example below: + +``` yaml +ibexa_integrated_help: + help_center: + enabled: false # Disable only the Help center + product_tour: + enabled: false # Disable only the Product tour +``` + ## Modify user documentation link [[= product_name =]] provides a comfortable method for replacing a link to user documentation, when you do not want to modify the rest of the integrated help menu. diff --git a/docs/administration/back_office/customize_product_tour.md b/docs/administration/back_office/customize_product_tour.md new file mode 100644 index 0000000000..5ae123bf07 --- /dev/null +++ b/docs/administration/back_office/customize_product_tour.md @@ -0,0 +1,54 @@ +--- +description: Customize product tour scenarios with custom event listeners +edition: lts-update +month_change: true +--- + +# Customize scenarios with PHP code + +You can customize the product tour scenarios with the [`RenderProductTourScenarioEvent`](integrated_help_events.md) event. +This event is dispatched before a product tour scenario is rendered. +You can use it to: + +- modify tour steps based on user permissions or roles +- add or remove steps dynamically +- change block content based on runtime conditions +- integrate custom data into tour scenarios + +With the following example, a custom onboarding scenario is built. +It starts only when the current user has a pending [notification]([[= user_doc =]]/getting_started/notifications/). + +First, define a custom product tour scenario. +It contains a placeholder step with a single block. + +``` yaml +ibexa: + system: + admin_group: + product_tour: + notifications: + type: 'targetable' + steps: + placeholder_step: + step_title_translation_key: 'This is a placeholder step' + target: '.ibexa-header-user-menu__notifications-toggler' + blocks: + - type: text + params: + text_translation_key: 'This is a placeholder block, modified during event subscriber execution' +``` + +Then, create a subscriber that modifies the scenario. + +```php hl_lines="32-34 36-38 40-42 44-55" +[[= include_file('code_samples/back_office/product_tour/src/EventSubscriber/NotificationScenarioSubscriber.php') =]] +``` + +The subscriber executes the following actions: + +- makes sure the correct scenario is being processed +- removes all the existing scenario steps +- verifies that the current user has a pending notification +- adds a custom clickable step to highlight the unread notification + +![Scenario built with PHP triggered on unread notification](img/product_tour/custom_scenario.png "Scenario built with PHP triggered on unread notification") diff --git a/docs/administration/back_office/img/product_tour/clickable_mode.png b/docs/administration/back_office/img/product_tour/clickable_mode.png new file mode 100644 index 0000000000..380fb794e5 Binary files /dev/null and b/docs/administration/back_office/img/product_tour/clickable_mode.png differ diff --git a/docs/administration/back_office/img/product_tour/custom_scenario.png b/docs/administration/back_office/img/product_tour/custom_scenario.png new file mode 100644 index 0000000000..770d73dc6a Binary files /dev/null and b/docs/administration/back_office/img/product_tour/custom_scenario.png differ diff --git a/docs/administration/back_office/img/product_tour/draggable_mode.png b/docs/administration/back_office/img/product_tour/draggable_mode.png new file mode 100644 index 0000000000..b860d48fed Binary files /dev/null and b/docs/administration/back_office/img/product_tour/draggable_mode.png differ diff --git a/docs/administration/back_office/img/product_tour/general_scenario.png b/docs/administration/back_office/img/product_tour/general_scenario.png new file mode 100644 index 0000000000..60d4bff09e Binary files /dev/null and b/docs/administration/back_office/img/product_tour/general_scenario.png differ diff --git a/docs/administration/back_office/img/product_tour/standard_mode.png b/docs/administration/back_office/img/product_tour/standard_mode.png new file mode 100644 index 0000000000..e5a970f2f0 Binary files /dev/null and b/docs/administration/back_office/img/product_tour/standard_mode.png differ diff --git a/docs/administration/back_office/img/product_tour/targetable_scenario.png b/docs/administration/back_office/img/product_tour/targetable_scenario.png new file mode 100644 index 0000000000..3f9b726364 Binary files /dev/null and b/docs/administration/back_office/img/product_tour/targetable_scenario.png differ diff --git a/docs/administration/back_office/integrated_help.md b/docs/administration/back_office/integrated_help.md index 54f5e4f720..639f60ecd5 100644 --- a/docs/administration/back_office/integrated_help.md +++ b/docs/administration/back_office/integrated_help.md @@ -1,31 +1,35 @@ --- description: Integrated help provides quick access to documentation, training, and support resources. edition: lts-update -month_change: false +month_change: true --- # Integrated help -Integrated help is an [LTS Update](editions.md#lts-updates) that brings documentation, training resources and product roadmap-related information into the back office. +Integrated help is an [LTS Update](editions.md#lts-updates) that brings documentation, training resources, and product roadmap-related information into the back office, together with user onboarding capabilities. With this feature installed, users can click the ![Help icon](about-info.png){.inline-image} icon to access relevant content straight from the UI. ![Integrated help menu](5_0_integrated_help_menu.png) Integrated help is contextual, therefore, apart from user documentation, release notes, and partner guidelines, which are available to editors and store managers, developers can access API references, the GraphQL console, or the support portal. +## Product tours + +Product tours are interactive guided walkthroughs that help back office users discover [[= product_name =]] features, available starting with [[= product_name =]] v4.6.29. +They provide step-by-step guidance directly within the application interface, accelerating user adoption and reducing training time. + +Developers can create custom onboarding journeys tailored to specific client implementations, user roles, or business processes. + +For more information, see [Product tour](product_tour.md). + ## Install package -Integrated help is optional. +The Integrated help LTS Update is optional. To enable it, run the following command: ```bash composer require ibexa/integrated-help ``` -After installation, you must [enable the help center in user settings]([[= user_doc =]]/getting_started/discover_ui#enable-help-center) to use the feature. - -## Customize help menu - -You can extend or alter the integrated help menu by quickly changing the link to user documentation, or adding or removing menu items or even entire menu sections. - -For more information, see [Customize integrated help](customize_integrated_help.md). +After installation, the help center is enabled by default for all back office users. +If needed, they can [disable it in user settings]([[= user_doc =]]/getting_started/discover_ui#disable-help-center). diff --git a/docs/administration/back_office/product_tour.md b/docs/administration/back_office/product_tour.md new file mode 100644 index 0000000000..4d01c3137b --- /dev/null +++ b/docs/administration/back_office/product_tour.md @@ -0,0 +1,80 @@ +--- +description: Product tours provide interactive guided walkthroughs to help users learn Ibexa DXP features. +edition: lts-update +month_change: true +--- + +# Product tour + +Product tour is an in-app onboarding tool that helps back office contributors discover [[= product_name =]] features through interactive, step-by-step guided walkthroughs. +Unlike static documentation, product tours provide real-time, contextual guidance directly within the application interface. + +With product tours, you can create customized onboarding journeys tailored to specific client implementations, user roles, or business processes. +This accelerates user adoption, reduces training time, and helps users confidently navigate the platform. + +Product tour functionality is available from versions 4.6.29 and 5.0.7 as part of the Integrated help package. +To use product tours, you must first [install the Integrated help LTS Update](integrated_help.md#install-package). + +
+ +## Key concepts + +Product tour consists of three main elements: + +- **Scenario** - a complete onboarding scenario containing multiple steps that guide users through a specific feature or workflow +- **Step** - an individual instruction or explanation within a scenario, containing blocks, displayed as an overlay or tooltip +- **Block** - a content element within a step, such as text, images, videos, or links that provide information to the user + +## Scenario types + +[[= product_name =]] supports two types of scenarios, each designed for different use cases: + +### General scenarios + +General tours display information in centered modals without targeting specific UI elements. +These tours provide an overview of features or concepts and do not require interaction with particular interface elements. + +General tours are ideal for: + +- Introducing new users to the platform +- Explaining high-level concepts or feature overviews +- Welcoming users with customizable background images and branding + +![General scenario type](img/product_tour/general_scenario.png "General scenario type") + +### Targetable scenarios + +Targetable scenarios highlight specific UI elements on the page and guide users through interactive workflows. +Each step targets a particular element by using a CSS selector, and can draw attention to buttons, navigation elements, or other interface components. + +Targetable scenarios are ideal for: + +- Demonstrating specific features or workflows +- Guiding users through multi-step processes +- Teaching users how to interact with particular UI elements + +The steps building the scenario support three interaction modes: + +- **Standard** - Users navigate between steps by clicking **Previous** and **Next** buttons +- **Clickable** - Users must click the highlighted element to proceed to the next step +- **Draggable** - Users must drag and drop an element to continue the scenario + +![Targetable scenario type](img/product_tour/targetable_scenario.png "Targetable scenario type") + +## Scenario lifecycle + +Depending on scenario configuration, they automatically appear to users when they first log in or visit a specific page. +Each scenario appears only once for each user. + +Users can complete a tour with one of the following actions: + +- by finishing all steps +- by skipping it with the **Skip** button in general tours and **Exit tour** in targetable tours +- by skipping it with the **Escape** key + +For **Standard** scenario steps, users can move freely between the previous and next steps. +For **Clickable** and **Draggable** steps, users can't go back to the previous step without restarting the scenario and starting from the beginning. + +At any time, users can manually restart completed tours from their [user settings]([[= user_doc =]]/getting_started/get_started/#user-settings). + +To start building your custom onboarding scenarios, see [Configure product tour](configure_product_tour.md). diff --git a/docs/ai_actions/ai_actions_guide.md b/docs/ai_actions/ai_actions_guide.md index 8fe4a6377b..614b0a85f5 100644 --- a/docs/ai_actions/ai_actions_guide.md +++ b/docs/ai_actions/ai_actions_guide.md @@ -12,7 +12,7 @@ Wherever you look, artificial intelligence becomes more and more important by en AI Actions is an extensible solution for integrating features provided by AI services into your workflows, all managed through a user-friendly interface. Out-of-the-box, AI Actions solution includes two essential components: a framework package and an OpenAI connector package. -The Anthropic connector is also available - as an [LTS update](editions.md#lts-updates). +The Anthropic and Gemini connectors are also available - as [LTS updates](editions.md#lts-updates). AI Actions can integrate with [[[= product_name_connect =]]]([[= connect_doc =]]/general/ibexa_connect/), to give you an opportunity to build complex data transformation workflows without having to rely on custom code. From the developer's perspective, the integration removes the burden of maintaining third-party AI handlers, and accelerates the deployment of AI-based solutions. @@ -163,12 +163,17 @@ With some customization, administrators could use the API to run a batch process ### Suggesting taxonomy entries -Content editors and product managers can use [taxonomy suggestions](taxonomy.md#taxonomy-suggestions) when assigning tags or product categorie to content items and products. +Content editors and product managers can use [taxonomy suggestions](taxonomy.md#taxonomy-suggestions) when assigning tags or product categories to content items and products. Instead of manually browsing through extensive taxonomy trees, editors can request suggestions based on the content's text fields, such as name and description. +!!! note "Alternative suggestion provider" + + By default, embeddings used by the taxonomy suggestions feature are generated with OpenAI. + If you install and configure the [Google Gemini connector](configure_ai_actions.md#install-google-gemini-connector), you can modify the [taxonomy suggestions settings](taxonomy.md#change-embeddings-provider-to-google-gemini) and use Google Gemini as an alternative embeddings provider. + ### Performing advanced image to text analysis -With some additional customization, store managers could benefit from automating part of product management by integrating their [[= product_name =]] with Google Cloud Vision and [PIM](pim_guide.md) by using [[= product_name_connect =]]. +With some additional customization, store managers could benefit from automating part of product management by integrating their [[= product_name =]] with Google Cloud Vision and the [product catalog](product_catalog_guide.md) by using [[= product_name_connect =]]. Instead of manually selecting and linking images stored in a [DAM](add_image_asset_from_dam.md) solution to their products, they could use of a no-code workflow where an AI service, for example, Google Cloud Vision, extracts text and attributes from product images, which are then matched with existing items in a product catalog. This would enable automatic product identification, tagging, and catalog updates, resulting in less manual work and more efficient product management. diff --git a/docs/ai_actions/configure_ai_actions.md b/docs/ai_actions/configure_ai_actions.md index 42bf67b29d..e7a6a84ffd 100644 --- a/docs/ai_actions/configure_ai_actions.md +++ b/docs/ai_actions/configure_ai_actions.md @@ -8,13 +8,17 @@ month_change: false AI Actions are available in [[= product_name =]] regardless of its edition. To use this feature you must first configure the built-in service connectors or build your own ones. -!!! note "Next steps" +Once the framework is configured, before you can start using AI Actions, you can configure access to [[= product_name_base =]]-made service connectors by following the instructions below, or [create your own](extend_ai_actions.md#create-custom-action-handler). - Once the framework is configured, before you can start using AI Actions, you can configure access to [[= product_name_base =]]-made service connectors by following the instructions below, or [create your own](extend_ai_actions.md#create-custom-action-handler). +Only then you can restart you application and start [working with the AI Actions feature]([[= user_doc =]]/ai_actions/work_with_ai_actions/). - Only then you can restart you application and start [working with the AI Actions feature]([[= user_doc =]]/ai_actions/work_with_ai_actions/). +!!! note "Taxonomy suggestions" + + The default OpenAI or the optional Google Gemini connectors can used by the [Taxonomy suggestions](taxonomy.md#taxonomy-suggestions) feature to generate embeddings for suggesting tags and product categories. + After you configure the OpenAI connector, or set up the optional Google Gemini connector and [modify the default taxonomy suggestions settings](taxonomy.md#change-embeddings-provider-to-google-gemini), you can [create AI actions that use the Text to Taxonomy action type]([[= user_doc =]]/ai_actions/work_with_ai_actions/#create-ai-actions-that-control-taxonomy-suggestions). + You can also create [your own embedding provider](taxonomy.md#replace-the-embedding-provider). -## Configure access to OpenAI (optional) +## Configure access to OpenAI To use the built-in connector with the OpenAI service, you need to create an OpenAI account, [get an API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-openai-api-key), and make sure that you [set up a billing method](https://help.openai.com/en/articles/9038407-how-can-i-set-up-billing-for-my-account). @@ -32,12 +36,6 @@ The AI actions come with sample AI action configurations to quickly get you star Based on these examples, which reflect the most common use cases, you can learn to configure your own AI actions with greater ease. -!!! note "Taxonomy suggestions" - - OpenAI connector is also used by the [Taxonomy suggestions](taxonomy.md#taxonomy-suggestions) feature to generate embeddings for suggesting tags and product categories. - After you configure the connector, you can [create AI actions that use the Text to Taxonomy action type]([[= user_doc =]]/ai_actions/work_with_ai_actions/#create-ai-actions-that-control-taxonomy-suggestions). - You can also create [your own embedding provider](taxonomy.md#replace-the-embedding-provider). - ## Install Anthropic connector [[% include 'snippets/lts-update_badge.md' %]] Run the following command to install the package: @@ -83,6 +81,99 @@ ibexa_connector_anthropic: ``` You can now use the Anthropic connector in your project. +## Install Google Gemini connector [[% include 'snippets/lts-update_badge.md' %]] + +Run the following command to install the package: + +``` bash +composer require ibexa/connector-gemini +``` + +This command adds the feature code, including basic handlers that let you refine text or generate alternative text for images. + +### Get API key + +To use the connector with the Gemini services, you need to create an account, set up billing, enable Gemini API and get an API key. + +#### Create the Google Cloud project + +1. Sign in to the [Google Cloud Console](https://console.cloud.google.com/). +1. In the top bar, click **Default Gemini Project** to open a project picker. +1. Click **New project** and provide project details: + 1. Add project name, for example, "My project". + 1. Modify the automatically generated **Project ID** if necessary. + 1. Select location: choose your organization. +1. Click **Create**. + +#### Configure billing + +1. Navigate to the Google Cloud Console's **Billing** page. +1. If you do not have one, click **Add billing account** and add a payment method. +1. In **Your projects** tab, locate your project, and in its line, from the **Actions** menu, select **Change billing**. +1. Select your active billing account, and click **Set account**. + +#### Enable the Gemini API + +1. Navigate to the Google Cloud Console's **APIs & Services** page. +1. From the left-hand menu, select **Library** and search for the Generative Language API. +1. In the API's details page, click **Enable**. + +#### Generate the API key + +1. Go to [Google AI Studio](https://aistudio.google.com/app/api-keys)'s **API keys** page, and click **Create API key**. +1. Provide a name for the API key, select "My project" from a list of projects and click **Create key**. +1. Back in the **API keys** list, in your project's line, copy the API key. + +### Set API key in configuration + +Then, in the root folder of your project, modify the `.env` file: add an `GEMINI_API_KEY` variable and populate its value with the API key that you got from the AI service. + +```bash +###> ibexa/connector-gemini ### +GEMINI_API_KEY= +###< ibexa/connector-gemini ### +``` + +!!! note "Different API keys for different SiteAccesses" + + If there are multiple SiteAccesses in your installation, you can set different API keys for each SiteAccess. + To do it, set the keys under the `ibexa.system.` [configuration key](configuration.md#configuration-files), like so: + + ```yaml + ibexa: + system: + default: + connector_gemini: + gemini: + api_key: '%env(GEMINI_API_KEY)%' + base_url: 'https://generativelanguage.googleapis.com/v1beta/' # Google Gemini's API endpoint + ``` + +### Configure default models + +By default, when reaching out for responses, the Gemini connector uses the Gemini Pro [model](https://ai.google.dev/gemini-api/docs/models) for text refinement and Gemini Flash model for alternative text generation. +Users can override this setting at runtime when they [edit or create an AI action]([[= user_doc =]]/ai_actions/work_with_ai_actions/#edit-existing-ai-actions). +You can also change the default values globally. +To do it, in `config/packages` folder, create a YAML file similar to this example: + +```yaml +[[= include_file('code_samples/ai_actions/config/packages/ibexa_connector_gemini.yaml') =]] +``` + +When setting up models, make sure that you follow these rules: + +- `default_model` must reference a configured model +- `default_max_tokens` must not exceed the model’s limit +- If you use the same model for different action types, settings must be consistent + +!!! note "Google Gemini and taxonomy suggestions" + + To use Google Gemini for generating taxonomy suggestions, ensure that you [change the embeddings provider and model setting accordingly](taxonomy.md#change-embeddings-provider-to-google-gemini). + +You can now use the Gemini connector in your project. + +For more information, see [Extend Gemini connector](extend_ai_actions.md#extend-google-gemini-connector). + ## Configure access to [[= product_name_connect =]] First, get the credentials by contacting [Ibexa Support](https://support.ibexa.co). diff --git a/docs/ai_actions/extend_ai_actions.md b/docs/ai_actions/extend_ai_actions.md index 4bbe4f198e..a356b0fc47 100644 --- a/docs/ai_actions/extend_ai_actions.md +++ b/docs/ai_actions/extend_ai_actions.md @@ -374,3 +374,64 @@ See [configuring assets from main project files](importing_assets_from_bundle.md Your custom Action Type is now fully integrated into the back office UI and can be used by the Editors. ![Transcribe Audio Action Type integrated into the back office](img/transcribe_audio.png "Transcribe Audio Action Type integrated into the back office") + +## Extend Google Gemini connector [[% include 'snippets/lts-update_badge.md' %]] + +The Gemini connector provides several extension points that allow you to customize available models, behavior, validation, and response handling, while remaining compatible with the AI Actions framework. + +The connector builds Gemini requests in an options provider and formats responses through a response formatter. +Both components can be replaced or extended to customize how requests are constructed and how responses are normalized. + +### Add or customize models + +You can register additional Gemini models or customize existing ones by extending the connector’s model [configuration](configure_ai_actions.md#configure-default-models). + +Extend the models map by defining: + +- a human-readable label +- a `max_tokens` limit + +Optionally, you can set the default model that would be used for the action type that you're modifying, the default allowed tokens limit and the default temperature. +Default values must stay within the limits supported by the [Gemini API](https://ai.google.dev/gemini-api/docs/models). + +### Add a custom Action Handler + +To introduce a new Gemini-based AI action: + +1. Create a handler that extends `Ibexa\Contracts\ConnectorAi\Action\AbstractActionHandler`. +1. Register the handler in `services/ai_action_handlers.yaml`. +1. Provide supporting components as needed: + - a prompt factory + - a form type for configuration + - validators for action options + +This follows the same extension mechanism as other [custom AI actions](#create-custom-action-handler). + +### Add custom response formatting + +To change how Gemini responses are post-processed or normalized: + +1. Implement the `Ibexa\ConnectorGemini\Response\GeminiResponseFormatterInterface` interface. +1. Alias your implementation in the service container to override the default formatter. + +### Add custom validation + +Add extra validation rules for Gemini action configuration options by tagging custom validators: + +- For `text-to-text` actions: + + ``` yaml + ibexa.connector_ai.action_configuration.options.validator.gemini_text_to_text + ``` + +- For `image-to-text` actions: + + ``` yaml + ibexa.connector_ai.action_configuration.options.validator.gemini_image_to_text + ``` + +### Replace the Gemini client implementation + +To get full control over the low-level API communication without modifying the connector itself, you can swap the Gemini client implementation entirely with your own: + +- Use dependency injection to bind your own implementation to `Ibexa\ConnectorGemini\Client\GeminiClientInterface`. diff --git a/docs/api/event_reference/event_reference.md b/docs/api/event_reference/event_reference.md index aa3b1fdb1a..389db92df3 100644 --- a/docs/api/event_reference/event_reference.md +++ b/docs/api/event_reference/event_reference.md @@ -15,3 +15,30 @@ For example, copying a content item is connected with two events: `BeforeCopyCon ``` php [[= include_file('code_samples/api/public_php_api/src/EventSubscriber/MyEventSubcriber.php') =]] ``` + +[[= cards([ + "api/event_reference/ai_action_events", + "api/event_reference/cart_events", + "api/event_reference/product_catalog_events", + "api/event_reference/collaboration_events", + "api/event_reference/content_events", + "api/event_reference/content_type_events", + "api/event_reference/discounts_events", + "api/event_reference/integrated_help_events", + "api/event_reference/language_events", + "api/event_reference/location_events", + "api/event_reference/object_state_events", + "api/event_reference/order_management_events", + "api/event_reference/other_events", + "api/event_reference/page_events", + "api/event_reference/payment_events", + "api/event_reference/role_events", + "api/event_reference/section_events", + "api/event_reference/segmentation_events", + "api/event_reference/site_events", + "api/event_reference/taxonomy_events", + "api/event_reference/trash_events", + "api/event_reference/twig_component_events", + "api/event_reference/url_events", + "api/event_reference/user_events", +], columns=3) =]] diff --git a/docs/api/event_reference/integrated_help_events.md b/docs/api/event_reference/integrated_help_events.md new file mode 100644 index 0000000000..94d560967e --- /dev/null +++ b/docs/api/event_reference/integrated_help_events.md @@ -0,0 +1,18 @@ +--- +description: Events that are triggered when working with integrated help features like product tours. +edition: lts-update +page_type: reference +month_change: true +--- + +# Integrated help events + +## Product tour events + +The following event is dispatched when rendering a [product tour scenario](product_tour.md). + +| Event | Dispatched by | +|---|---| +|[`RenderProductTourScenarioEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-IntegratedHelp-Event-RenderProductTourScenarioEvent.html)|`Ibexa\IntegratedHelp\Renderer\ProductTourRenderer::render()`| + +To learn how you can use this event to customize your product tour scenarios, see [Customize product tour](customize_product_tour.md). diff --git a/docs/api/event_reference/catalog_events.md b/docs/api/event_reference/product_catalog_events.md similarity index 90% rename from docs/api/event_reference/catalog_events.md rename to docs/api/event_reference/product_catalog_events.md index dbd23a8112..245e78c0fb 100644 --- a/docs/api/event_reference/catalog_events.md +++ b/docs/api/event_reference/product_catalog_events.md @@ -1,9 +1,10 @@ --- -description: Events that are triggered when working with products, prices and currencies. +description: Events that are triggered when working with products, prices, currencies, and attribute rendering. page_type: reference +month_change: true --- -# Catalog events +# Product catalog events ## Products @@ -84,3 +85,13 @@ page_type: reference |`CreateCatalogEvent`|`CatalogService::createCatalog`|`CatalogCreateStruct $createStruct`
`CatalogInterface $catalog`| |`DeleteCatalogEvent`|`CatalogService::deleteCatalog`|`CatalogInterface $catalog`| |`UpdateCatalogEvent`|`CatalogService::updateCatalog`|`CatalogUpdateStruct $updateStruct`| + +## Attribute rendering + +The following event is dispatched when the [`ibexa_format_product_attribute`](product_twig_functions.md#ibexa_format_product_attribute) Twig filter renders an attribute value. + +| Event | Dispatched by | Properties | +|---|---|---| +|`ProductAttributeRenderEvent`|`ibexa_format_product_attribute` Twig filter|`list $templates`
[`AttributeInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-AttributeInterface.html)
`array $parameters`| + +For a usage example, see [Customize product attribute templates](customize_product_attribute_templates.md). diff --git a/docs/content_management/content_model.md b/docs/content_management/content_model.md index 0a3e436202..9dc1c6029b 100644 --- a/docs/content_management/content_model.md +++ b/docs/content_management/content_model.md @@ -139,6 +139,6 @@ A new version is also created when a new [language](languages.md) is added to th ## Products -Products are a special type of content that holds products you can manage in the built-in PIM system. +Products are a special type of content that holds products you can manage with the product catalog capabilities. -For more information, see [PIM](pim.md). +For more information, see [Product catalog](../product_catalog/product_catalog.md). diff --git a/docs/content_management/data_migration/importing_data.md b/docs/content_management/data_migration/importing_data.md index 4af7563dc6..9dbecc1e07 100644 --- a/docs/content_management/data_migration/importing_data.md +++ b/docs/content_management/data_migration/importing_data.md @@ -74,6 +74,14 @@ The following data migration step modes are available: | `user` | ✔ | ✔ | | | | | `user_group` | ✔ | ✔ | ✔ | | | +Additionally, the following special migration types are available: + +| `type` | `execute` | +|------------------------|:---------:| +| `repeatable` | ✔ | +| `sql` | ✔ | +| `try_catch` | ✔ | + ### Repeatable steps You can run a set of one or more similar migration steps multiple times by using the special `repeatable` migration type. @@ -122,6 +130,58 @@ Then, you can use `faker()` in expressions, for example: This step generates field values with fake personal names. +### SQL migrations + +You can execute raw SQL queries directly in migrations by using the `sql` migration type. +Use it for custom database operations that don't fit into standard entity migrations, such as creating custom tables or performing bulk updates. + +Each query requires a `driver` property that specifies which database system the query is for. +The migration system automatically filters queries and executes only those matching your current database driver. + +```yaml +[[= include_file('code_samples/data_migration/examples/sql_execute.yaml') =]] +``` + +The supported database drivers are: + +- `mysql` - MySQL/MariaDB +- `postgresql` - PostgreSQL +- `sqlite` - SQLite + +You can define queries for multiple database drivers in a single migration step. +The system executes only the queries that match your configured database platform. +If no matching queries are found, the migration throws an error. + +!!! caution + + SQL migrations bypass the content model abstraction layer and directly modify the database. + Use them with caution and ensure your queries are compatible with your target database system. + +### Error handling with try-catch + +You can wrap one or more migration steps with a `try_catch` step to handle exceptions gracefully. + +Use it for migration steps that may fail under specific conditions but should not halt the entire migration process. + +For example, you can ensure a language creation migration step succeeds even if the language already exists. +If the migration step fails for this reason, the exception is suppressed, allowing the remaining migrations to proceed without interruption. + +A `try_catch` migration requires the `steps` property and accepts optional `allowed_exceptions` and `stop_after_first_exception` settings. + +Default values are: + +- `allowed_exceptions`: empty list +- `stop_after_first_exception`: `true` + +```yaml +[[= include_file('code_samples/data_migration/examples/try_catch_step.yaml') =]] +``` + +When an exception is thrown within a `try_catch` step, it's compared against the list of `allowed_exceptions`. +If the exception matches, it's caught and the migration step continues or stops depending on the `stop_after_first_exception` configuration setting. +The migration step is marked as successful and the migration process continues. +Non-matching exceptions throw immediately, halting the migration process and returning an error. + ### Expression syntax You can use [Symfony expression syntax]([[= symfony_doc =]]/reference/formats/expression_language.html) in data migrations, like in [repeatable steps](#repeatable-steps), where you can use it to generate varied content in migration steps. diff --git a/docs/content_management/field_types/field_type_reference/productspecificationfield.md b/docs/content_management/field_types/field_type_reference/productspecificationfield.md index 4a988312bd..ddea872a1b 100644 --- a/docs/content_management/field_types/field_type_reference/productspecificationfield.md +++ b/docs/content_management/field_types/field_type_reference/productspecificationfield.md @@ -6,7 +6,7 @@ month_change: false # Product specification field type This field represents and handles [product attributes](products.md#product-attributes) and [VAT](prices.md#vat). -Consider it as internal to the [PIM](pim.md). +Consider it as internal to the [product catalog](product_catalog.md). | Name | Internal name | Expected input | |------------------------|-------------------------------|----------------| diff --git a/docs/content_management/rich_text/online_editor_guide.md b/docs/content_management/rich_text/online_editor_guide.md index bb047d8caf..8f9edece72 100644 --- a/docs/content_management/rich_text/online_editor_guide.md +++ b/docs/content_management/rich_text/online_editor_guide.md @@ -77,7 +77,7 @@ For more information, see [Extend Online Editor](extend_online_editor.md#custom- ### Plugins -Because Online Editor is based on CKEditor 5, you can use CKEditor's capabilities to [create plugins](extend_online_editor.md#add-ckeditor-plugins) for the editor. +Online Editor is based on CKEditor 5, and you can use CKEditor's capabilities to [create plugins](extend_online_editor.md#add-ckeditor-plugins) for the editor. ## Benefits @@ -112,6 +112,15 @@ Then, you can add a link attribute to provide target for the button, and a style Refer to [Extend Online Editor](extend_online_editor.md#link-tag) for a similar use case. +### Product marketing campaigns + +With the Online Editor, editors can embed products from the product catalog directly into RichText fields. +Products can be embedded as block-level or inline elements. + +You can use it to weave marketing content around your product data, showcasing your product capabilities and bringing it closer to your customers. + +See [Embed products in content](products.md#embed-products-in-content) for details. + ### Embed external resources Custom tags allow embedding content from external resources inside RichText fields. diff --git a/docs/content_management/taxonomy/taxonomy.md b/docs/content_management/taxonomy/taxonomy.md index 35724fbd4d..afee28e616 100644 --- a/docs/content_management/taxonomy/taxonomy.md +++ b/docs/content_management/taxonomy/taxonomy.md @@ -100,7 +100,7 @@ ibexa: ## Remove orphaned content items -In some rare case, especially in [[= product_name =]] v4.2 and older, when deleting parent of huge subtrees, some Taxonomy entries aren't properly deleted, leaving content items that point to a non-existing parent. +In some rare case, especially in [[= product_name =]] v4.2 and older, when deleting parent of huge subtrees, some taxonomy entries aren't properly deleted, leaving content items that point to a non-existing parent. The command `ibexa:taxonomy:remove-orphaned-content` deletes those orphaned content item. It works on a taxonomy passed as an argument, and has two options that act as a protective measure against deleting data by mistake: @@ -132,7 +132,7 @@ When it happens, the `Ibexa\Taxonomy\ActionHandler\TextToTaxonomyActionHandler` !!! note "Field selection" - You select the actual text fields, whose values are used as source for the embedding generation, when you create an [AI action](https://doc.ibexa.co/projects/userguide/en/latest/ai_actions/work_with_ai_actions/#create-ai-actions-that-use-ibexa-connect) that uses the `openai-text-to-taxonomy-entries` handler. + You select the actual text fields, whose values are used as source for the embedding generation, when you create an [AI action](https://doc.ibexa.co/projects/userguide/en/latest/ai_actions/work_with_ai_actions/#create-ai-actions-that-use-ibexa-connect) that uses the `text-to-taxonomy` handler. The search engine then compares the generated embedding with the taxonomy path embeddings stored in its index. By default, it selects the three best-matching taxonomy paths and presents them to the editor as suggestions. @@ -145,23 +145,27 @@ However, before you can enable it, make sure the following prerequisites have be - [Search engine](search_engines.md): Taxonomy suggestions require a search engine that supports vector search. The feature has been tested to work with Elasticsearch or Solr 9.8.1+. -- [AI Actions](ai_actions.md): To be able to process embeddings, Taxonomy suggestions require that you have the [AI Actions configured](configure_ai_actions.md#configure-access-to-openai-optional) to support the OpenAI service. +- [AI Actions](ai_actions.md): To be able to process embeddings, Taxonomy suggestions require that you have the AI Actions configured to support the default [OpenAI](configure_ai_actions.md#configure-access-to-openai) or the optional [Google Gemini](configure_ai_actions.md#install-google-gemini-connector) service. + +!!! note "Alternative embeddings provider" + + To use Google Gemini as an alternative embeddings provider, you must also modify the default [taxonomy suggestions settings](taxonomy.md#change-embeddings-provider-to-google-gemini). #### Enable taxonomy embedding indexing -Enable embedding indexing for taxonomy branches by changing the default setting from `false` to `true`: +Enable embedding indexing for taxonomy branches by changing the default setting from `false` to `true`. +Toggle this setting at any time to enable or disable indexing of taxonomy embeddings. -```yaml +```yaml hl_lines="6" ibexa: - system: - default: - taxonomy: - search: - index_embeddings: true + system: + default: + taxonomy: + search: + index_embeddings: true + default_embedding_model: 'text-embedding-ada-002' ``` -Toggle this setting at any time to enable or disable indexing of taxonomy embeddings. - If you are happy with the default settings, clear the cache and reindex the search engine. ```bash @@ -220,9 +224,12 @@ Like in the case of the number of suggestions, you can override this setting per When selecting the input data for embedding creation, it's recommended to include only the essential information and limit the number of tokens sent. Otherwise, the embedding models can generate values that don't correspond closely to the actual meaning of the input. -### Change the embedding generation model +### Change embedding generation models or embedding provider -By default, the system comes with a set of OpenAI models listed in its configuration, and a setting that allows you to choose the default model that should be used with the Taxonomy suggestions feature. +By default, the system comes with a set of OpenAI models that can be used for embedding generation. +The following example shows these models listed in system configuration, together with a setting that controls what model is used when the editor requests taxonomy suggestions for an item. + +Also, here is where you can change the name of the model used by the provider, the embedding's dimensions, and other settings. ```yaml hl_lines="20" ibexa: @@ -230,24 +237,61 @@ ibexa: default: embedding_models: text-embedding-3-small: - name: text-embedding-3-small + name: 'text-embedding-3-small' dimensions: 1536 - field_suffix: 3small - embedding_provider: ibexa_openai + field_suffix: '3small' + embedding_provider: 'ibexa_openai' text-embedding-3-large: - name: text-embedding-3-large + name: 'text-embedding-3-large' dimensions: 3072 - field_suffix: 3large - embedding_provider: ibexa_openai + field_suffix: '3large' + embedding_provider: 'ibexa_openai' text-embedding-ada-002: - name: text-embedding-ada-002 + name: 'text-embedding-ada-002' dimensions: 1536 - field_suffix: ada002 - embedding_provider: ibexa_openai - default_embedding_model: text-embedding-ada-002 + field_suffix: 'ada002' + embedding_provider: 'ibexa_openai' + default_embedding_model: 'text-embedding-ada-002' ``` -Also, here is where you can change the name of the model used by the provider, the embedding's dimensions, and other settings. +!!! warning "Change both embedding generation models" + + When you change the default suggestions generation model, ensure that you update the `ibexa.system.default.taxonomy.search.default_embedding_model` setting that is used for taxonomy indexing purposes. + Otherwise the taxonomy suggestions feature fails to find matching entries. + +#### Change embeddings provider to Google Gemini [[% include 'snippets/lts-update_badge.md' %]] + +Once you have installed and configured the [Google Gemini connector](configure_ai_actions.md#install-google-gemini-connector), you can modify the default configuration to use the `ibexa_gemini` embedding provider and one of the [supported models](https://ai.google.dev/gemini-api/docs/embeddings): + +```yaml hl_lines="15 22" +ibexa: + system: + default: + embedding_models: + gemini_embedding_001_1536: + name: 'gemini-embedding-001' + dimensions: 1536 + field_suffix: 'gemini_embedding_001_1536_dv' + embedding_provider: 'ibexa_gemini' + gemini_embedding_001_3072: + name: 'gemini-embedding-001' + dimensions: 3072 + field_suffix: 'gemini_embedding_001_3072_dv' + embedding_provider: 'ibexa_gemini' + default_embedding_model: 'gemini_embedding_001_1536' + +# ... + + taxonomy: + search: + index_embeddings: true + default_embedding_model: 'gemini_embedding_001_1536' +``` + +After you make the change: + +- Update the [Solr schema](field_type_search.md#configuring-solr) or [Elasticsearch mappings](configure_elasticsearch.md#fine-tune-the-search-results) by adding dynamic field definitions. Ensure that they match the dimensions (for example, 1536 or 3072) and suffixes that you defined above +- Clear the cache and reindex the search engine ### Extending Taxonomy suggestions diff --git a/docs/content_management/taxonomy/taxonomy_api.md b/docs/content_management/taxonomy/taxonomy_api.md index 16cb291ff8..613abecde4 100644 --- a/docs/content_management/taxonomy/taxonomy_api.md +++ b/docs/content_management/taxonomy/taxonomy_api.md @@ -71,3 +71,15 @@ and a `position` parameter, which is either `TaxonomyServiceInterface::MOVE_POSI Taxonomy entry management functions triggers events you can listen to. For more information, see [Taxonomy events](taxonomy_events.md). + +## Search + +You can search for content based on its taxonomy entry assignments by using the standard [`SearchService`](search_api.md) with taxonomy-specific Search Criteria: + +| Criterion | Description | +|---|---| +| [TaxonomyEntryId](taxonomy_entry_id.md) | Find content assigned to a specific taxonomy entry | +| [TaxonomyNoEntries](taxonomy_no_entries.md) | Find content that has no entries assigned from a given taxonomy | +| [TaxonomySubtree](taxonomy_subtree.md) | Find content assigned to a taxonomy entry or any of its descendants | + +You can also use the [TaxonomyEntryId Aggregation](taxonomyentryid_aggregation.md) to count content items per taxonomy entry. diff --git a/docs/discounts/discounts_guide.md b/docs/discounts/discounts_guide.md index b33e73a428..0b9a7d26a9 100644 --- a/docs/discounts/discounts_guide.md +++ b/docs/discounts/discounts_guide.md @@ -71,7 +71,7 @@ After choosing where the discount applies (catalog or cart), you can choose the - **Fixed amount** - where a specified amount of money, for example, 5 Euro, is deducted from the base price of the product - **Percentage** - where a specified percentage, for example, 10%, is used to calculate the deducted amount from the product's base price -Discounts are translatable and you can limit them to specific [regions](pim_guide.md#regions) or a single currency. +Discounts are translatable and you can limit them to specific [regions](product_catalog_guide.md#regions) or a single currency. They can be permanent or be active only in a specified time frame. Regardless of the specified dates, you can disable a discount at any time to prevent customers from using it. @@ -86,10 +86,10 @@ With discounts, you can target your entire customer base or only a subset of it #### Product selection -All products, including [product variants](pim_guide.md#product-variants), can be selected when creating a discount. +All products, including [product variants](product_catalog_guide.md#product-variants), can be selected when creating a discount. You can also limit this choice to a subset of products: -- belonging to selected [product categories](pim_guide.md#product-categories) +- belonging to selected [product categories](product_catalog_guide.md#product-categories) - hand-picked manually for special cases #### Conditions diff --git a/docs/discounts/extend_discounts.md b/docs/discounts/extend_discounts.md index e81d4f22e4..604aa069c6 100644 --- a/docs/discounts/extend_discounts.md +++ b/docs/discounts/extend_discounts.md @@ -32,7 +32,7 @@ You can also [create your own](#custom-expressions). | Type | Name | Value | Available for | | --- | --- | --- | --- | | Function | `get_current_region()` | [Region object](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-RegionInterface.html) of the current siteaccess.| Conditions, rules | -| Function | `is_in_category()` | `true/false`, depending if a product belongs to given [product categories](pim_guide.md#product-categories).| Conditions, rules | +| Function | `is_in_category()` | `true/false`, depending if a product belongs to given [product categories](product_catalog_guide.md#product-categories).| Conditions, rules | | Function | `is_user_in_customer_group()` | `true/false`, depending if an user belongs to given [customer groups](customer_groups.md). | Conditions, rules | | Function | `calculate_purchase_amount()` | Purchase amount, calculated for all products in the cart before the discounts are applied.| Conditions, rules | | Function | `is_product_in_product_codes()` | Parameters:
- [Product object](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-ProductInterface.html)
- array of product codes
Returns `true` if the product is part of the given list.| Conditions, rules | diff --git a/docs/ibexa_products/editions.md b/docs/ibexa_products/editions.md index b833a82376..bd2a034677 100644 --- a/docs/ibexa_products/editions.md +++ b/docs/ibexa_products/editions.md @@ -30,7 +30,7 @@ Compare all features available in [[= product_name_headless =]], [[= product_nam | [Search]([[= user_doc =]]/search/search_for_content/) | ✔ | ✔ | ✔ | | [Editorial workflow]([[= user_doc =]]/content_management/workflow_management/editorial_workflow/) | ✔ | ✔ | ✔ | | [Digital Asset Management]([[= user_doc =]]/dam/ibexa_dam/) | ✔ | ✔ | ✔ | -| [Product Information Management]([[= user_doc =]]/pim/pim/) | ✔ | ✔ | ✔ | +| [Product catalog capabilities]([[= user_doc =]]/pim/pim/) | ✔ | ✔ | ✔ | | [Date and time attribute type](date_and_time.md) | ✔ | ✔ | ✔ | | [Symbol attribute type](symbol_attribute_type.md) | ✔ | ✔ | ✔ | | [Personalization](personalization_guide.md) | ✔ | ✔ | ✔ | @@ -67,5 +67,6 @@ The features brought by LTS Updates become standard parts of the next LTS releas | Feature | [[= product_name_headless =]] | [[= product_name_exp =]] | [[= product_name_com =]] | |-----------------|-----------------|-----------------|-----------------| | [Anthropic connector](configure_ai_actions.md#install-anthropic-connector) | ✔ | ✔ | ✔ | +| [Google Gemini connector](configure_ai_actions.md#install-google-gemini-connector) | ✔ | ✔ | ✔ | | [Integrated help](integrated_help.md) | ✔ | ✔ | ✔ | | [Shopping list](shopping_list_guide.md) | | | ✔ | diff --git a/docs/ibexa_products/ibexa_commerce.md b/docs/ibexa_products/ibexa_commerce.md index 2a99fc715c..fae132a317 100644 --- a/docs/ibexa_products/ibexa_commerce.md +++ b/docs/ibexa_products/ibexa_commerce.md @@ -84,7 +84,7 @@ You can set up your search engine using [[= product_name_com =]] to help clients #### Catalog management -[[= product_name_com =]] gives you the ability to manage your product repository - [PIM](pim_guide.md), and construct an infinite number of product catalogs, each with unique prices, to further customize the experience for your customers. +[[= product_name_com =]] gives you the ability to manage your product repository - [Product catalog](product_catalog_guide.md), and construct an infinite number of catalogs, each with unique prices, to further customize the experience for your customers. #### Transactional emails diff --git a/docs/ibexa_products/ibexa_headless.md b/docs/ibexa_products/ibexa_headless.md index f1285f5a2e..8f7fd51d9b 100644 --- a/docs/ibexa_products/ibexa_headless.md +++ b/docs/ibexa_products/ibexa_headless.md @@ -10,7 +10,7 @@ description: Get to know Ibexa Headless - an edition that focuses on content man The Headless edition of [[= product_name =]] focuses on content management. It provides tools to collaboratively create content, and interfaces (API) to distribute this content. -Multilingual, multichannel, extensible, [[= product_name_headless =]] is an advanced Content Management Framework (CMF), a Product Information Management (PIM) platform, and a Digital Asset Management (DAM) repository. +Multilingual, multichannel, extensible, [[= product_name_headless =]] is an advanced Content Management Framework (CMF) with product catalog capabilities, and a Digital Asset Management (DAM) repository. It's provided without a default front office, but with a complete back office and several APIs to manage and access content. ![Ibexa Headless](ibexa_headless.png) @@ -118,7 +118,7 @@ Like everything in the back office, the calendar is extendable: you can add an e #### Many ways to structure and organize content -[Product Information Management](pim_guide.md) (PIM) helps organize complex products and their catalogs: +[Product catalog](product_catalog_guide.md) helps organize complex products and their catalogs: - Products are organized by using product types, variants, catalogs, categories, and tags. - Product attributes are grouped and factorized among product types. For example, fabric + color + size can be shared by many clothing product types. diff --git a/docs/index.md b/docs/index.md index 3ad2bdb604..62bac368dd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -89,11 +89,11 @@
-

The newest LTS Update is Shopping list

-
Customers can use it to save potential purchases, recurring product sets, and other items for future use in the cart.
+

The newest LTS Update is Google Gemini connector

+
Integrate Google's AI services into Ibexa DXP.
@@ -122,8 +122,8 @@
@@ -185,15 +185,16 @@ diff --git a/docs/infrastructure_and_maintenance/backup.md b/docs/infrastructure_and_maintenance/backup.md index b0f985a0ab..0e710ea36a 100644 --- a/docs/infrastructure_and_maintenance/backup.md +++ b/docs/infrastructure_and_maintenance/backup.md @@ -20,20 +20,25 @@ cd /path/to/ibexa 2\. Clear all caches: -```bash -var/cache/* -var/logs/* +``` bash +rm -rf var/cache/* +rm -rf var/share/* +rm -rf var/logs/* ``` 3\. Create a dump of the database: -```bash -# MySQL -mysqldump -u --add-drop-table > db_backup.sql +=== "MySQL" -# PostgreSQL -pg_dump -c --if-exists > db_backup.sql -``` + ``` bash + mysqldump -u --add-drop-table > db_backup.sql + ``` + +=== "PostgreSQL" + + ``` bash + pg_dump -c --if-exists > db_backup.sql + ``` 4\. In parent directory create a tar archive of the files (including the database dump) using the "tar" command: diff --git a/docs/infrastructure_and_maintenance/support_and_maintenance_faq.md b/docs/infrastructure_and_maintenance/support_and_maintenance_faq.md index feb032c3e7..72c192194d 100644 --- a/docs/infrastructure_and_maintenance/support_and_maintenance_faq.md +++ b/docs/infrastructure_and_maintenance/support_and_maintenance_faq.md @@ -76,12 +76,12 @@ php bin/console cache:pool:clear cache.redis ```bash rm -rf var/cache/* +rm -rf var/share/* ``` !!! caution "Clearing cache manually" - Manual cache clearing should be executed with caution. - `rm -rf var/cache/*` wipes all the files and unlike `cache:clear` doesn't warm up the cache. + Manual cache clearing should be executed with caution, as it doesn't warm up the cache. It results in a significant performance drop on first request, so it shouldn't be called on a production environment. Besides, it could lead to issues with file ownership after running `cache:clear` as a root. diff --git a/docs/permissions/limitation_reference.md b/docs/permissions/limitation_reference.md index 51cf008013..b4f54984de 100644 --- a/docs/permissions/limitation_reference.md +++ b/docs/permissions/limitation_reference.md @@ -290,6 +290,10 @@ The Personalization limitation specifies the SiteAccesses for which the user can The Product Type (`ProductType`) limitation specifies whether the user has access to products belonging to a specific product type. +!!! warning + + The `ProductType` limitation can't be used when using [[[= pim_product_name =]]](/product_catalog/quable/quable.md). + ### Possible values |Value|UI value|Description| diff --git a/docs/permissions/policies.md b/docs/permissions/policies.md index 396caa67a7..723b90d4f9 100644 --- a/docs/permissions/policies.md +++ b/docs/permissions/policies.md @@ -289,7 +289,7 @@ The [discount](discounts.md) policies decide which actions can be executed by gi | `comparison` | `view` | view version comparison | | `workflow` | `change_stage` | change stage in the specified workflow | [Workflow Transition](limitation_reference.md#workflow-transition-limitation) | -### PIM +### Product catalog #### Catalogs @@ -309,6 +309,10 @@ The [discount](discounts.md) policies decide which actions can be executed by gi | | `edit` | edit a product | [Product Type](limitation_reference.md#product-type-limitation)
[Language](limitation_reference.md#language-limitation) | | | `view` | view products listed in the product catalog | [Product Type](limitation_reference.md#product-type-limitation) | +!!! warning + + The `ProductType` limitation can't be used when using [[[= pim_product_name =]]](/product_catalog/quable/quable.md). + #### Product collaborative editing | Module | Function | Effect | Possible limitations | @@ -317,12 +321,16 @@ The [discount](discounts.md) policies decide which actions can be executed by gi #### Product types -| Module | Function | Effect | Possible limitations | -|-----------------------------|-----------------------|-----------------------------------------------------------------------------------------------------------------|----------------------| -| `product_type` | `create` | create a product type, a new attribute, a new attribute group, and add translation to product type and attribute | -| | `delete` | delete a product type, attribute, attribute group | -| | `edit` | edit a product type, attribute, attribute group | -| | `view` | view product types, attributes and attribute groups | +| Module | Function | Effect | Possible limitations | +|-----------------------------|-----------------------|------------------------------------------------------------------------------------------------------------------|----------------------| +| `product_type` | `create` | create a product type, a new attribute, a new attribute group, and add translation to product type and attribute | [Product Type](limitation_reference.md#product-type-limitation) | +| | `delete` | delete a product type, attribute, attribute group | | +| | `edit` | edit a product type, attribute, attribute group | [Product Type](limitation_reference.md#product-type-limitation) | +| | `view` | view product types, attributes and attribute groups | | + +!!! warning + + The `ProductType` limitation can't be used when using [[[= pim_product_name =]]](/product_catalog/quable/quable.md). ## Combining policies diff --git a/docs/pim/customize_pim.md b/docs/pim/customize_pim.md deleted file mode 100644 index 877e1daebc..0000000000 --- a/docs/pim/customize_pim.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -description: Customize PIM to the needs of your organization. -page_type: landing_page ---- - -# Customize PIM - -You can customize various areas of the Product Information Management solution to adjust it to the specific requirements of your organization. - -[[= cards([ - "pim/create_custom_attribute_type", - "pim/create_product_code_generator", - "pim/create_custom_catalog_filter", - "pim/create_custom_name_schema_strategy", -], columns=4) =]] diff --git a/docs/pim/pim.md b/docs/pim/pim.md deleted file mode 100644 index 2fd55d49f9..0000000000 --- a/docs/pim/pim.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -description: Ibexa DXP offers PIM functionalities, with product, product type, product variant and attribute management capabilities to manage complex products. -page_type: landing_page ---- - -# PIM (Product management) - -PIM (Product Information Management) enables handling of products offered in the shop, -including their specifications and pricing. - -[[= cards([ - "pim/pim_guide", - "pim/products", - "pim/catalogs", - "pim/pim_configuration", - "pim/prices", -], columns=3) =]] diff --git a/docs/pim/add_remote_pim_support.md b/docs/product_catalog/add_remote_pim_support.md similarity index 71% rename from docs/pim/add_remote_pim_support.md rename to docs/product_catalog/add_remote_pim_support.md index ef537b0273..abb7a820d0 100644 --- a/docs/pim/add_remote_pim_support.md +++ b/docs/product_catalog/add_remote_pim_support.md @@ -4,7 +4,10 @@ description: Install and configure the Remote PIM example package. # Add Remote PIM support -To implement [Remote PIM support](pim_guide.md#remote-pim-support) you can build upon a foundation provided by [[= product_name_base =]]. +[[= product_name =]] provides flexible product catalog infrastructure that works with external Product Information Management (PIM) systems. +For advanced product data management without custom development, you can use the readily available [[[= pim_product_name =]] PIM integration](quable/quable.md) with [[= product_name =]]. + +To implement [Remote PIM support](product_catalog_guide.md#remote-pim-support) for a custom integration, you can build upon a foundation provided by [[= product_name_base =]]. While doing so, you must implement services that process data coming from the remote PIM. @@ -22,7 +25,7 @@ To connect to your remote PIM, provide your implementation of the following serv ## Switch to the new product catalog engine -To inform the application that the local PIM engine has been replaced by an external one, in `config/packages/ibexa_product_catalog.yaml`, set the new product catalog engine, for example: +To inform the application that the product catalog engine has been replaced by an external one, in `config/packages/ibexa_product_catalog.yaml`, set the new product catalog engine, for example: ``` yaml ibexa_product_catalog: @@ -46,12 +49,12 @@ ibexa: !!! note "Enabling the remote PIM support" - By default, the `ibexa.repositories..product_catalog.engine.type` key is set to `local`, which informs [[= product_name =]] that the built-in PIM solution is used. + By default, the `ibexa.repositories..product_catalog.engine.type` key is set to `local`, which informs [[= product_name =]] that the built-in product catalog capabilities are used. By changing this setting and the `ibexa.repositories..product_catalog.engine` setting from `default` to your custom value, you inform [[= product_name =]] that you're using a remote PIM. ## Install Remote PIM example package -The example implementation provides services that take over the role of services provided by the local PIM package. +The example implementation provides services that take over the role of services provided by the product catalog package. You can modify them to suit your needs. Install the `ibexa/example-in-memory-product-catalog` package: diff --git a/docs/pim/attributes/date_and_time.md b/docs/product_catalog/attributes/date_and_time.md similarity index 94% rename from docs/pim/attributes/date_and_time.md rename to docs/product_catalog/attributes/date_and_time.md index f01446bb98..e07ddc1a76 100644 --- a/docs/pim/attributes/date_and_time.md +++ b/docs/product_catalog/attributes/date_and_time.md @@ -4,7 +4,7 @@ description: Date and time attribute type allows you to store product informatio # Date and time attributes -The date and time [attribute type](products.md#product-attributes) allows you to represent date and time values as part of the product specification in the [Product Information Management](pim_guide.md) system. +The date and time [attribute type](products.md#product-attributes) allows you to represent date and time values as part of the product specification in the [product catalog](product_catalog_guide.md). You can use it to store, for example, manufacturing dates, expiration dates, or event dates, all with specified accuracy. diff --git a/docs/pim/attributes/img/datetime.png b/docs/product_catalog/attributes/img/datetime.png similarity index 100% rename from docs/pim/attributes/img/datetime.png rename to docs/product_catalog/attributes/img/datetime.png diff --git a/docs/pim/attributes/symbol_attribute_type.md b/docs/product_catalog/attributes/symbol_attribute_type.md similarity index 95% rename from docs/pim/attributes/symbol_attribute_type.md rename to docs/product_catalog/attributes/symbol_attribute_type.md index d29643f537..284ebabb60 100644 --- a/docs/pim/attributes/symbol_attribute_type.md +++ b/docs/product_catalog/attributes/symbol_attribute_type.md @@ -6,7 +6,7 @@ description: Create a symbol attribute type that enables for the efficient repre In product specifications, the symbol attribute type enables the efficient representation of string-based data and enforces their format. -This feature allows you to store standard product identifiers (such as EAN or ISBN) in the [Product Information Management](pim_guide.md) system. +This feature allows you to store standard product identifiers (such as EAN or ISBN) in the [product catalog](product_catalog_guide.md). ## Build-in symbol attribute formats @@ -66,7 +66,7 @@ To validate checksum of symbol: See below the example implementation of checksum validation using Luhn formula: ``` php -[[= include_file('code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php') =]] +[[= include_file('code_samples/product_catalog/Symbol/Format/Checksum/LuhnChecksum.php') =]] ``` Example service definition: diff --git a/docs/pim/catalog_api.md b/docs/product_catalog/catalog_api.md similarity index 100% rename from docs/pim/catalog_api.md rename to docs/product_catalog/catalog_api.md diff --git a/docs/pim/catalogs.md b/docs/product_catalog/catalogs.md similarity index 100% rename from docs/pim/catalogs.md rename to docs/product_catalog/catalogs.md diff --git a/docs/pim/create_custom_attribute_type.md b/docs/product_catalog/create_custom_attribute_type.md similarity index 100% rename from docs/pim/create_custom_attribute_type.md rename to docs/product_catalog/create_custom_attribute_type.md diff --git a/docs/pim/create_custom_catalog_filter.md b/docs/product_catalog/create_custom_catalog_filter.md similarity index 100% rename from docs/pim/create_custom_catalog_filter.md rename to docs/product_catalog/create_custom_catalog_filter.md diff --git a/docs/pim/create_custom_name_schema_strategy.md b/docs/product_catalog/create_custom_name_schema_strategy.md similarity index 100% rename from docs/pim/create_custom_name_schema_strategy.md rename to docs/product_catalog/create_custom_name_schema_strategy.md diff --git a/docs/pim/create_product_code_generator.md b/docs/product_catalog/create_product_code_generator.md similarity index 78% rename from docs/pim/create_product_code_generator.md rename to docs/product_catalog/create_product_code_generator.md index 05ef3379ce..e7c000604a 100644 --- a/docs/pim/create_product_code_generator.md +++ b/docs/product_catalog/create_product_code_generator.md @@ -6,7 +6,7 @@ description: A custom product code generator enables you to control how product Product code generator strategies control what product variant codes are generated. -Besides the [built-in](pim_configuration.md#code-generation-strategy) strategies, you can create your own ones. +Besides the [built-in](product_catalog_configuration.md#code-generation-strategy) strategies, you can create your own ones. A code generator strategy must implement `Ibexa\Contracts\ProductCatalog\Local\CodeGenerator\CodeGeneratorInterface`. @@ -26,4 +26,4 @@ Then, register the strategy generator as a service and tag it with `ibexa.produc [[= include_file('code_samples/catalog/custom_code_generator_strategy/config/custom_services.yaml') =]] ``` -Use the defined `type` in [catalog configuration](pim_configuration.md#code-generation-strategy) to apply codes generated by this strategy to new product variants. +Use the defined `type` in [catalog configuration](product_catalog_configuration.md#code-generation-strategy) to apply codes generated by this strategy to new product variants. diff --git a/docs/product_catalog/customize_product_attribute_templates.md b/docs/product_catalog/customize_product_attribute_templates.md new file mode 100644 index 0000000000..3fc261a8e5 --- /dev/null +++ b/docs/product_catalog/customize_product_attribute_templates.md @@ -0,0 +1,93 @@ +--- +description: Customize the Twig templates used to render product attribute values. +month_change: true +--- + +# Customize product attribute templates + +The `ibexa_format_product_attribute` Twig filter renders a product attribute value by using a configurable list of Twig templates. +Each template contains Twig blocks that control how specific [attribute types](products.md#product-attributes) are displayed. + +You can customize this rendering by: + +- adding your own template [to the configuration](product_catalog_configuration.md#attribute-rendering-templates). +- injecting a template by subscribing to the [`ProductAttributeRenderEvent`](product_catalog_events.md#attribute-rendering) event + +## Template blocks + +Each template can define the following blocks: + +| Block | Used for | +|---|---| +| `_attribute` | Rendering an attribute of a specific type. Replace `` with the attribute type identifier, for example `color_attribute` or `integer_attribute`. | +| `generic_attribute` | Fallback block used when no type-specific block is found. | + +For a list of available attributes, see [product attributes](products.md#product-attributes). + +When rendering an attribute, the system iterates through the configured templates in order and uses the first matching type-specific block it finds. +If none is found, it falls back to the first `generic_attribute` block available. + +### [[= pim_product_name =]] attribute types + +When using [[[= pim_product_name =]] PIM](/product_catalog/quable/quable.md), use the following identifiers to override the templates for [[[= pim_product_name =]]'s attribute types](https://docs.quable.com/v5-EN/docs/objects-and-attributes#attribute-types): + +| Attribute name | Identifier | +|---|---| +| Simple text not localized | `unlocalized_text` | +| Simple text localized | `localized_text` | +| Text area localized | `multiline_text` | +| HTML code | `html_text` | +| JSON code | `json_text` | +| Integer | `integer` | +| Decimal | `decimal` | +| Date | `date` | +| Time | `time` | +| Checkbox | `switch` | +| Simple select of predefined values | `simple_select` | +| Select of multiple predefined values | `multi_select` | +| Calculated | `calculated` | + +### Template variables + +The following variables are available in attribute template blocks: + +| Variable | Type | Description | +|---|---|---| +| `attribute` | [`AttributeInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-AttributeInterface.html) | The attribute object being rendered. | +| `value` | `?string` | The pre-formatted attribute value, produced by the value formatter. | +| `parameters` | `array` | Optional rendering parameters passed to the filter or modified by an event subscriber. | + +## Create custom attribute template + +Create a Twig template and define the blocks for the attribute types you want to customize: + +- To customize a specific attribute type, define a block named `_attribute`. +- To handle all remaining types, define a `generic_attribute` block. + +The following example adds a custom template for an `integer` attribute type: + +```html+twig +{# templates/product/attributes/integer_attribute.html.twig #} + +{% block integer_attribute %} + Integer value: {{ value }} +{% endblock %} +``` + +Then, [configure the product catalog](product_catalog_configuration.md#attribute-rendering-templates) to use it: + +``` yaml +ibexa_product_catalog: + templates: + attributes: + - 'templates/product/attributes/integer_attribute.html.twig' +``` + +## Inject templates at runtime + +You can inject additional templates by listening to the [`ProductAttributeRenderEvent`](product_catalog_events.md#attribute-rendering) event. +Use this option when you want to add templates conditionally, for example based on the active catalog engine or region. + +``` php +[[= include_file('code_samples/product_catalog/src/EventSubscriber/MyAttributeRenderSubscriber.php') =]] +``` diff --git a/docs/product_catalog/customize_product_catalog.md b/docs/product_catalog/customize_product_catalog.md new file mode 100644 index 0000000000..e7fe81495c --- /dev/null +++ b/docs/product_catalog/customize_product_catalog.md @@ -0,0 +1,17 @@ +--- +description: Customize the product catalog to the needs of your organization. +page_type: landing_page +--- + +# Customize product catalog + +You can customize various areas of the product catalog capabilities to adjust it to the specific requirements of your organization. + +[[= cards([ + "product_catalog/create_custom_attribute_type", + "product_catalog/create_product_code_generator", + "product_catalog/create_custom_catalog_filter", + "product_catalog/create_custom_name_schema_strategy", + "product_catalog/customize_product_attribute_templates", + "product_catalog/customize_product_embed_templates", +], columns=4) =]] diff --git a/docs/product_catalog/customize_product_embed_templates.md b/docs/product_catalog/customize_product_embed_templates.md new file mode 100644 index 0000000000..2abd17da32 --- /dev/null +++ b/docs/product_catalog/customize_product_embed_templates.md @@ -0,0 +1,80 @@ +--- +description: Customize the templates used to render products embedded in RichText fields. +month_change: true +--- + +# Customize product embed templates + +When a product is [embedded in a RichText field](products.md#embed-products-in-content), it is rendered by using a Twig template. +You can override the default templates to customize the appearance of embedded products. + +## Embed types + +Six embed types exist in the system, each with its own template: + +| Embed type | Description | +| --- | --- | +| `product` | Block-level embed when the product is found and the user has access. | +| `product_inline` | Inline embed when the product is found and the user has access. | +| `product_denied` | Block-level embed when the user has no access to view the product data. | +| `product_inline_denied` | Inline embed when the user has no access to view the product data. | +| `product_not_found` | Block-level embed when the product code cannot be found. | +| `product_inline_not_found` | Inline embed when the product code cannot be found. | + +## Template variables + +The following variables are available in the embed templates: + +| Variable | Available in | Description | +|---|---|---| +| `product` | `product`, `product_inline` | A [`ProductInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-ProductInterface.html) object. | +| `productCode` | `product_denied`, `product_inline_denied`, `product_not_found`, `product_inline_not_found` | The product code string, used to identify the product that could not be loaded. | +| `embedParams` | All block types | Optional parameters set by the online editor, for example `align` or `class` properties | + +## Override template + +The default templates are located in `vendor/ibexa/product-catalog/src/bundle/Resources/views/themes/standard/product_catalog/richtext/embed/`. + +To override a template, create a file with the same name in your [theme directory](design_engine.md). +For example, to override the block embed template for the `standard` theme, create a file in `templates/themes/standard/product_catalog/richtext/embed/product.html.twig` + +A minimal product embed template looks as follows: + +```html+twig +
+ {{ product.name }} +
+``` + +And a minimal inline embed template (`product_inline.html.twig`): + +```html+twig +{{ product.name }} +``` + +## Configure template paths + +In addition to overriding the templates with the [design engine](design_engine.md), you can explicitly set the template path for any embed type in your [SiteAccess configuration](multisite_configuration.md): + +```yaml +ibexa: + system: + : + fieldtypes: + ibexa_richtext: + embed: + product: + template: '@ibexadesign/product_catalog/richtext/embed/product.html.twig' + product_inline: + template: '@ibexadesign/product_catalog/richtext/embed/product_inline.html.twig' + product_denied: + template: '@ibexadesign/product_catalog/richtext/embed/product_denied.html.twig' + product_inline_denied: + template: '@ibexadesign/product_catalog/richtext/embed/product_inline_denied.html.twig' + product_not_found: + template: '@ibexadesign/product_catalog/richtext/embed/product_not_found.html.twig' + product_inline_not_found: + template: '@ibexadesign/product_catalog/richtext/embed/product_inline_not_found.html.twig' +``` + +Replace `` with the name of your SiteAccess or SiteAccess group (for example, `default`). diff --git a/docs/pim/enable_purchasing_products.md b/docs/product_catalog/enable_purchasing_products.md similarity index 100% rename from docs/pim/enable_purchasing_products.md rename to docs/product_catalog/enable_purchasing_products.md diff --git a/docs/pim/img/catalog_custom_attribute_type.png b/docs/product_catalog/img/catalog_custom_attribute_type.png similarity index 100% rename from docs/pim/img/catalog_custom_attribute_type.png rename to docs/product_catalog/img/catalog_custom_attribute_type.png diff --git a/docs/pim/img/catalog_vat_rates.png b/docs/product_catalog/img/catalog_vat_rates.png similarity index 100% rename from docs/pim/img/catalog_vat_rates.png rename to docs/product_catalog/img/catalog_vat_rates.png diff --git a/docs/pim/img/catalogs_filters.png b/docs/product_catalog/img/catalogs_filters.png similarity index 100% rename from docs/pim/img/catalogs_filters.png rename to docs/product_catalog/img/catalogs_filters.png diff --git a/docs/pim/img/custom_catalog_filter.png b/docs/product_catalog/img/custom_catalog_filter.png similarity index 100% rename from docs/pim/img/custom_catalog_filter.png rename to docs/product_catalog/img/custom_catalog_filter.png diff --git a/docs/pim/img/diagrams_source/remote_pim_support.xml b/docs/product_catalog/img/diagrams_source/remote_pim_support.xml similarity index 100% rename from docs/pim/img/diagrams_source/remote_pim_support.xml rename to docs/product_catalog/img/diagrams_source/remote_pim_support.xml diff --git a/docs/pim/img/general_assets.png b/docs/product_catalog/img/general_assets.png similarity index 100% rename from docs/pim/img/general_assets.png rename to docs/product_catalog/img/general_assets.png diff --git a/docs/pim/img/group_base_pricing.png b/docs/product_catalog/img/group_base_pricing.png similarity index 100% rename from docs/pim/img/group_base_pricing.png rename to docs/product_catalog/img/group_base_pricing.png diff --git a/docs/pim/img/grouping_products.png b/docs/product_catalog/img/grouping_products.png similarity index 100% rename from docs/pim/img/grouping_products.png rename to docs/product_catalog/img/grouping_products.png diff --git a/docs/pim/img/how_pim_works.png b/docs/product_catalog/img/how_pim_works.png similarity index 100% rename from docs/pim/img/how_pim_works.png rename to docs/product_catalog/img/how_pim_works.png diff --git a/docs/pim/img/multilevel_variants.png b/docs/product_catalog/img/multilevel_variants.png similarity index 100% rename from docs/pim/img/multilevel_variants.png rename to docs/product_catalog/img/multilevel_variants.png diff --git a/docs/pim/img/product_assets.png b/docs/product_catalog/img/product_assets.png similarity index 100% rename from docs/pim/img/product_assets.png rename to docs/product_catalog/img/product_assets.png diff --git a/docs/pim/img/product_attribute_types.png b/docs/product_catalog/img/product_attribute_types.png similarity index 100% rename from docs/pim/img/product_attribute_types.png rename to docs/product_catalog/img/product_attribute_types.png diff --git a/docs/pim/img/product_attributes.png b/docs/product_catalog/img/product_attributes.png similarity index 100% rename from docs/pim/img/product_attributes.png rename to docs/product_catalog/img/product_attributes.png diff --git a/docs/pim/img/product_categories.png b/docs/product_catalog/img/product_categories.png similarity index 100% rename from docs/pim/img/product_categories.png rename to docs/product_catalog/img/product_categories.png diff --git a/docs/pim/img/regional_vat.png b/docs/product_catalog/img/regional_vat.png similarity index 100% rename from docs/pim/img/regional_vat.png rename to docs/product_catalog/img/regional_vat.png diff --git a/docs/pim/img/remote_pim_support.png b/docs/product_catalog/img/remote_pim_support.png similarity index 100% rename from docs/pim/img/remote_pim_support.png rename to docs/product_catalog/img/remote_pim_support.png diff --git a/docs/pim/price_api.md b/docs/product_catalog/price_api.md similarity index 100% rename from docs/pim/price_api.md rename to docs/product_catalog/price_api.md diff --git a/docs/pim/prices.md b/docs/product_catalog/prices.md similarity index 87% rename from docs/pim/prices.md rename to docs/product_catalog/prices.md index 6c9a906c3e..6109093886 100644 --- a/docs/pim/prices.md +++ b/docs/product_catalog/prices.md @@ -4,7 +4,7 @@ description: The price engine calculates product prices taking into account cust # Prices -The price engine is responsible for calculating prices for products in the [catalog](pim.md). +The price engine is responsible for calculating prices for products in the [product catalog](product_catalog.md). ## Custom pricing @@ -30,4 +30,4 @@ To use currencies in your shop, you need to first enable them in the back office ## VAT -You can [configure VAT rate globally](pim_configuration.md#vat-rates) (per SiteAccess), or set it individually for each product type and product. +You can [configure VAT rate globally](product_catalog_configuration.md#vat-rates) (per SiteAccess), or set it individually for each product type and product. diff --git a/docs/pim/product_api.md b/docs/product_catalog/product_api.md similarity index 96% rename from docs/pim/product_api.md rename to docs/product_catalog/product_api.md index 92d049522d..3f604a680b 100644 --- a/docs/pim/product_api.md +++ b/docs/product_catalog/product_api.md @@ -9,8 +9,10 @@ month_change: false [[= product_name =]]'s Product API provides two services for handling product information, which differ in function: -- [`ProductServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-ProductServiceInterface.html) is used to request product data -- [`LocalProductServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Local-LocalProductServiceInterface.html) is used to modify products +| Service name | Description | +| ------------ | ----------- | +| [`ProductServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-ProductServiceInterface.html) | Use it to retrieve product data regardless of the source: [[= product_name =]], [[[= pim_product_name =]]](/product_catalog/quable/quable.md), or [remote PIM](add_remote_pim_support.md) | +| [`LocalProductServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Local-LocalProductServiceInterface.html) | Use it to modify products defined in [[= product_name =]] | !!! tip "Product REST API" diff --git a/docs/product_catalog/product_catalog.md b/docs/product_catalog/product_catalog.md new file mode 100644 index 0000000000..904eda2e95 --- /dev/null +++ b/docs/product_catalog/product_catalog.md @@ -0,0 +1,22 @@ +--- +description: Ibexa DXP provides product catalog capabilities for managing products, product types, variants, attributes, pricing, and catalogs. +page_type: landing_page +month_change: true +--- + +# Product Catalog + +The Product Catalog provides comprehensive capabilities for managing products offered in your digital commerce experience, including their specifications, pricing, and organization. + +[[= product_name =]] offers robust product catalog infrastructure that can be used standalone. + +You can also use [[[= pim_product_name =]] Product Information Management (PIM)](/product_catalog/quable/quable.md) add-on that fully integrates into the [[= product_name_base =]] ecosystem, or the [Remote PIM](add_remote_pim_support.md) to add integration with any external PIM system. + +[[= cards([ + "product_catalog/product_catalog_guide", + "product_catalog/quable/quable", + "product_catalog/products", + "product_catalog/catalogs", + "product_catalog/product_catalog_configuration", + "product_catalog/prices", +], columns=3) =]] diff --git a/docs/pim/pim_configuration.md b/docs/product_catalog/product_catalog_configuration.md similarity index 74% rename from docs/pim/pim_configuration.md rename to docs/product_catalog/product_catalog_configuration.md index e2c1884587..6bab65e630 100644 --- a/docs/pim/pim_configuration.md +++ b/docs/product_catalog/product_catalog_configuration.md @@ -1,10 +1,10 @@ --- -description: Configure PIM settings per Repository, with different catalog engines and VAT configurations. +description: Configure product catalog settings per repository, with different catalog engines and VAT configurations. --- -# PIM configuration +# Product catalog configuration -You can configure PIM per [Repository](repository_configuration.md). +You can configure the product catalog per [Repository](repository_configuration.md). Under `ibexa.repositories..product_catalog` [configuration key](configuration.md#configuration-files), indicate the catalog engine to use: @@ -32,7 +32,11 @@ ibexa_product_catalog: product_type_group_identifier: 'product' ``` -The `local` type is the built-in type of catalog based on the repository. +The `local` type is the built-in type of catalog based on the content repository. +With [[[= pim_product_name =]] PIM integration](/product_catalog/quable/quable_guide.md) add-on installed and configured, by using the `quable` type you can retrieve product data coming from [[= pim_product_name =]]. + +You can use a single engine across all repositories, or assign different ones per repository. +Each repository can use only one product catalog engine. Under `options.product_type_group_identifier` you can define the identifier of the content type Group used for storing products. @@ -100,6 +104,21 @@ ibexa_product_catalog: You can also [create your own custom code generation strategy](create_product_code_generator.md). +## Attribute rendering templates + +You can configure which Twig templates are used to render product attribute values with the [`ibexa_format_product_attribute` Twig filter](product_twig_functions.md#ibexa_format_product_attribute). + +```yaml +ibexa_product_catalog: + templates: + attributes: + - 'templates/product/attributes/my_attribute_blocks.html.twig' +``` + +The default template (`@ibexadesign/product_catalog/product/attributes/attribute_blocks.html.twig`) is always appended as the last fallback, even if not listed explicitly. + +For more information, see [Customize product attribute templates](customize_product_attribute_templates.md). + ## Catalogs ### Catalog filters diff --git a/docs/pim/pim_guide.md b/docs/product_catalog/product_catalog_guide.md similarity index 78% rename from docs/pim/pim_guide.md rename to docs/product_catalog/product_catalog_guide.md index 7f3f50ed16..0fa004ab75 100644 --- a/docs/pim/pim_guide.md +++ b/docs/product_catalog/product_catalog_guide.md @@ -1,30 +1,31 @@ --- -description: The PIM product guide provides a full description of the features and benefits that this module brings to the clients. +description: The product catalog guide provides a full description of the features and capabilities for managing products, their specifications, variants, pricing, and organization. month_change: false --- -# PIM product guide +# Product catalog guide -## What is PIM +## What is product catalog -PIM is a Product Information Management module that lets you create, configure, and manage products, their specifications, assets, variants, and prices, but also group products into categories and catalogs. +The product catalog is a comprehensive set of capabilities for managing products in [[= product_name =]] that can be used standalone. +It lets you create, configure, and manage products, their specifications, assets, variants, and prices, and group products into categories and catalogs. ## Availability -PIM is available in all [[= product_name =]] editions. +Product catalog capabilities are available in all [[= product_name =]] editions. -## How does PIM work +## How does product catalog work -Products in [[= product_name =]]’s PIM have underlying content items enriched with product-specific information such as attributes, assets, prices, and others. +Products in [[= product_name =]]’s product catalog have underlying content items enriched with product-specific information such as attributes, assets, prices, and others. -PIM lets you group products into categories and catalogs. +The product catalog lets you group products into categories and catalogs. Catalogs are collections of products selected by using configurable filters. They're specific to each of your sites or storefronts and only contain the products in them that you wish to sell in their associated storefronts. Catalogs contain a complete list of related products that can be displayed on a store site. You can have as many catalogs as required. -![How does PIM work](img/how_pim_works.png) +![How does product catalog work](img/how_pim_works.png) ## Capabilities @@ -70,7 +71,7 @@ A product can only be ordered when it has either positive stock, or stock set to ### Product categories -Product categories help you to organize your products within PIM and also create relationships between them. +Product categories help you to organize your products within the product catalog and also create relationships between them. Each product can belong to multiple categories of, depending on user’s choice, different or similar character. Category can also be assigned to multiple products. @@ -150,29 +151,35 @@ To have a better overview for a specific group of products, you can filter the l - product category - the date when the product was created -Catalog filters let you narrow down the products from the PIM that are available in the given catalog. +Catalog filters let you narrow down the products from the product catalog that are available in the given catalog. Besides, the built-in catalog filters, you can also [create custom ones](create_custom_catalog_filter.md). ### Remote PIM support +[[= product_name =]] provides flexible product catalog infrastructure that works with external PIM systems. + In [[= product_name =]], products are created and maintained by using the REST API or the back office, and their data is stored in a local database. However, in your project or organization, you might have an existing product database, or be specifically concerned about product information security. -To address such needs, [[= product_name =]] provides a foundation for remote PIM support. -You can build upon it to connect to a remote PIM or ERP system, pull product data and present it on your website. +To address such needs, [[= product_name =]] provides remote PIM support. +You can install and configure a readily available [[[= pim_product_name =]] PIM integration](/product_catalog/quable/quable.md) add-on, or build a custom one to connect to a remote PIM or ERP system, pull product data and present it on your website. ![Remote PIM](img/remote_pim_support.png) -Remote PIM support is available in all [[= product_name =]] editions as of version v4.6.0. An example implementation is delivered as an optional package that you can [install and customize](add_remote_pim_support.md) to fulfill your requirements. #### Capabilities With remote PIM support, you can take advantage of the following capabilities: +##### Product marketing + +Use the product information coming from another system in your marketing campaigns to promote certain products or brands. +By embedding the products within content items and landing pages, you can leverage [[= product_name =]] marketing capabilities to showcase products. + ##### Purchasing -Remote PIM support ensures that integration with [Commerce features](commerce.md) mirrors the efficiency of the local PIM, even with [quick orders](quick_order.md). -This versatility allows for a consistent and user-friendly workflow regardless of the product's origin. +Remote PIM systems can integrate with [Commerce features](commerce.md). +This versatility allows for a consistent and user-friendly purchasing workflow regardless of the product's origin. ##### Pricing, stock and availability @@ -181,18 +188,25 @@ A product can only be ordered when it has defined [availability]([[= user_doc =] By default, such information is held in the [[= product_name =]]'s local database. In your specific scenario, you can implement the support for availability and pricing information coming from an external source as well, by using a price/availability matching strategy that is an extension point exposed in the Product catalog module. -##### Filtering +#### Limitations + +The limitation of remote PIM depend on implementation details of specific integration and may arise in areas relying on [content model](content_model.md). + +To see the limitations of the [[= pim_product_name =]] PIM integration add-on, see [[[= pim_product_name =]] PIM known limitations](/product_catalog/quable/quable_guide.md#known-limitations). + +##### Searching + +Filtering and pagination function the same as with the product catalog, relying on product attributes for effective organization of product data. +However, criteria and sort clauses within product catalog relying on [[= product_name =]]'s content model are not supported. -Filtering and pagination function the same as with the local PIM, relying on product attributes for effective organization of product data. -However, criteria and Sort Clauses within local PIM correspond with [[= product_name =]]'s content model. Depending on your source of product information, you might need to adjust the implementation to be compatible with your data format. -For reference, you could review the `CriterionVisitor.php` file that is part of [Remote PIM example package](add_remote_pim_support.md#install-remote-pim-example-package). +For reference, you could review the [`CriterionVisitor` class](https://github.com/ibexa/example-in-memory-product-catalog/blob/main/src/lib/PIM/InMemory/CriterionVisitor.php) that is part of [Remote PIM example package](add_remote_pim_support.md#install-remote-pim-example-package). -##### Catalogs +For more information about product search, see [Product Search Criteria reference](product_search_criteria.md) and [Product Sort Clauses](product_sort_clauses.md). -Catalogs can be created just like with the local PIM, but the criteria are limited to type, availability, and attributes. +##### Catalogs -#### Limitations +Depending on the implementation, creating [catalogs](#catalogs) might be supported, but the criteria for filtering can be limited. The default implementation, which serves as a basis for the example remote PIM package, has some limitations: certain functionalities either don't operate or operate within defined constraints. Therefore, if your specific requirements aren't met, you may need to extend [[= product_name =]]. @@ -213,7 +227,7 @@ Therefore, if your specific requirements aren't met, you must extend the applica - Taxonomy - URL aliases -##### Simplified presentation of PIM-related blocks and views +##### Simplified presentation of product-related blocks and views Enabling Remote PIM impacts a number of application views and blocks, such as Product view, Product list, Catalog, and Product Collection. They're simplified, for example, they don't include thumbnails and other assets, or refer to URL aliases. @@ -281,7 +295,7 @@ You can set up different prices depending on customer group - it means that you ### Product taxonomy -The taxonomy mechanism enables creating tags or categories with a tree structure and assign them to a content item, for example, Products. Thanks to this mechanism product categories can be organized into a Category tree to make it easy for the users to browse and to deliver content appropriate for them. +The [taxonomy mechanism](taxonomy.md) enables creating tags or categories with a tree structure and assign them to a content item, for example, Products. Thanks to this mechanism product categories can be organized into a Category tree to make it easy for the users to browse and to deliver content appropriate for them. ### Grouping products into catalogs diff --git a/docs/pim/products.md b/docs/product_catalog/products.md similarity index 84% rename from docs/pim/products.md rename to docs/product_catalog/products.md index d4ce2f9edd..ac6533ec4c 100644 --- a/docs/pim/products.md +++ b/docs/product_catalog/products.md @@ -1,5 +1,5 @@ --- -description: Products in the PIM are characterized by attributes describing their characteristics. You can create product variants and add assets to each product and variant. +description: Products are characterized by attributes describing their characteristics. You can create product variants and add assets to each product and variant. month_change: false --- @@ -40,8 +40,9 @@ The following attribute types are available: - [date and time](date_and_time.md) - float - integer -- measurement +- measurement (`measurement_range` and `measurement_single`) - selection +- [symbol](symbol_attribute_type.md) Product attributes are collected in groups. An example of an attribute group can be dimensions (length, width, height). @@ -64,7 +65,7 @@ You can create product variants automatically based on attributes that have the You can create variants for any combination of values of selected attributes. In the back office you can automatically generate all possible variants for a product. -Codes for product variants are generated automatically based on the [selected strategy](pim_configuration.md#code-generation-strategy). +Codes for product variants are generated automatically based on the [selected strategy](product_catalog_configuration.md#code-generation-strategy). Each product variant has separate availability and stock information. Each variant can also have separate price rules. @@ -77,6 +78,14 @@ Product assets are images that are assigned to products and their specific varia You can group assets in collections which correspond to specific values of attributes. A collection is assigned to the variant or variants that have these attribute values. +## Embed products in content + +You can embed products directly into content, including the [landing pages](pages.md), by using the [Online Editor](online_editor_guide.md). + +Use it to build marketing campaigns directly around the products, bridging product marketing and product data together. + +To customize the design of the embedded products, see [Customize product embed templates](customize_product_embed_templates.md). + ## Product availability and stock Product availability defines whether a product is available in the catalog. diff --git a/docs/product_catalog/quable/configure_quable_connector.md b/docs/product_catalog/quable/configure_quable_connector.md new file mode 100644 index 0000000000..e386ad1207 --- /dev/null +++ b/docs/product_catalog/quable/configure_quable_connector.md @@ -0,0 +1,57 @@ +--- +description: Quable PIM connector configuration reference for Ibexa DXP +page_type: reference +month_change: true +--- + +# Configure Quable connector + +You can customize the behavior of the [[= pim_product_name =]] integration add-on by using the following [configuration](configuration.md). + +## Configuration example + +In `config/packages/ibexa_connector_quable.yaml`, specify your configuration by using the `ibexa_connector_quable` key: + +``` yaml +ibexa_connector_quable: + enabled: true + instance_url: 'https://example.quable.com' + api_token: '' + channel_code: '' + webhook_secret: '' # Needed for webhook authentication + language_map: + eng-GB: en_GB + fre-FR: fr_FR + throw_on_invalid_criteria: '%kernel.debug%' + throw_on_invalid_mapping: '%kernel.debug%' + cache: + enabled: true + attribute: true + attribute_group: true + product: true + product_type: true +``` + +## Configuration options + +| Parameter | Default value | Description | +|-----------|--------------------------|-------------| +| `enabled` | `false` | Enables the connector. | +| `instance_url` | string | Base URL of your [[= pim_product_name =]] instance, for example `https://example.quable.com`. | +| `api_token` | string | [Read Access API token](https://docs.quable.com/v5-EN/docs/api-tokens) used to authenticate requests to [[= pim_product_name =]]. | +| `channel_code` | string | Code of the [[[= pim_product_name =]] channel](https://docs.quable.com/v5-EN/docs/content-channels) used as the source of product data. | +| `webhook_secret` | string | Secret expected in the [webhook](https://docs.quable.com/v5-EN/docs/webhook) authorization header. | +| `language_map` | Empty | Maps [[= product_name =]] language codes (for example, `eng-GB`) to [[= pim_product_name =]] locale codes (for example, `en_GB`). For more information, see [Set up [[= pim_product_name =]] languages](/product_catalog/quable/install_quable.md) | +| `throw_on_invalid_criteria` | `%kernel.debug%` | Controls behavior for unsupported search criteria: `true` throws an exception, `false` only logs unsupported criteria. | +| `throw_on_invalid_mapping` | `%kernel.debug%` | Controls behavior for mapping errors during data transformation: `true` throws an exception, `false` only logs mapping errors. | +| `cache.enabled` | `true` | Global cache switch for the connector. When set to `false`, only [in-memory cache](persistence_cache.md#in-memory-cache-configuration) is used. When set to `true`, [Symfony's `cache.app` cache pool]([[= symfony_doc =]]/cache.html#system-cache-and-application-cache) is used. | +| `cache.attribute` | `true` | Enables caching for attribute definition requests. | +| `cache.`
`attribute_group` | `true` | Enables caching for attribute group requests. | +| `cache.`
`product` | `true` | Enables caching for product requests. | +| `cache.`
`product_type` | `true` | Enables caching for product type requests. | + +In production environments, it's recommended to: + +- keep the `api_token` and the `webhook_secret` [secure](security_checklist.md#app_secret-and-other-secrets) +- enable caching for better performance, by using Redis or Valkey as [persistence cache](persistence_cache.md#redisvalkey) +- disable `throw_on_invalid_criteria` and `throw_on_invalid_mapping` to prevent non-critical errors from causing application crashes diff --git a/docs/product_catalog/quable/install_quable.md b/docs/product_catalog/quable/install_quable.md new file mode 100644 index 0000000000..aaf32e25e9 --- /dev/null +++ b/docs/product_catalog/quable/install_quable.md @@ -0,0 +1,184 @@ +--- +description: Install and configure Quable PIM connector for Ibexa DXP +month_change: true +--- + +# Install Quable connector + +To integrate [[= product_name =]] with [[= pim_product_name =]] PIM, you need to install the [[= pim_product_name =]] connector packages, configure the connection, and set up synchronization. + +## Create [[= pim_product_name =]] instance + +Before installing the [[= pim_product_name =]] connector, ensure you have access to a [[[= pim_product_name =]] PIM instance](https://quable.com). + +## Install package + +Run the following command to install the required package: + +``` bash +composer require ibexa/connector-quable +``` + +The command adds the [[= pim_product_name =]] connector code, including services that enable communication with [[= pim_product_name =]] PIM. + +## Get API credentials + +To connect to [[= pim_product_name =]] PIM, you need an API token: + +1. Log in to your [[= pim_product_name =]] instance, for example, `https://example.quable.com`. +2. Navigate to the [API Tokens](https://docs.quable.com/v5-EN/docs/api-tokens) section. +3. Create a new **Read Access Token** for use in the configuration. + +## Configure [[= pim_product_name =]] connector + +In `config/packages/ibexa_connector_quable.yaml`, specify the configuration for the [[= pim_product_name =]] connector: + +``` yaml +ibexa_connector_quable: + instance_url: 'https://example.quable.com' + api_token: '' + channel_code: '' +``` + +Replace `` with the Read Access API token you obtained from [[= pim_product_name =]] in the previous step. + +[[[= pim_product_name =]]'s channels](https://docs.quable.com/v5-EN/docs/content-channels) allow you to distribute your product information to defined recipients, for example e-commerce platforms. +Select the [[= pim_product_name =]] channel that you want to integrate within [[= product_name =]]. + +For all available configuration options, see [Configure [[= pim_product_name =]]](configure_quable_connector.md). + +## Configure product catalog engine + +To use [[= pim_product_name =]] as a product data source, configure [[= product_name =]]'s [product catalog](product_catalog_guide.md) to use the [[= pim_product_name =]] engine. + +### Define [[= pim_product_name =]] engine + +In `config/packages/ibexa_product_catalog.yaml`, add a new engine configuration: + +``` yaml hl_lines="8-13" +ibexa_product_catalog: + engines: + local: + type: local + options: + root_location_remote_id: ibexa_product_catalog_root + product_type_group_identifier: product + quable: + type: quable + options: + taxonomy: quable + root_location_remote_id: ibexa_product_catalog_root + product_type_group_identifier: product +``` + +This configuration defines two engines: the default `local` engine and the new `quable` engine, allowing you to work with products defined within [[= pim_product_name =]]. + +To learn more about product catalog configuration, see [Product catalog configuration](product_catalog_configuration.md). + +The [[= pim_product_name =]] integration add-on comes with a new [taxonomy](taxonomy.md) called `quable`. +By setting the `ibexa_product_catalog.engines.quable.options.taxonomy` key to `quable`, you configure the engine to use it for storing product categories. + +### Set [[= pim_product_name =]] as default engine + +In your repository configuration, typically in `config/packages/ibexa.yaml`, configure the product catalog to use the [[= pim_product_name =]] engine as the product data source: + +``` yaml hl_lines="9" +ibexa: + repositories: + default: + storage: ~ + search: + engine: '%search_engine%' + connection: default + product_catalog: + engine: quable + regions: + default: ~ +``` + +## Set up languages + +To use the products from [[= pim_product_name =]] within [[= product_name =]] content, make sure the [data languages](https://docs.quable.com/v5-EN/docs/data-languages) in [[= pim_product_name =]] have corresponding [languages](languages.md) in [[= product_name =]]. + +To compare the language configuration in both systems, run the following command: + +``` bash +php bin/console ibexa:quable:languages:check +``` + +Based on the command output, configure the `language_map` in `config/packages/ibexa_connector_quable.yaml`, mapping each [[= product_name =]] language code to its [[= pim_product_name =]] locale code as in the following example: + +``` yaml +ibexa_connector_quable: + # ... + language_map: + eng-GB: en_GB + fre-FR: fr_FR +``` + +The system uses the language map to retrieve data in the correct language from [[= pim_product_name =]]. + +After configuring the map, rerun the `ibexa:quable:languages:check` command to confirm all languages are correctly mapped. + +## Synchronize taxonomy + +After configuring the integration, synchronize [product classifications from [[= pim_product_name =]]](https://docs.quable.com/v5-EN/docs/documents-classification-new-version) to [[= product_name =]]'s [taxonomies](taxonomy.md). + +Run the following command to synchronize classifications: + +``` bash +php bin/console ibexa:quable:classification:sync +``` + +This command imports the product classification structure from [[= pim_product_name =]] PIM into [[= product_name =]], ensuring that product categories are aligned. + +!!! tip + + To keep the classifications aligned, we recommend running the `ibexa:quable:classification:sync` command every night, even when using synchronization with webhooks. + +## Set up real-time synchronization + +[[= pim_product_name =]] PIM can notify [[= product_name =]] about product data and classification changes in real-time by using webhooks. +This invalidates the cache kept in [[= product_name =]], ensuring that product information stays up to date. + +Webhook configuration must be set up in both Quable PIM and [[= product_name =]]. + +### Create webhook in [[= pim_product_name =]] + +1. Create a new [webhook in Quable](https://docs.quable.com/v5-EN/docs/webhook). +2. Set the webhook code (used as the webhook name). +3. Provide the URL to your [[= product_name =]] instance suffixed by `/webhook/quable`, for example: `https://example.com/webhook/quable`. +4. Mark it as **Activated**. +5. Enter a secret value for the **Authorization Header**. +6. Choose the following scopes: + + - Products: created, updated, deleted + - Classifications: created, updated, deleted + +The **Authorization Header** value is a [secret that must be kept secure](security_checklist.md#app_secret-and-other-secrets). + +!!! note + + For local development and testing, you can consider using one of the available [tunnel providers](https://github.com/anderspitman/awesome-tunneling) to make your local instance accessible from the internet. + +### Configure webhook in [[= product_name =]] + +In `config/packages/ibexa_connector_quable.yaml`, specify the configuration for the [[= pim_product_name =]] connector: + +``` yaml +ibexa_connector_quable: + + # ... + webhook_secret: '' +``` + +!!! warning + + [Quable uses dynamic IP addresses](https://faq.quable.com/en/articles/8250056-what-are-the-ip-addresses-of-quable-to-add-to-the-whitelist) to connect to [[= product_name =]]. + If your DXP instance is protected by a firewall, make sure your configuration allows connections from changing IP addresses. + +### Configure background task + +[[= product_name =]]'s webhook processes Quable's classification change events and queues them to be processed in the background. + +To process them, [configure Ibexa Messenger](background_tasks.md) and make sure the `messenger:consume` command is run periodically. diff --git a/docs/product_catalog/quable/quable.md b/docs/product_catalog/quable/quable.md new file mode 100644 index 0000000000..84bf0051ad --- /dev/null +++ b/docs/product_catalog/quable/quable.md @@ -0,0 +1,33 @@ +--- +description: Quable PIM integration with Ibexa DXP +page_type: landing_page +month_change: true +--- + +# Quable PIM Integration + +[[= product_name =]] integrates with [[[= pim_product_name =]]](https://www.quable.com/en) to provide product information management as part of the [[= product_name_base =]] orchestration platform. + +[[= pim_product_name =]] is [[= product_name_base =]]’s PIM solution for managing complex product catalogs and serves as the single source of truth, available as an add-on for [[= product_name =]]. +Once you install and configure it, the integration performs an initial synchronization of product data, followed by ongoing updates via webhooks. +Products can be viewed, selected, and embedded in [[= product_name =]], while all product management operations remain handled in [[= pim_product_name =]]. + +## Getting started + +[[= cards([ + "product_catalog/quable/quable_guide", + ("https://doc.ibexa.co/projects/userguide/en/5.0/product_catalog/quable_pim_integration/"), + ("https://quable.com/en", "Quable - PIM solution for product data management", "Manage your product data and accelerate sales with Quable. Discover the new PIM platform that revolutionizes the product experience"), + ("https://docs.quable.com/", "Quable resources", "Find all Quable PIM, DAM, and Portal resources: user guides, training content, product documentation, technical documentation, and the PIM API for developers."), +]) =]] + +## Development + +[[= cards([ + "product_catalog/quable/install_quable", + "product_catalog/quable/configure_quable_connector", + "product_catalog/quable/quable_api", + "templating/twig_function_reference/quable_twig_functions", + "product_catalog/customize_product_attribute_templates", + ("https://developers.quable.com/", "Quable technical documentation", "Explore Quable's technical documentation"), +]) =]] diff --git a/docs/product_catalog/quable/quable_api.md b/docs/product_catalog/quable/quable_api.md new file mode 100644 index 0000000000..41e6ff5120 --- /dev/null +++ b/docs/product_catalog/quable/quable_api.md @@ -0,0 +1,76 @@ +--- +description: Learn how to use PHP and REST APIs to retrieve product data from Quable +month_change: true +--- + + +# Quable API + +As [[= pim_product_name =]] products are represented as [[= product_name =]] products, you can use the existing [Product APIs](product_api.md) to retrieve the product information. + +[[= pim_product_name =]] is the source of truth about products and categories and you should only use the [[= product_name =]] APIs to read the information coming from [[= pim_product_name =]], but you can't use them to modify it. +To modify the information, use the [[[= pim_product_name =]] interface](https://quable.com) or the dedicated [[[= pim_product_name =]] APIs](https://developers.quable.com/quable-api/). + +## REST API Usage + +To learn how to work with [[= product_name =]] REST API, see [REST API reference](rest_api_usage.md). + +You can use the following endpoints to retrieve product and category information: + +- [Product REST API](/api/rest_api/rest_api_reference/rest_api_reference.html#tag/Product) +- [Taxonomy REST API](/api/rest_api/rest_api_reference/rest_api_reference.html#tag/Taxonomy) + +## PHP API Usage + +### Retrieve products + +To retrieve product information coming from [[= pim_product_name =]], use the same APIs as described in [Product API](product_api.md). + +The following example shows how you can retrieve a single product: + +``` php +[[= include_file('code_samples/api/product_catalog/src/Command/ProductCommand.php', 54, 57, remove_indent=True) =]] +``` + +### Search for products + +Use [`ProductQuery`](product_api.md#getting-product-information) to search for mulitple products: + +``` php +[[= include_file('code_samples/api/product_catalog/src/Command/ProductCommand.php', 58, 68, remove_indent=True) =]] +``` + +When working with [[= pim_product_name =]] products, the following search criteria are supported: + +|Search Criterion|Search based on| +|-----|-----| +|[CreatedAt](createdat_criterion.md)|Date and time when product was created| +|[LogicalAnd](logicaland_criterion.md)|Composite criterion combining multiple criteria with AND| +|[MatchAll](matchall_criterion.md)|All products| +|[ProductCategory](productcategory_criterion.md)|Product category assigned to product| +|[ProductCategorySubtree](productcategorysubtree_criterion.md)|Product category subtree| +|[ProductCode](productcode_criterion.md)|Product's code| +|[ProductName](productname_criterion.md)|Product's name| +|[ProductType](producttype_criterion.md)|Product type| +|[UpdatedAt](updated_at_criterion.md)|Date and time when product was last updated| + +The following sort clauses are supported: + +|Sort Clause|Sorting based on| +|-----|-----| +|[CreatedAt](createdat_sort_clause.md)|Date and time of the creation of a product| +|[ProductCode](productcode_sort_clause.md)|Product's code| +|[ProductName](productname_sort_clause.md)|Product's name| + +### Manage stock and pricing + +For information stored outside of [[= pim_product_name =]], such as [product availability](product_api.md#product-availability) or [pricing](price_api.md), you can use the existing services to manage them: + +``` php hl_lines="6 14" +// Manage availability +[[= include_file('code_samples/api/product_catalog/src/Command/ProductCommand.php', 84, 89, remove_indent=True) =]] +// Manage prices +[[= include_file('code_samples/api/product_catalog/src/Command/ProductPriceCommand.php', 69, 75, remove_indent=True) =]] +``` + +For advanced pricing strategies, use the [Discounts API](discounts_api.md) to specify prices for [[= pim_product_name =]]'s products. diff --git a/docs/product_catalog/quable/quable_guide.md b/docs/product_catalog/quable/quable_guide.md new file mode 100644 index 0000000000..5e8feba800 --- /dev/null +++ b/docs/product_catalog/quable/quable_guide.md @@ -0,0 +1,71 @@ +--- +description: The Quable product guide describes how you can use the product data from Quable in Ibexa DXP to create marketing campaigns built around your products. +month_change: true +--- + +# Quable product guide + +## Overview + +[[= pim_product_name =]] integration connects [[= product_name =]] with [[[= pim_product_name =]] Product Information Management (PIM)](https://www.quable.com/en), making [[= pim_product_name =]] the authoritative source of product information for every website powered by [[= product_name =]]. + +[[= pim_product_name =]] serves as the single source of truth for all product data, including attributes, classifications, variants, and translations. +[[= product_name =]] consumes this data and makes it available for use in content and digital experiences. + +This approach eliminates the need to manage product data in multiple systems, while preserving a clear separation of responsibilities between product management and content usage. + +## Availability + +The integration with [[= pim_product_name =]] PIM is available as an add-on for all [[= product_name =]] editions, starting with [[= product_name =]] v5.0.7. + +Before installing and enabling the add-on, ensure that you have an active [[= pim_product_name =]] PIM instance with defined products, classifications, and channels. + +Then, [perform the initial configuration](install_quable.md). + +## How does [[= pim_product_name =]] integration work + +The integration is built on [[= product_name =]]'s [Remote PIM framework](add_remote_pim_support.md), which enables connection to external product data sources. + +Once configured, the system performs: + +- an initial synchronization of product data from Quable +- ongoing updates via webhooks (near real-time) + +Product data is mapped to the [[= product_name =]]'s product data model, including variants, attributes and [product categorties](product_catalog_guide.md#product-taxonomy). + +This data is then available in the back office, content editing tools like [Online Editor](online_editor_guide.md) and [Page Builder](page_builder_guide.md), and APIs. + +All product management operations remain handled in [[= pim_product_name =]]. + +[[= product_name =]] can be used to manage pricing and availability for products sourced from [[= pim_product_name =]], including support for market-specific configurations such as regions and currencies. + +## Capabilities + +### Single source of truth + +[[= pim_product_name =]] is the authoritative system for product data, including attributes, classifications, variants, and translations. + + +[[= product_name =]] consumes this data and makes it available for use within content and back office interfaces, enabling editorial teams to enrich content by reusing product information. + +## Use cases + +### Multi-market operations + +A retailer operating across multiple markets can manage product data in [[= pim_product_name =]] using channels and localized languages. +[[= product_name =]] connects to the relevant channel and makes localized product information available for use in content and back office interfaces, ensuring consistency across markets from a single [[= pim_product_name =]] instance. + +## Faster campaign execution + +Product data defined in [[= pim_product_name =]] can be immediately used in [[= product_name =]] for building content and campaigns. +Marketing teams can create pages and enrich content using up-to-date product information, without the need to duplicate or manually synchronize data. + +## Known limitations + +The integration with [[= pim_product_name =]] has the following known limitations: + +- It's not compatible with [Commerce](commerce.md) functionalities. [Carts](cart.md), [order management](order_management.md), and [shopping lists](shopping_list.md) can't be used with products coming from [[= pim_product_name =]]. +- [Catalogs](product_catalog_guide.md#catalogs) can't be created from [[= pim_product_name =]] products. +- [Product assets](product_catalog_guide.md#product-assets) are not fully synchronized. Only the main product thumbnail from [[= pim_product_name =]] is used. +- [Product-level access restrictions](policies.md#products) based on product type are not supported. +- You can't define prices and availability for products with product codes exceeding 64 characters. diff --git a/docs/product_guides/product_guides.md b/docs/product_guides/product_guides.md index 1c2359f5b2..0a0072b99f 100644 --- a/docs/product_guides/product_guides.md +++ b/docs/product_guides/product_guides.md @@ -19,8 +19,10 @@ Discover the primary ones with the help of product guides. Condensed content all "content_management/collaborative_editing/collaborative_editing_guide", "customer_management/customer_portal", "personalization/personalization_guide", - "pim/pim_guide", + "product_catalog/product_catalog_guide", + "product_catalog/quable/quable_guide", "commerce/shopping_list/shopping_list_guide", "ibexa_cloud/ibexa_cloud_guide", "cdp/cdp_guide", + "recommendations/raptor_integration/raptor_connector_guide", ], columns=4) =]] diff --git a/docs/recommendations/raptor_integration/connector_installation_configuration.md b/docs/recommendations/raptor_integration/connector_installation_configuration.md new file mode 100644 index 0000000000..dfc2645400 --- /dev/null +++ b/docs/recommendations/raptor_integration/connector_installation_configuration.md @@ -0,0 +1,78 @@ +--- +description: To configure the Raptor integration, follow the step-by-step procedure described below. +month_change: true +--- + +# Configuration procedure + +To configure the [Raptor](https://www.raptorservices.com/) integration add-on, follow the step-by-step procedure below. + +## Install Raptor connector + +Before you can proceed to configuring the integration with Raptor, install the Raptor connector. +To do it, run the following command: + +``` bash +composer require ibexa/connector-raptor +``` + +!!! note + + The [Ibexa Messenger](background_tasks.md) package is installed automatically as a dependency, but must be configured to enable server-side tracking. + See the Ibexa Messenger documentation for [configuration](background_tasks.md#configure-package) details. + +## SiteAccess-aware configuration + +To configure the Raptor connector, use the `ibexa.system..connector_raptor` configuration key in the `config/packages/ibexa_connector_raptor.yaml` file: + +``` yaml +[[= include_file('code_samples/recommendations/config/packages/ibexa_connector_raptor.yaml', 0, 13) =]] +``` + +- `enabled` - enables or disables the connector for a given scope. Default value: `true`. If set to `false`, no tracking or recommendation requests are executed. +- `customer_id` - an identifier used to authenticate requests to the recommendation engine. You can find this value as ["Account number"](connector_installation_configuration.md#customer-id) in Raptor Control Panel. +- `tracking_type` - defines how user events are sent to the tracking API. Default value: `client`. Possible values: + - `client` - tracking is executed in the browser using JavaScript snippets generated by the [Twig functions](recommendations_twig_functions.md) and included in the templates. This approach may be blocked by ad blockers. + - `server` - tracking is handled on the backend, with events sent directly to the tracking API. It's not affected by ad blockers. +- `recommendations_api_key` - an API key used to authenticate requests to the Recommendations API. This key allows the connector to retrieve personalized recommendations from the recommendation engine. You can find this value as ["API key"](connector_installation_configuration.md#recommendations-api-key) in Raptor Control Panel. +- `recommendations_api_url` (optional) - overrides the default Raptor address, do not set it unless a custom endpoint is required. + +By default, `tracking_type` is set to `client` as client-side tracking is the standard Raptor mode. +To understand the differences between client and server tracking types, including their advantages and disadvantages, refer to the [Raptor documentation](https://content.raptorservices.com/help-center/client-side-vs.-server-side-tracking). + +!!! note + + Only one tracking mode can be enabled at a time. + Client-side and server-side tracking cannot be used together. + +### Customer ID + +To find the value for the `customer_id` identifier, log in to Raptor Control Panel, and look for "Account number": + +A. In the top-left corner, above the account name, you can find the account number for the currently active account. +B. Click the arrow icon in the top-left corner to expand the window. There you can see a list of all your accounts, with their numbers shown in the “Account number” column on the right. This way, if you have multiple accounts, you can locate and copy the number of any of your accounts, not just the active one. + +![Account number](account_number.png) + +### Recommendations API key + +To find the value for the `recommendations_api_key`, log in to Raptor Control Panel, and look for "API key". +To do it, in the left panel, open the **Recommendations** section, and select **Website**. +Next, click on the Web module you’re interested in. +In the top-right corner, click the three-dot icon and select **API information**. +A new window appears, where you can find the "API key" value. +Click **Show API information** and copy the value. + +![API key](api_key.png) + +## Global configuration (non-SiteAccess-aware) + +The following settings are global and apply to the entire application (they are not scoped per SiteAccess): + +- `strict_exceptions` – when enabled, tracking exceptions are thrown instead of being silently handled. Default value: `%kernel.debug%`. + +This value can be overridden in `config/packages/ibexa_connector_raptor.yaml` file, for example: + +``` yaml hl_lines="14-17" +[[= include_file('code_samples/recommendations/config/packages/ibexa_connector_raptor.yaml') =]] +``` diff --git a/docs/recommendations/raptor_integration/custom_recommendation_rendering.md b/docs/recommendations/raptor_integration/custom_recommendation_rendering.md new file mode 100644 index 0000000000..0aca28d0e6 --- /dev/null +++ b/docs/recommendations/raptor_integration/custom_recommendation_rendering.md @@ -0,0 +1,78 @@ +--- +description: Use existing controllers to render recommendations outside the Page Builder. +month_change: true +--- + +# Custom recommendation rendering + +You can use existing controllers to render [recommendations](recommendation_blocks.md) outside the Page Builder. +The controllers responsible for rendering block recommendations on the front-end are independent and can be used to render recommendations for specific strategies. + +Each controller can be used to retrieve and display recommendations within a Twig template as follows: + +``` html+twig +{{ render(controller('', { + 'limit': limit, + 'template': '@ibexadesign/.html.twig', + '': parameter_value +})) }} +``` + +The controllers are placed in the `Ibexa\Bundle\ConnectorRaptor\Controller\Block` namespace. + +Each controller always requires these two parameters: + +- **limit** – the number of recommendations to render +- **template** – the path to the template + +Any other required parameters are specific to each controller and are detailed in the **Parameters** column of the table below: + +|Block name| Controller |Parameters|Recommendation item type| +|----------|---------------------------------------------------------------------------------------------|----------|------------------------| +|[Content that have been seen along with the item category]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#content-that-have-been-seen-along-with-the-item-category-block)| `ContentBasedOnProductCategoryBlockController`
`::showAction()` |`categoryId` (integer),
`limit` (integer),
`template` (string)|Content| +|[Most popular content]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#most-popular-content-block)| `PopularContentBlockController`
`::showAction()` |`limit` (integer),
`template` (string)|Content| +|[Most popular products]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#most-popular-products-block)| `PopularItemsBlockController`
`::showAction()` |`showInStock` (boolean),
`limit` (integer),
`template` (string)|Product| +|[Most popular products in category]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#most-popular-products-in-category-block)| `PopularItemsInCategoryBlockController`
`::showAction()` |`categoryId` (integer),
`showInStock` (boolean),
`limit` (integer),
`template` (string)|Product| +|[Other customers have also seen]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#other-customers-have-also-seen-block)| `SimilarItemsBlockController`
`::showAction()` |`productCode` (string),
`showInStock` (boolean),
`limit` (integer),
`template` (string)|Product| +|[Other customers have also seen this content]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#other-customers-have-also-seen-this-content-block)| `SimilarContentBlockController`
`::showAction()` |`contentId` (integer),
`limit` (integer),
`template` (string)|Content| +|[Other Customers Have also Purchased block]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#other-customers-have-also-purchased-block)| `OtherCustomersAlsoPurchasedBlockController`
`::showAction()` |`productCode` (string),
`limit` (integer),
`template` (string)|Product| +|[Personalized content recommendations]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#personalized-content-recommendations-block)| `UserContentRecommendationsBlockController`
`::showAction()` |`limit` (integer),
`template` (string)|Content| +|[The Personal Shopping Assistant]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#the-personal-shopping-assistant-block)| `UserItemRecommendationsBlockController`
`::showAction()` |`productCode` (string),
`showInStock` (boolean),
`limit` (integer),
`template` (string)|Product| +|[User's item history]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#users-item-history-block)| `UserItemHistoryBlockController`
`::showAction()` |`showInStock` (boolean),
`limit` (integer),
`template` (string)|Product| + +Each template receives a `recommendations` Twig variable, which is a list with either [`Ibexa\Contracts\ProductCatalog\Values\ProductInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-ProductInterface.html) instances for product recommendations or [`Ibexa\Contracts\Core\Repository\Values\Content\Content`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Content.html) instances for content recommendations. + +Two generic templates are provided and can be used in `./templates/themes/` directory: + +- `@ibexadesign/ibexa/recommendations/_content_list.html.twig` for content items: + +``` html+twig +{% if recommendations is not empty %} + {% for content in recommendations %} + {% set location = content.contentInfo.mainLocation %} + {% if location %} +

{{ ibexa_content_name(content) }}

+ {% else %} +

{{ ibexa_content_name(content) }}

+ {% endif %} + {% endfor %} +{% endif %} +``` + +- `@ibexadesign/ibexa/recommendations/_product_list.html.twig` for products: + +``` html+twig +{% if recommendations is not empty %} + +{% endif %} +``` + +To fetch recommendations for the remaining modules, you need to [create a custom controller](controllers.md) and use a method from [`Ibexa\Contracts\ConnectorRaptor\Recommendations\RecommendationsServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorRaptor-Recommendations-RecommendationsServiceInterface.html). + +Use this method to display recommendations on any page, for example, on a specific product page, as shown below: + +![Custom rendering](custom_rendering.png) diff --git a/docs/recommendations/raptor_integration/img/account_number.png b/docs/recommendations/raptor_integration/img/account_number.png new file mode 100644 index 0000000000..b6d2cd5f86 Binary files /dev/null and b/docs/recommendations/raptor_integration/img/account_number.png differ diff --git a/docs/recommendations/raptor_integration/img/advanced_settings.png b/docs/recommendations/raptor_integration/img/advanced_settings.png new file mode 100644 index 0000000000..d63a18e4d1 Binary files /dev/null and b/docs/recommendations/raptor_integration/img/advanced_settings.png differ diff --git a/docs/recommendations/raptor_integration/img/api_key.png b/docs/recommendations/raptor_integration/img/api_key.png new file mode 100644 index 0000000000..a133d98265 Binary files /dev/null and b/docs/recommendations/raptor_integration/img/api_key.png differ diff --git a/docs/recommendations/raptor_integration/img/custom_rendering.png b/docs/recommendations/raptor_integration/img/custom_rendering.png new file mode 100644 index 0000000000..e7649cde21 Binary files /dev/null and b/docs/recommendations/raptor_integration/img/custom_rendering.png differ diff --git a/docs/recommendations/raptor_integration/img/raptor_module.png b/docs/recommendations/raptor_integration/img/raptor_module.png new file mode 100644 index 0000000000..0cddfb73d5 Binary files /dev/null and b/docs/recommendations/raptor_integration/img/raptor_module.png differ diff --git a/docs/recommendations/raptor_integration/img/recommendation_blocks.png b/docs/recommendations/raptor_integration/img/recommendation_blocks.png new file mode 100644 index 0000000000..db8ef552de Binary files /dev/null and b/docs/recommendations/raptor_integration/img/recommendation_blocks.png differ diff --git a/docs/recommendations/raptor_integration/raptor_connector.md b/docs/recommendations/raptor_integration/raptor_connector.md new file mode 100644 index 0000000000..34251bfcf5 --- /dev/null +++ b/docs/recommendations/raptor_integration/raptor_connector.md @@ -0,0 +1,35 @@ +--- +description: Step-by-step activation procedure of setting up the Raptor connector. +page_type: landing_page +month_change: true +--- + +# Raptor connector + +The [Raptor](https://www.raptorservices.com/) connector is an add-on that provides a seamless integration between [[= product_name =]] and Raptor recommendation engine. + +Its primary goal is to enable editors and managers to deliver personalized experiences across digital channels, which helps increase conversion rates, drive sales, and improve user engagement. + +By combining content management capabilities with advanced recommendation features, the connector allows teams to build and manage personalized experiences across integrated tools. + +The connector ensures a smooth and unified integration layer, enabling: + +- event tracking through the tracking API +- personalized delivery of content and product recommendations through the Recommendations API +- flexible, SiteAccess-aware configuration + +This approach reduces integration complexity while providing a scalable foundation for personalization use cases across multiple sites and markets. + +To configure the integration with Raptor, follow a step-by-step procedure that allows you to activate the Raptor connector. +Activation includes [configuration](connector_installation_configuration.md), adding tracking scripts and events, and using [Page Builder](page_builder_guide.md) blocks. + +For more information about tracking, check the Raptor documentation: [Implementing tracking](https://content.raptorservices.com/help-center/data-management#implementing-tracking). + +[[= cards([ + "recommendations/raptor_integration/connector_installation_configuration", + "recommendations/raptor_integration/tracking_functions", + "recommendations/raptor_integration/tracking_php_api", + "recommendations/raptor_integration/recommendation_blocks", + "recommendations/raptor_integration/custom_recommendation_rendering", + "templating/twig_function_reference/recommendations_twig_functions", +], columns=3) =]] diff --git a/docs/recommendations/raptor_integration/raptor_connector_guide.md b/docs/recommendations/raptor_integration/raptor_connector_guide.md new file mode 100644 index 0000000000..6557343f25 --- /dev/null +++ b/docs/recommendations/raptor_integration/raptor_connector_guide.md @@ -0,0 +1,125 @@ +--- +description: Discover Raptor integration - an add-on focused on recommendations and tracking customer behaviors. +month_change: true +--- + +# Raptor integration guide + +Discover [Raptor](https://www.raptorservices.com/) integration - an add-on that is focused on recommendations and tracking customer behaviors. +It includes Raptor connector with tracking scripts and events, used to track and analyze customer behaviors, and a set of Recommendation blocks. + +## What is Raptor connector + +The [Raptor connector](raptor_connector.md) provides a seamless integration between [[= product_name =]] and Raptor recommendation engine. + +Its primary goal is to enable editors and managers to deliver personalized experiences across digital channels, which helps to increase conversion rates, drive sales, and improve user engagement. + +By bringing content and recommendations together, the connector makes it easy to build and manage personalized experiences. + +It provides a seamless integration layer that supports: + +- event tracking of user interactions through the Tracking API +- personalized delivery of content and product recommendations through the Recommendations API +- flexible SiteAccess-aware configuration adapted to different sites and contexts + +This approach simplifies integration while supporting personalization across different sites and markets. + +## Availability + +Raptor integration elements, such as tracking, Twig functions, and public API, are available in all supported [[= product_name =]] editions starting from v5.0.7 version. + +Recommendation blocks provided in Page Builder, are available in [[= product_name_exp =]] and [[= product_name_com =]] editions. + +## How does Raptor tracking work + +To start [tracking](https://content.raptorservices.com/help-center/introduction-to-tracking-documentation) user interactions, the tracking script needs to be added to the website’s layout. +Tracking can be set up either on the client-side or server-side, depending on how you want to capture and process the events. + +The tracking works differently depending on the mode you choose. +In server-side mode, tracking happens on the server, handling all events without loading scripts in the browser. +In client-side mode, it inserts script tags so tracking runs directly in the browser. + +You can switch between server and client tracking at any time by changing the tracking type to fit your setup and needs. + +## Capabilities + +### Tracking + +Raptor [tracking functions](tracking_functions.md) allow you to collect data about how users interact with your products and content. + +You can track product visits to better understand what users are viewing. +Provided [Twig functions](../../templating/twig_function_reference/recommendations_twig_functions.md) simplify the implementation, allowing developers to quickly add tracking to templates without complex setup. + +This gives you the data you need to better understand user behavior, improve recommendations, and support personalization. + +### Recommendation blocks + +The Raptor Integration add-on provides a set of ready-to-use recommendation blocks that can be added directly in the [Page Builder](page_builder_guide.md). + +These blocks can be configured to adjust how they work and what they display. +Content, Product, and Commerce recommendations can be placed on landing pages using these components. + +Editors can use these blocks to display tailored product recommendations, promote related content, and highlight items that are trending or recently viewed. + +Recommendation blocks are organized into dedicated categories, each grouping blocks based on the type of recommendation they provide: + +- **Recommendations: Content** - presents content recommendations: + - [Content that has been seen along with the item category]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#content-that-have-been-seen-along-with-the-item-category-block) + - [Most popular content]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#most-popular-content-block) + - [Other customers have also seen this content]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#other-customers-have-also-seen-this-content-block) + - [Personalized content recommendations]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#personalized-content-recommendations-block) +- **Recommendations: Product** - displays product suggestions based on visitors’ browsing history: + - [Most popular products]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#most-popular-products-block) + - [Most popular products in category]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#most-popular-products-in-category-block) + - [Other customers have also seen]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#other-customers-have-also-seen-block) +- **Recommendations: Commerce** - shows recommendations based on visitors' purchase history (buy and basket events): + - [Other customers have also purchased block]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#other-customers-have-also-purchased-block) + - [The Personal Shopping Assistant]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#the-personal-shopping-assistant-block) + - [User's item history]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#users-item-history-block) + +![Recommendation blocks](recommendation_blocks.png) + +For a complete description of Recommendation blocks see [Recommendation blocks in User Documentation]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/). + +### Advanced usage for complex tracking scenarios + +For more complex tracking requirements, [PHP API](tracking_php_api.md) provides direct access to the service. +It lets you track custom user actions, create more detailed tracking logic, and support scenarios not covered by the standard client- or server-side setups. + +## Benefits + +### Understand user behavior + +Thanks to tracking functions, you can capture how users interact with your products and content, giving you valuable insights into their behavior. +It helps you make data-driven decisions to improve engagement and personalize the user experience. + +### Highlight recommendations + +Use recommendation blocks on your websites to highlight content targeted at your customers. +Deliver relevant content and build trust in your brand. + +### Suggest content to boost retention + +Help users find content of their interest quicker. +Showing visitors content and products that match their interests helps keep them engaged and encourages them to come back. + +### Meet customer expectations and increase engagement + +Recommendation blocks highlight products that match customers' interests. +Tailored content boosts engagement by showing visitors information and products that align with their interests and fulfill their needs. +This strengthens the connection between your brand and your audience, encouraging them to spend more time on your site and return more often. + +### Increase average order value + +Use tracking for predictive analysis and find out what motivates users to put extra items into their carts. +Start building predictions of their behaviors and suggest products your visitors are willing to buy. + +### Track performance and increase conversions + +Use the Raptor service in your Commerce shop and see how recommendations drive sales. +Keep track of which recommendations are shown to visitors and measure conversion rates to evaluate their effectiveness against your goals. + +### Flexible tracking with PHP API + +Tracking using PHP API gives you full control over how events are recorded and processed. +You can use it for complex scenarios, so tracking can be adapted to your specific needs or business requirements. diff --git a/docs/recommendations/raptor_integration/recommendation_blocks.md b/docs/recommendations/raptor_integration/recommendation_blocks.md new file mode 100644 index 0000000000..76a13e2f8a --- /dev/null +++ b/docs/recommendations/raptor_integration/recommendation_blocks.md @@ -0,0 +1,43 @@ +--- +description: Recommendation blocks in Page Builder +edition: experience +month_change: true +--- + +# Recommendation blocks in Page Builder + +One of the Raptor Integration elements is the introduction of recommendation blocks available in the [Page Builder](page_builder_guide.md). + +Content, Product, and Commerce recommendations can be added to a landing page using the blocks. + +Editors can configure these blocks to display: + +- personalized product recommendations +- related articles or content +- recently viewed or popular items + +In the toolbar, corresponding categories for recommendation blocks are available, containing sets of blocks depending on the recommendation type: + +- **Recommendations: Content** - presents content recommendations: + - [Content that has been seen along with the item category]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#content-that-has-been-seen-along-with-the-item-category-block) + - [Most popular content]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#most-popular-content-block) + - [Other customers have also seen this content]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#other-customers-have-also-seen-this-content-block) + - [Personalized content recommendations]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#personalized-content-recommendations-block) +- **Recommendations: Product** - displays product suggestions based on visitors’ browsing history: + - [Most popular products]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#most-popular-products-block) + - [Most popular products in category]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#most-popular-products-in-category-block) + - [Other customers have also seen]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#other-customers-have-also-seen-block) +- **Recommendations: Commerce** - shows recommendations based on visitors' purchase history (buy and basket events): + - [Other customers have also purchased block]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#other-customers-have-also-purchased-block) + - [The Personal Shopping Assistant]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#the-personal-shopping-assistant-block) + - [User's item history]([[= user_doc =]]/personalization/raptor_integration/raptor_recommendation_blocks/#users-item-history-block) + +![Recommendation blocks](img/recommendation_blocks.png) + +After opening the settings of a recommendation block, a link is available at the bottom of the window. +It leads to the [Raptor Control Panel](https://controlpanel.raptorsmartadvisor.com/) (opens in a separate tab), where you can configure advanced settings and fine-tune the recommendation strategy. + +![Advanced settings](img/advanced_settings.png) + +For a complete description of Recommendation blocks see [Recommendation blocks]([[= user_doc =]]/recommendations/raptor_integration/raptor_recommendation_blocks/). +For the list of all page blocks that are available in Page Builder, see [Block reference page]([[= user_doc =]]/content_management/block_reference/). diff --git a/docs/recommendations/raptor_integration/tracking_functions.md b/docs/recommendations/raptor_integration/tracking_functions.md new file mode 100644 index 0000000000..70ac6a4a61 --- /dev/null +++ b/docs/recommendations/raptor_integration/tracking_functions.md @@ -0,0 +1,94 @@ +--- +description: Integrate the tracking script to collect user interactions. +month_change: true +--- + +# Raptor tracking functions + +[Raptor connector](raptor_connector.md) introduces [visit tracking functionality](https://content.raptorservices.com/help-center/introduction-to-tracking-documentation) for collecting user interactions with products and content. +The implementation includes product visit tracking with mapping to tracking parameters, and Twig functions for straightforward integration. + +Raptor integration introduces two Twig functions: + +- [`ibexa_tracking_script()`](../../templating/twig_function_reference/recommendations_twig_functions.md#ibexa_tracking_script-function) - allows you to embed main tracking script into the website. +- [`ibexa_tracking_track_event()`](../../templating/twig_function_reference/recommendations_twig_functions.md#ibexa_tracking_track_event-function) - is responsible for sending event data to the service, enabling tracking of user interactions and behaviors. + +## Embed tracking script + +You must embed the tracking script into the website’s layout to enable tracking. +To do it, add the `ibexa_tracking_script()` Twig function into the section of your base layout template, for example, `@ibexadesign/pagelayout.html.twig`: + +``` html+twig +[[= include_file('code_samples/recommendations/templates/themes/standard/pagelayout.html.twig') =]] +``` + +## Tracking modes + +Tracking user interactions can be implemented on the client-side or the server-side. +Each approach differs in where events are captured and how they are sent to the tracking backend. + +The [tracking Twig function](#embed-tracking-script) outputs different content depending on the mode: + +``` yaml +# Server-side tracking +connector_raptor: + tracking_type: 'server' # Returns nothing (prod) or HTML comments (dev) + +# Client-side tracking +connector_raptor: + tracking_type: 'client' # Returns