Skip to content

Commit

Permalink
Support EU Cloud Region (#1134)
Browse files Browse the repository at this point in the history
Add a cloud region config option to the global_config to allow either 'us' (default), or 'eu' to be set as the cloud region.

The cloud region determines where the search assets and ytag are sourced from.

J=BACK-2277
TEST=manual, auto

Using the test site, set the cloudRegion to "eu" and confirmed the assets are loaded from the EU CDN and executed searches against the EU search endpoints
  • Loading branch information
cea2aj committed May 9, 2023
1 parent 17d560e commit eb9515b
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 25 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ static/node_modules/
static/dist/
node_modules
**/.DS_Store
.idea/
3 changes: 2 additions & 1 deletion global_config.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"sdkVersion": "1.15", // The version of the Answers SDK to use
"sdkVersion": "1.16", // The version of the Answers SDK to use
// "token": "<REPLACE ME>", // The auth token to access Answers experience.
// "apiKey": "<REPLACE ME>", // The answers api key found on the experiences page. This will be provided automatically by the Yext CI system
// "experienceVersion": "<REPLACE ME>", // the Answers Experience version to use for API requests. This will be provided automatically by the Yext CI system
// "environment": "production", // The environment to run on for this Answers Experience. (i.e. 'production' or 'sandbox')
// "cloudRegion": "us", // The cloud region to use for this Answers Experience. (i.e. 'us' or 'eu')
// "businessId": "<REPLACE ME>", // The business ID of the account. This will be provided automatically by the Yext CI system
// "initializeManually": true, // If true, the experience must be started by calling AnswersExperience.init() or AnswersExperienceFrame.init() for iframe integrations.
// "useJWT": true, // Whether or not to enable JWT. If true, the apiKey will be hidden from the build output and the token must be specified through manual initialization.
Expand Down
26 changes: 19 additions & 7 deletions hbshelpers/sdkAssetUrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,25 @@ const RELEASE_BRANCH_REGEX = /^release\/v[0-9.]+$/;
const HOTFIX_BRANCH_REGEX = /^hotfix\/v[0-9.]+$/;
const I18N_FEATURE_BRANCH_REGEX = /^feature\/.+-i18n$/;
const SEM_VER_REGEX = /^[1-9]+$|^[1-9]+\.[0-9]+$|^[1-9]+\.[0-9]+\.[0-9]+$/;
const US = 'us';
const EU = 'eu';

/**
* Given a branch (or release) of the SDK and a locale, this helper provides the correct
* URL in the CDN for the asset.
*
*
* @param {string} branch The branch (or release) of the SDK.
* @param {string} locale The locale to use.
* @param {string} assetName The name of the desired asset.
* @param {string} cloudRegion The cloud region to use.
* @returns {string} The CDN URL of the localized asset.
*/
module.exports = function sdkAssetUrl(branch, locale, assetName) {
module.exports = function sdkAssetUrl(
branch,
locale,
assetName,
cloudRegion = US
) {
const isReleasedBranch = SEM_VER_REGEX.test(branch);

let parsedBranch;
Expand All @@ -24,17 +32,21 @@ module.exports = function sdkAssetUrl(branch, locale, assetName) {
parsedBranch = `dev/${branch.replace(/\//g, '-')}`;
}

const isPreReleaseBranch =
const isPreReleaseBranch =
RELEASE_BRANCH_REGEX.test(branch) || HOTFIX_BRANCH_REGEX.test(branch);
const isI18nFeatureBranch = I18N_FEATURE_BRANCH_REGEX.test(branch);
const isDevelopBranch = branch === 'develop';
const isLocalizationSupported =
(isReleasedBranch || isPreReleaseBranch || isI18nFeatureBranch || isDevelopBranch) &&
const isLocalizationSupported =
(isReleasedBranch || isPreReleaseBranch || isI18nFeatureBranch || isDevelopBranch) &&
!(locale.startsWith('en') || assetName === 'answers.css') ;

const parsedAssetName = isLocalizationSupported ?
`${locale}-${assetName}` :
assetName;

return `https://assets.sitescdn.net/answers/${parsedBranch}/${parsedAssetName}`;
const domain = cloudRegion === EU
? 'assets.eu.sitescdn.net'
: 'assets.sitescdn.net';

return `https://${domain}/answers/${parsedBranch}/${parsedAssetName}`;
};
22 changes: 15 additions & 7 deletions layouts/html.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@
<link rel="dns-prefetch" href="//dynl.mktgcdn.com">
<link rel="dns-prefetch" href="//dynm.mktgcdn.com">
<link rel="dns-prefetch" href="//www.google-analytics.com">
<link rel="dns-prefetch" href="//assets.sitescdn.net">

{{#ifeq global_config.cloudRegion 'eu'}}
<link rel="dns-prefetch" href="//assets.eu.sitescdn.net">
{{else}}
<link rel="dns-prefetch" href="//assets.sitescdn.net">
{{/ifeq}}

{{> layouts/preload-fonts }}

<script>
Expand Down Expand Up @@ -115,23 +119,27 @@
{{/if}}

{{#if global_config.conversionTrackingEnabled}}
<script src="https://assets.sitescdn.net/ytag/ytag.min.js"></script>
{{#ifeq global_config.cloudRegion "eu"}}
<script src="https://assets.eu.sitescdn.net/ytag/ytag.min.js"></script>
{{else}}
<script src="https://assets.sitescdn.net/ytag/ytag.min.js"></script>
{{/ifeq}}
{{/if}}

<script>
{{#babel}}
function iframeGetSearchParams() {
const params = window.location.search.substr(1);
const verticalUrl = window.location.pathname.substr(1);
return verticalUrl
return verticalUrl
? params + '&verticalUrl=' + verticalUrl
: params;
}
let iframeLoadedResolve;
window.iframeLoaded = new Promise(resolve => {
iframeLoadedResolve = resolve;
});
window.iFrameResizer = {
onReady: function() {
window.parentIFrame.sendMessage(JSON.stringify({
Expand Down Expand Up @@ -164,9 +172,9 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.2.10/iframeResizer.contentWindow.min.js"></script>
<link rel="stylesheet" type="text/css"
{{#if (isRTL global_config.locale) }}
href="{{sdkAssetUrl global_config.sdkVersion 'en' 'answers.rtl.css'}}"
href="{{sdkAssetUrl global_config.sdkVersion 'en' 'answers.rtl.css' global_config.cloudRegion}}"
{{else}}
href="{{sdkAssetUrl global_config.sdkVersion 'en' 'answers.css'}}"
href="{{sdkAssetUrl global_config.sdkVersion 'en' 'answers.css' global_config.cloudRegion}}"
{{/if}}
>
<link rel="stylesheet" type="text/css"
Expand Down
5 changes: 3 additions & 2 deletions script/core.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
console.error('ERROR: no sdkVersion specified, please specify an sdkVersion in the global_config.');
}
</script>
<script src="{{sdkAssetUrl global_config.sdkVersion (findFirst params.sdkLocaleOverride global_config.locale 'en') 'answerstemplates.compiled.min.js'}}" defer></script>
<script src="{{sdkAssetUrl global_config.sdkVersion (findFirst params.sdkLocaleOverride global_config.locale 'en') 'answerstemplates.compiled.min.js' global_config.cloudRegion}}" defer></script>
<script>
{{#babel}}
function initAnswers() {
const JAMBO_INJECTED_DATA = {{{ json env.JAMBO_INJECTED_DATA }}} || {};
const IS_STAGING = HitchhikerJS.isStaging(JAMBO_INJECTED_DATA?.pages?.stagingDomains || []);
const injectedConfig = {
experienceVersion: IS_STAGING ? 'STAGING' : 'PRODUCTION',
{{#unless global_config.useJWT}}
{{#unless global_config.useJWT}}
apiKey: HitchhikerJS.getInjectedProp('{{{global_config.experienceKey}}}', ['apiKey']),
{{/unless}}
{{#with env.JAMBO_INJECTED_DATA}}
Expand Down Expand Up @@ -152,4 +152,5 @@
{{> script/partials/sdk-js-script-tags
locale=(findFirst params.sdkLocaleOverride global_config.locale 'en')
sdkVersion=global_config.sdkVersion
cloudRegion=global_config.cloudRegion
}}
7 changes: 4 additions & 3 deletions script/partials/sdk-js-script-tags.hbs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
{{!--
Returns the SDK js script tags needed by the page.
@param locale
@param locale
@param sdkVersion
@param cloudRegion
--}}
<script
src="{{sdkAssetUrl sdkVersion locale "answers-modern.min.js"}}"
src="{{sdkAssetUrl sdkVersion locale "answers-modern.min.js" cloudRegion}}"
type="module"
></script>
<script
src="{{sdkAssetUrl sdkVersion locale "answers.min.js"}}"
src="{{sdkAssetUrl sdkVersion locale "answers.min.js" cloudRegion}}"
nomodule
defer
></script>
1 change: 1 addition & 0 deletions test-site/config/global_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"apiKey": "2d8c550071a64ea23e263118a2b0680b", // The answers api key found on the experiences page. This will be provided automatically by the Yext CI system
// "experienceVersion": "<REPLACE ME>", // the Answers Experience version to use for API requests. This will be provided automatically by the Yext CI system
// "environment": "production", // The environment to run on for this Answers Experience. (i.e. 'production' or 'sandbox')
// "cloudRegion": "eu", // The cloud region to use for this Answers Experience. (i.e. 'us' or 'eu')
"businessId": "3350634", // The business ID of the account. This will be provided automatically by the Yext CI system
// "initializeManually": true, // If true, the experience must be started by calling AnswersExperience.init() or AnswersExperienceFrame.init() for iframe integrations.
// "useJWT": true, // Whether or not to enable JWT. If true, the apiKey will be hidden from the build and the token must be specified through the runtime config.
Expand Down
8 changes: 4 additions & 4 deletions tests/acceptance/constants.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
exports.PORT=9999;
exports.VERTICAL_SEARCH_URL_REGEX=/v2\/accounts\/me\/answers\/vertical\/query/;
exports.UNIVERSAL_SEARCH_URL_REGEX=/v2\/accounts\/me\/answers\/query/;
exports.UNIVERSAL_AUTOCOMPLETE_URL_REGEX=/v2\/accounts\/me\/answers\/autocomplete/;
exports.VERTICAL_AUTOCOMPLETE_URL_REGEX=/v2\/accounts\/me\/answers\/vertical\/autocomplete/;
exports.VERTICAL_SEARCH_URL_REGEX=/v2\/accounts\/me\/search\/vertical\/query/;
exports.UNIVERSAL_SEARCH_URL_REGEX=/v2\/accounts\/me\/search\/query/;
exports.UNIVERSAL_AUTOCOMPLETE_URL_REGEX=/v2\/accounts\/me\/search\/autocomplete/;
exports.VERTICAL_AUTOCOMPLETE_URL_REGEX=/v2\/accounts\/me\/search\/vertical\/autocomplete/;
18 changes: 17 additions & 1 deletion tests/hbshelpers/sdkAssetUrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@ describe('URLs are computed properly for released versions', () => {
expect(sdkAssetUrl('1.8', 'fr', 'answers.min.js')).toEqual(expectedJSUrl);
expect(sdkAssetUrl('1.8', 'fr', 'answers.css')).toEqual(expectedCSSUrl);
});

it('works correctly when locale is "en" and cloudRegion is "eu"', () => {
const expectedJSUrl = 'https://assets.eu.sitescdn.net/answers/v1.8/answers.min.js';
const expectedCSSUrl = 'https://assets.eu.sitescdn.net/answers/v1.8/answers.css'

expect(sdkAssetUrl('1.8', 'en', 'answers.min.js', 'eu')).toEqual(expectedJSUrl);
expect(sdkAssetUrl('1.8', 'en', 'answers.css', 'eu')).toEqual(expectedCSSUrl);
});

it('works correctly when locale is not "en" and cloudRegion is "eu"', () => {
const expectedJSUrl = 'https://assets.eu.sitescdn.net/answers/v1.8/fr-answers.min.js';
const expectedCSSUrl = 'https://assets.eu.sitescdn.net/answers/v1.8/answers.css'

expect(sdkAssetUrl('1.8', 'fr', 'answers.min.js', 'eu')).toEqual(expectedJSUrl);
expect(sdkAssetUrl('1.8', 'fr', 'answers.css', 'eu')).toEqual(expectedCSSUrl);
});
});

describe('URLs are computed properly for release branches', () => {
Expand Down Expand Up @@ -88,4 +104,4 @@ describe('URLs are computed properly for all other branches', () => {
expect(sdkAssetUrl('feature/foo', 'fr', 'answers.min.js')).toEqual(expectedJSUrl);
expect(sdkAssetUrl('feature/foo', 'fr', 'answers.css')).toEqual(expectedCSSUrl);
});
});
});
38 changes: 38 additions & 0 deletions tests/script/partials/sdk-js-script-tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@ const jaOutput = `<script
defer
></script>`;

const entOutputEu = `<script
src="https://assets.eu.sitescdn.net/answers/v1.8/answers-modern.min.js"
type="module"
></script>
<script
src="https://assets.eu.sitescdn.net/answers/v1.8/answers.min.js"
nomodule
defer
></script>`;

const jaOutputEu = `<script
src="https://assets.eu.sitescdn.net/answers/v1.8/ja-answers-modern.min.js"
type="module"
></script>
<script
src="https://assets.eu.sitescdn.net/answers/v1.8/ja-answers.min.js"
nomodule
defer
></script>`;

it('creates correct tags for en', () => {
const partialUsage = `{{> script/partials/sdk-js-script-tags
sdkVersion=1.8
Expand All @@ -35,3 +55,21 @@ it('creates correct tags for ja', () => {
}}`
expect(hbs.compile(partialUsage)()).toEqual(jaOutput);
});

it('creates correct tags for en in eu', () => {
const partialUsage = `{{> script/partials/sdk-js-script-tags
sdkVersion=1.8
locale="en"
cloudRegion="eu"
}}`
expect(hbs.compile(partialUsage)()).toEqual(entOutputEu);
});

it('creates correct tags for ja in eu', () => {
const partialUsage = `{{> script/partials/sdk-js-script-tags
sdkVersion=1.8
locale="ja"
cloudRegion="eu"
}}`
expect(hbs.compile(partialUsage)()).toEqual(jaOutputEu);
});

0 comments on commit eb9515b

Please sign in to comment.