Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix utm #327

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 33 additions & 14 deletions docs/subscriptions/observable-events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,40 @@ title: Observable Events
nav_label: Observable Events
sidebar_position: 100
---
You can integrate Subscriptions with external systems like enterprise resource planning, fulfilment and other systems. For example, when a subscriber updates their address, the Customer Relationship Management system is updated with the change.

Events are actions that occur in Subscriptions, such as a subscriber changing their address or a subscription changing from active to inactive. You can create custom functions that perform additional processing outside of Subscriptions, and create integrations so that when an event occurs in your store, the custom function is run.
# Observable Events in Subscriptions

Events are processed concurrently. This means that events may not be delivered in the order they are created. For example, if a subscription is updated multiple times, the events may not be delivered in the same sequence they were updated. Events operate on an "at least once" delivery policy. We aim to deliver messages within 30 minutes or less. Ensure that you design your receiving code accordingly.
## Overview
Observable events allow you to integrate Subscriptions with external systems like ERP, fulfillment, and CRM platforms. When specific actions occur within Subscriptions (such as address updates or status changes), these events can trigger custom functions to perform additional processing or update external systems.

For more information about integrating Subscriptions, see [**Integration Types**](/docs/api/integrations/integrations-introduction#integration-types).
## Event Processing Behavior
- Events are processed concurrently and may not be delivered in chronological order
- Events follow an "at least once" delivery policy
- Target delivery time is within 30 minutes
- Integration code should be designed to handle out-of-order and duplicate events

| Resource | Action | Observable Key | Availability |
| --- | --- | --- | --- |
| Product | <ul><li>Created</li><li>Updated</li><li>Deleted</li></ul> | <ul><li>`subscription-product.created`</li><li>`subscription-product.updated`</li><li>`subscription-product.deleted`</li></ul> | Store |
| Plan | <ul><li>Created</li><li>Updated</li><li>Deleted</li></ul> | <ul><li>`subscription-plan.created`</li><li>`subscription-plan.updated`</li><li>`subscription-plan.deleted`</li></ul> | Store |
| Offering | <ul><li>Created</li><li>Updated</li><li>Deleted</li></ul> | <ul><li>`subscription-offering.created`</li><li>`subscription-offering.updated`</li><li>`subscription-offering.deleted`</li></ul> | Store |
| Subscription | <ul><li>Created</li><li>Create-failed</li><li>Paused</li><li>Canceled</li><li>Pending-cancel</li><li>Pending-pause</li><li>Resumed</li><li>Closed</li></ul> | <ul><li>`subscription.created`</li><li>`subscription.create-failed`</li><li>`subscription.canceled`</li><li>`subscription.paused`</li><li>`subscription.pending_cancel`</li><li>`subscription.pending_pause`</li><li>`subscription.resumed`</li><li>`subscription.closed`</li></ul> | Store |
| Job | <ul><li>Created</li><li>Updated</li><li>Deleted</li></ul> | <ul><li>`subscription-job.created`</li><li>`subscription-job.updated`</li><li>`subscription-job.deleted`</li></ul> | Store |
| Invoices | <ul><li>Created</li><li>Deleted</li></ul> | <ul><li>`subscription-invoice.created`</li><li>`subscription-offering.deleted`</li></ul> | Store |
| Schedule | <ul><li>Created</li><li>Updated</li><li>Deleted</li></ul> | <ul><li>`subscription-schedule.created`</li><li>`subscription-schedule.updated`</li><li>`subscription-schedule.deleted`</li></ul> | Store |
| Subscriber | <ul><li>Created</li><li>Updated</li><li>Deleted</li></ul> | <ul><li>`subscription-subscriber.created`</li><li>`subscription-subscriber.updated`</li><li>`subscription-subscriber.deleted`</li></ul> | Store |
For detailed information about integration options, see [**Integration Types**](/docs/api/integrations/integrations-introduction#integration-types).

## Available Events

### Subscription Management
| Resource | Actions | Observable Keys |
|----------|---------|-----------------|
| Subscription | • Created<br/>• Create-failed<br/>• Paused<br/>• Canceled<br/>• Pending-cancel<br/>• Pending-pause<br/>• Resumed<br/>• Closed | `subscription.created`<br/>`subscription.create-failed`<br/>`subscription.paused`<br/>`subscription.canceled`<br/>`subscription.pending_cancel`<br/>`subscription.pending_pause`<br/>`subscription.resumed`<br/>`subscription.closed` |
| Subscriber | • Created<br/>• Updated<br/>• Deleted | `subscription-subscriber.created`<br/>`subscription-subscriber.updated`<br/>`subscription-subscriber.deleted` |

### Product Configuration
| Resource | Actions | Observable Keys |
|----------|---------|-----------------|
| Product | • Created<br/>• Updated<br/>• Deleted | `subscription-product.created`<br/>`subscription-product.updated`<br/>`subscription-product.deleted` |
| Plan | • Created<br/>• Updated<br/>• Deleted | `subscription-plan.created`<br/>`subscription-plan.updated`<br/>`subscription-plan.deleted` |
| Offering | • Created<br/>• Updated<br/>• Deleted | `subscription-offering.created`<br/>`subscription-offering.updated`<br/>`subscription-offering.deleted` |

### Operations
| Resource | Actions | Observable Keys |
|----------|---------|-----------------|
| Job | • Created<br/>• Updated<br/>• Deleted | `subscription-job.created`<br/>`subscription-job.updated`<br/>`subscription-job.deleted` |
| Invoices | • Created<br/>• Deleted | `subscription-invoice.created`<br/>`subscription-invoice.deleted` |
| Schedule | • Created<br/>• Updated<br/>• Deleted | `subscription-schedule.created`<br/>`subscription-schedule.updated`<br/>`subscription-schedule.deleted` |

> **Note**: All events are available at the Store level.
26 changes: 14 additions & 12 deletions docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,6 @@ const config = {
googleTagManager: {
containerId: 'G-NZ3NL8DLLD',
},
googleTagManager: {
containerId: 'G-NZ3NL8DLLD',
},
}),
],
],
Expand Down Expand Up @@ -224,11 +221,13 @@ const config = {
{
label: "Guides",
to: "guides",
datautmcampaign: "guides",
},
{
label: "Docs",
type: "dropdown",
className: "nav-dropdown",
datautmcampaign: "docs",
items: [
{
type: "html",
Expand All @@ -252,10 +251,12 @@ const config = {
{
label: "Changelog",
to: "/changelog-landing",
datautmcampaign: "changelog",
},
{
label: "Support",
to: "https://support.elasticpath.com",
datautmcampaign: "support",
},
{
type: "search",
Expand All @@ -266,12 +267,14 @@ const config = {
href: "https://www.elasticpath.com/get-in-touch",
position: "right",
className: "navbar-book-demo",
datautmcampaign: "get-in-touch",
},
{
label: "Free Trial",
href: "https://useast.cm.elasticpath.com/free-trial",
position: "right",
className: "dev-portal-signup dev-portal-link",
datautmcampaign: "free-trial",
},
],
},
Expand Down Expand Up @@ -313,7 +316,7 @@ const config = {
},
{
label: "GitHub",
href: "https://github.com/facebook/docusaurus",
href: "https://github.com/elasticpath",
},
],
},
Expand Down Expand Up @@ -1329,7 +1332,7 @@ const config = {
{ to: '/docs/studio/Settings/Domain-Management/Connecting-your-Namecheap-Domain', from: '/docs/cx-studio/Settings/Domain-Management/Connecting-your-Namecheap-Domain'},
{ to: '/docs/api/pxm/catalog/get-catalog-by-id', from: '/docs/pxm/catalogs/catalog-configuration/get-all-catalogs'},
{ to: '/docs/api/carts/transactions', from: '/docs/commerce-cloud/payments/transactions/get-all-transactions'},
{ to: '/docs/api/pxm/catalog/get-by-context-all-nodes', from: '/docs/pxm/catalogs/shopper-catalog/get-a-hierarchys-nodes'},
{ to: '/docs/api/pxm/catalog/get-by-context-all-hierarchies', from: '/docs/pxm/catalogs/shopper-catalog/get-a-hierarchys-nodes'},
{ to: '/changelog/Studio-Release-Notes/Release-190-February-14-2024', from: '/docs/cx-studio/Release-Notes/Release-190-February-14-2024'},
{ to: '/changelog/Studio-Release-Notes/Release-190-February-14-2024', from: '/docs/cx-studio/Release-Notes/Release-191-February-27-2024'},
{ to: '/docs/api/pxm/products/build-child-products', from: '/docs/pxm/products/pxm-product-variations/child-products-api/build-child-products'},
Expand Down Expand Up @@ -1633,10 +1636,7 @@ const config = {
"@docusaurus/theme-live-codeblock",
[
require.resolve("@easyops-cn/docusaurus-search-local"),
/** @type {import("@easyops-cn/docusaurus-search-local").PluginOptions} */
({
// ... Your options.
// `hashed` is recommended as long-term-cache of index file is possible.
hashed: true,
indexDocs: true,
indexBlog: true,
Expand All @@ -1646,13 +1646,15 @@ const config = {
highlightSearchTermsOnTargetPage: false,
searchContextByPaths: ["docs","guides","changelog"],
useAllContextsWithNoSearchContext: true,
// For Docs using Chinese, The `language` is recommended to set to:
// ```
// language: ["en", "zh"],
// ```
}),
],
],
scripts: [
{
src: '/js/utm-handler.js',
async: true,
},
],
};

module.exports = config;
9 changes: 9 additions & 0 deletions src/snippets/resourceDOCS.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
onmouseover="document.body.setAttribute('docs-menu', 'cm')"
class="flex cursor-pointer !mt-2 items-start justify-start gap-2 border-none bg-transparent text-black dark:text-white"
href="/ui"
datautmcampaign="commerce-manager"
>
<div class="flex-shrink-0">
<img
Expand All @@ -62,6 +63,7 @@
onmouseover="document.body.setAttribute('docs-menu', 'pxm')"
class="flex cursor-pointer !mt-2 items-start justify-start gap-2 border-none bg-transparent text-black dark:text-white"
href="/pxm"
datautmcampaign="pxm"
>
<div class="flex-shrink-0">
<img
Expand All @@ -84,6 +86,7 @@
onmouseover="document.body.setAttribute('docs-menu', 'subs')"
class="flex cursor-pointer !mt-2 items-start justify-start gap-2 border-none bg-transparent text-black dark:text-white"
href="/subscriptions"
datautmcampaign="subscriptions"
>
<div class="flex-shrink-0">
<img
Expand All @@ -106,6 +109,7 @@
onmouseover="document.body.setAttribute('docs-menu', 'carts')"
class="flex cursor-pointer !mt-2 items-start justify-start gap-2 border-none bg-transparent text-black dark:text-white"
href="/orders"
datautmcampaign="carts"
>
<div class="flex-shrink-0">
<img
Expand Down Expand Up @@ -146,6 +150,7 @@
onmouseover="document.body.setAttribute('docs-menu', 'studio')"
class="flex cursor-pointer !mt-2 items-start justify-start gap-2 border-none bg-transparent text-black dark:text-white"
href="/docs/studio"
datautmcampaign="studio"
>
<div class="flex-shrink-0">
<img
Expand All @@ -168,6 +173,7 @@
onmouseover="document.body.setAttribute('docs-menu', 'composer')"
class="flex cursor-pointer !mt-2 items-start justify-start gap-2 border-none bg-transparent text-black dark:text-white"
href="/docs/composer"
datautmcampaign="composer"
>
<div class="flex-shrink-0">
<img
Expand All @@ -190,6 +196,7 @@
onmouseover="document.body.setAttribute('docs-menu', 'payments')"
class="flex cursor-pointer !mt-2 items-start justify-start gap-2 border-none bg-transparent text-black dark:text-white"
href="/docs/payments"
datautmcampaign="payments"
>
<div class="flex-shrink-0">
<img
Expand All @@ -212,6 +219,7 @@
onmouseover="document.body.setAttribute('docs-menu', 'developer')"
class="flex cursor-pointer !mt-2 items-start justify-start gap-2 border-none bg-transparent text-black dark:text-white"
href="/docs/developer-tools"
datautmcampaign="developer-tools"
>
<div class="flex-shrink-0">
<img
Expand All @@ -235,6 +243,7 @@
class="flex cursor-pointer !mt-4 items-start justify-start gap-2 border-none bg-transparent text-black dark:text-white"
href="https://documentation.elasticpath.com"
target="_blank"
datautmcampaign="self-managed"
>
<div class="flex-shrink-0">
<img
Expand Down
114 changes: 114 additions & 0 deletions static/js/utm-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Default UTM parameters
const DEFAULT_UTM = {
utm_source: 'elastic-path-dev',
utm_medium: 'dev-site',
utm_campaign: 'fy25q1-dev'
};

// Campaign mapping for different buttons
const CAMPAIGN_MAPPING = {
'support': 'fy25q1-dev-support',
'freetrial': 'fy25q1-dev-free-trial',
'docs': 'fy25q1-dev-documentation',
'get-in-touch': 'fy25q1-dev-get-in-touch',
'guides': 'fy25q1-dev-guides',
'videos': 'fy25q1-dev-videos',
'api': 'fy25q1-dev-api',
'sample-apps': 'fy25q1-dev-sample-apps',
'changelog': 'fy25q1-dev-changelog',
'commerce-manager': 'fy25q1-dev-commerce-manager',
'pxm': 'fy25q1-dev-pxm',
'subscriptions': 'fy25q1-dev-subscriptions',
'carts': 'fy25q1-dev-carts',
'studio': 'fy25q1-dev-studio',
'composer': 'fy25q1-dev-composer',
'payments': 'fy25q1-dev-payments',
'developer-tools': 'fy25q1-dev-developer-tools',
'self-managed': 'fy25q1-dev-self-managed',
// Add more campaign mappings as needed
};

// Get UTM params from URL if they exist
function getUrlUtmParams() {
const urlParams = new URLSearchParams(window.location.search);
const utmParams = {};

['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'].forEach(param => {
if (urlParams.has(param)) {
utmParams[param] = urlParams.get(param);
}
});

return utmParams;
}

// Store UTM params in sessionStorage
function storeUtmParams(params) {
sessionStorage.setItem('utmParams', JSON.stringify(params));
}

// Get stored UTM params
function getStoredUtmParams() {
const stored = sessionStorage.getItem('utmParams');
return stored ? JSON.parse(stored) : null;
}

// Add UTM params to a URL
function addUtmToUrl(url, campaignType) {
try {
const urlObj = new URL(url);

// Don't modify external URLs
if (!urlObj.hostname.includes('elasticpath.dev')) {
return url;
}

// Get stored or default UTM params
const utmParams = getStoredUtmParams() || {...DEFAULT_UTM};

// Override campaign if specified
if (campaignType && CAMPAIGN_MAPPING[campaignType]) {
utmParams.utm_campaign = CAMPAIGN_MAPPING[campaignType];
}

// Add UTM params to URL
Object.entries(utmParams).forEach(([key, value]) => {
urlObj.searchParams.set(key, value);
});

return urlObj.toString();
} catch (e) {
// Return original URL if invalid
return url;
}
}

// Initialize UTM handling
function initUtmHandler() {
// Store UTM params from URL if present
const urlUtmParams = getUrlUtmParams();
if (Object.keys(urlUtmParams).length > 0) {
storeUtmParams(urlUtmParams);
}

// Add click event listener to handle links
document.addEventListener('click', (e) => {
const link = e.target.closest('a');
if (link && link.href) {
// Get the campaign type from the data attribute
const campaignType = link.getAttribute('datautmcampaign');
const modifiedUrl = addUtmToUrl(link.href, campaignType);
if (modifiedUrl !== link.href) {
e.preventDefault();
window.location.href = modifiedUrl;
}
}
});
}

// Run when DOM is loaded
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initUtmHandler);
} else {
initUtmHandler();
}