- 1 Documentation & Reference
- 2 URLs for Integrating CMSs
- 3 Structure of a Template
- 4 Cases
- 5 Sitecore: https://optimere.atlassian.net/browse/MON-2701
- 6 Craft: https://optimere.atlassian.net/browse/SUPPORT-139
- 7 Drupal: https://optimere.atlassian.net/browse/MON-2105
- 8 Opencities - https://github.com/Monsido/bugs_and_issues/issues/1380
- 9 Umbraco - no Jira reference
- 10 Wordpress: No Jira reference
Documentation & Reference
More details in the full spec.
Github repo: https://github.com/Monsido/cms_templates
URLs for Integrating CMSs
Structure of a Template
Implementing a CMS Template requires 4 sections to be filled: Domain ID, URL(CMS), Replacements & Testing URLs
{ url: "http://domain.tld/admin/edit/{page_id}", testing_urls: [{ page_url: "http://domain.tld/blog/articles/testing-article", cms_url: "http://domain.tld/admin/edit/123" }], replacements: [{ var: "page_id", type: "source", css_selector: "div#article.article", value_of: "attribute", attribute_key: "article_id", type: "get_numbers", returns: "{result}" }] }
Domain ID
The id of the domain that you want to set up a template for.
URL (CMS)
The URL of a template is the pattern that will be used when generating the final URL. It contains the interpolations for the replacements that are gonna be used in the generated URLs.
The format for interpolation is {VARIABLE_NAME}
. For example:
https://example.com/admin/{article-id}/edit/{language}
Replacements
The replacements types supported are:
source: Extract values from HTML elements via CSS selectors.
When used, the css_selector needs to be set indicating which part of the source you want to use for replacement.
url: Extract a part of the original page URL to be used in the CMS URL.
Further filtering can be done via the value_of, process and regex fields.
Let’s ignore all the other options for now and use the defaults (process: none, regex: null, returns: {result}, default: null
)
value_of
for Source replacements
Example page source:
<div class=“example-class” id=“example-id”> <p some-attribute=“some-value”>Print Me! 123</p> </div>
all
Returns the whole HTML for the replacement after the
css_selector
is applied.
For the following template:
{ url: "https://{example-replacement}", replacements: [ { var: "example-replacement", type: "source", css_selector: "div#example-id", value_of: "all" } ] }
It will generate:
https://<div class=“example-class” id=“example-id”><p some-attribute=“some-value”>Print Me! 123</p></div>
content
Returns the HTML content of an element HTML for the replacement after the
css_selector
is applied.
For the following template:
{ url: "https://{example-replacement}", replacements: [ { var: "example-replacement", type: "source", css_selector: "div#example-id", value_of: "content" } ] }
It will generate:
https://<p some-attribute=“some-value”>Print Me! 123</p>
text_content
Returns the text content of an element HTML for the replacement after the
css_selector
is applied.
For the following template:
{ url: "https://{example-replacement}", replacements: [ { var: "example-replacement", type: "source", css_selector: "div#example-id", value_of: "text-content" } ] }
It will generate:
https://Print Me! 123
attribute
Returns the value of a given attribute (through the attribute_key value) of an element HTML for the replacement after the
css_selector
is applied.
For the following template:
{ url: "https://{example-replacement}", replacements: [ { var: "example-replacement", type: "source", css_selector: "div#example-id", value_of: "attribute", attribute_key: "class" } ] }
It will generate:
https://example-class
value_of
for Url replacements
Example URL:
https://example.com/print/me#or-me?search=better-me
path
Returns the URL path.
For the following template:
{ url: "https://cms.example.com/{example-replacement}", replacements: [ { var: "example-replacement", type: "url", value_of: "path" } ] }
It will generate:
https://cms.example.com/print/me
query
Returns the URL query.
For the following template:
{ url: "https://cms.example.com/{example-replacement}", replacements: [ { var: "example-replacement", type: "url", value_of: "query" } ] }
It will generate:
https://cms.example.com/search=better-me
fragment
Returns the URL fragment.
For the following template:
{ url: "https://cms.example.com/{example-replacement}", replacements: [ { var: "example-replacement", type: "url", value_of: "fragment" } ] }
It will generate:
https://cms.example.com/or-me
All
host
Returns the URL host.
For the following template:
{ url: "https://cms.example.com/{example-replacement}", replacements: [ { var: "example-replacement", type: "url", value_of: "host" } ] }
It will generate:
https://cms.example.com/example.com
Process
The process
key allows you to further filter the resulting strings.
You can either use:
none
: Return the string as it is.get_numbers
: Returns ONLY the numbers of the string.regex
: Returns the string after being processed by a ruby regular expression. You need to provide the regex adding aregex
key to each replacement. It will return the first capture group of a regex.
Returns
The returns
key allows you to further edit the output string.
By default it has value {result}
meaning it will only return whatever got captured. You can add something to it to concatenate your extracted result with something. For example on a numerical ID you could do something like this:
{ url: "https://example.com/edit/{articleid}", replacements: [{ var: "articleid", type: "source", … process: "get_numbers", returns: "article-{result}" ] }
Would then return:
https://example.com/edit/article-123
Default
The default
key can be used to return something in case is not present and even as a powerful conditional replacement by setting it to “”
(check examples on the repository).
Default accepts both Integers and Strings as input.
Cases
https://optimere.atlassian.net/browse/MS-2058 - Adobe Experience Manager
Specific case where CMS contain 2 difference links: https://author-atlascopco-prod.adobecqms.net/sites.html/content/products/en/Rental/Offshore-equipment-for-rent https://author-atlascopco-prod.adobecqms.net/sites.html/content/cl-ma-sp/en-uk/Rental/products 3 CMS urls share the first part <https://author-atlascopco-prod.adobecqms.net/sites.html/content> The rest is different, and it seems that it cannot be generated from the website's URLs, so I tried to look at the source code, the HTML. I took the first page, opened the source code and searched for products/en/Rental/Offshore-equipment-for-rent and found 2 snippets we could use: <a href="#" data-target-url="/en-uk/rental/rental-locations/contact-form" data-target-selector="#modal-contact-Topbanner-2dc34341c8624cf0b69442b81d65746f" data-target-country="en-uk" data-target-component="/content/products/en/Rental/Offshore-equipment-for-rent/jcr:content/par/hero" data-target-subject="/content/products/en/Rental/Offshore-equipment-for-rent/jcr:content/par/hero" class="cap-form js-modal"> <button class="ds_c-button ds_c-button--ghost ds_c-top-banner__button" type="button" design-system="true"> <span class="ds_c-button__inner">Request information</span> </button> </a> <a class="cmp-teaser__action-link primary cap-form js-modal" href="#" data-target-url="/en-uk/rental/rental-locations/contact-form" data-target-selector="#modal-Sticky-Banner-top-banner-" data-target-component="/content/products/en/Rental/Offshore-equipment-for-rent/jcr:content/par/hero" data-target-subject="/content/products/en/Rental/Offshore-equipment-for-rent/jcr:content/par/hero"> Request information </a> In these snippets there is data-target-subject="/content/products/en/Rental/Offshore-equipment-for-rent/jcr:content/par/hero" and what we need is actually /content/products/en/Rental/Offshore-equipment-for-rent so the strategy will be to get one of these snippets and extract what we need from it. <https://author-atlascopco-prod.adobecqms.net/sites.html{cms_path}> replacement: var: "cms_path", type: "source", css_selector: "a.primary[data-target-subject]", value_of: "attribute", attribute_key: "data-target-subject", process: "regex", regex: "(.+)/jcr" the type is source because we'll be extracting text from the source code, the HTML (as opposed to the URL) the css_selector is a.primary[data-target-subject] because we want to get all anchor elements a that have an attribute called data-target-subject and a class primary. since there are 2 anchors with the attribute data-target-subject (and in other pages there could be more) I used .primary to select only one,the one with the class primary. then attribute_key: "data-target-subject" will extract just the value of the attribute data-target-subject so /content/products/en/Rental/Offshore-equipment-for-rent/jcr:content/par/hero will be extracted Finally we need to keep the first part (what is before /jcr) so I use the regular expression (.+)/jcr to capture everything that is before /jcr
https://optimere.atlassian.net/browse/MS-11 - ACOS
https://optimere.atlassian.net/browse/MS-33 - Drupal
https://optimere.atlassian.net/browse/MS-136 - Umbraco
https://optimere.atlassian.net/browse/MS-2180 - Granicus govAccess (Vision) CMS
For Granicus - IDs foun on in a script tag head> <script>ID:1</script> </head> you can do: { "var": "id", "type": "source", "css_selector": "head", "value_of": "content", #this gets all the HTML inside that element "process": "regex", "regex": "ID:(\\d+)" } And if for example was <p id="hello"><span>ID:1</span></p> you can do: { "var": "id", "type": "source", "css_selector": "p#hello", "value_of": "text_content", #this gets only the text inside an element, eliminating all HTML "process": "get_numbers" }
More Templates:
Sitecore: https://optimere.atlassian.net/browse/MON-2701
Domain: 6680 URL: "https://cm.3f.dk/sitecore/content/FFFDK/Home{path}" Replacements: [{ "var": "path", "type": "url", "css_selector": null, "value_of": "path", "attribute_key": null, "process": "none", "regex": null, "returns": "{result}", "default": null }] Testing URLs: [{ "page_url": "https://www.3f.dk/find-svar/dagpenge", "cms_url": "https://cm.3f.dk/sitecore/content/FFFDK/Home/find-svar/dagpenge" }, { "page_url": "https://www.3f.dk/find-svar/overenskomst", "cms_url": "https://cm.3f.dk/sitecore/content/FFFDK/Home/find-svar/overenskomst" }]
Craft: https://optimere.atlassian.net/browse/SUPPORT-139
get content from meta
<meta name="controlPanelLink" content="https://vistacollege.nl/admin/entries/vistacollege/861-studeren?site=default"/>
{ "staging_domain_id": 6578, "cms_url": "https://{url}", "replacements": [ { "var": "url", "type": "source", "css_selector": "meta[name='controlPanelLink']", "value_of": "attribute", "attribute_key": "content", "process": "regex", "regex": "https?:\/\/(.+)" } ], "production_testing_urls": [ { "page_url": "https://vistacollege.nl/studeren", "cms_url": "https://vistacollege.nl/admin/entries/vistacollege/861-studeren" }, { "page_url": "https://vistacollege.nl/nieuws/samenwerking-regio-en-bedrijven-kansen-voor-werkzoekenden", "cms_url": "https://vistacollege.nl/admin/entries/nieuws/140484-samenwerking-regio-en-bedrijven-kansen-voor-werkzoekenden?site=default" }, { "page_url": "https://vistacollege.nl/taal/", "cms_url": "https://vistacollege.nl/admin/entries/taalPlus/39633?site=vistaTaal" }, { "page_url": "https://vistacollege.nl/kom-kijken/vista-match", "cms_url": "https://vistacollege.nl/admin/entries/vistacollege/101851-vista-match?site=default" } ], "staging_testing_urls": [ { "page_url": "https://vistacollege.nl/studeren/veelgestelde-vragen", "cms_url": "https://vistacollege.nl/admin/entries/vistacollege/872-veelgestelde-vragen?site=default" }, { "page_url": "https://vistacollege.nl/studeren/inschrijven-voor-een-opleiding", "cms_url": "https://vistacollege.nl/admin/entries/vistacollege/929-inschrijven-voor-een-opleiding?site=default" } ] }
Drupal: https://optimere.atlassian.net/browse/MON-2105
Find page id (aka node id) in
<link rel="shortlink" href="https://www.nordfynsbib.dk/node/765"/>
Domain ID: 102155 URL: https://www.nordfynsbib.dk/node/{page_id}/edit REPLACEMENTS: [{ "var": "page_id", "type": "source", "css_selector": "link[rel='shortlink']", "value_of": "attribute", "attribute_key": "href", "process": "get_numbers" }] TESTING URLs [{ "page_url":"https://www.nordfynsbib.dk/billetter", "cms_url":"https://www.nordfynsbib.dk/node/765/edit" },{ "page_url":"https://www.nordfynsbib.dk/regler-og-takster", "cms_url":"https://www.nordfynsbib.dk/node/2128/edit" },{ "page_url":"https://www.nordfynsbib.dk/page/om-bibliotek-borgerservice", "cms_url":"https://www.nordfynsbib.dk/node/2135/edit" }]
Opencities - https://github.com/Monsido/bugs_and_issues/issues/1380
Find page id (aka node id) in
<div class="share-page-container share-page-link-left share-page-link-medium share-page-link-square share-page-link-no-labels" data-item-id="6792e765-0e25-4ec4-b393-a2c51fec8235" id="share-page-container clearfix">
{ "staging_domain_id": 6726, "cms_url": "https://moretonbay.admin.opencities.com/InformationManagement/ContentAdmin.aspx?id={page_uuid}", "replacements": [ { "var": "page_uuid", "type": "source", "css_selector": "div[data-item-id]", "value_of": "attribute", "attribute_key": "data-item-id" } ], "production_testing_urls": [ { "page_url": "https://www.moretonbay.qld.gov.au/Services/Arts-Culture-Heritage", "cms_url": "https://moretonbay.admin.opencities.com/InformationManagement/ContentAdmin.aspx?id=6792e765-0e25-4ec4-b393-a2c51fec8235" }, { "page_url": "https://www.moretonbay.qld.gov.au/Services/Arts-Culture-Heritage/Cultivate-the-Arts", "cms_url": "https://moretonbay.admin.opencities.com/InformationManagement/ContentAdmin.aspx?id=0bb4d105-3758-44ed-a460-efbb7f80245d" } ], "staging_testing_urls": [ { "page_url": "https://www.moretonbay.qld.gov.au/Events", "cms_url": "https://moretonbay.admin.opencities.com/InformationManagement/ContentAdmin.aspx?id=685868c2-1988-4bef-8aba-7f6799ee0e4f" }, { "page_url": "https://www.moretonbay.qld.gov.au/libraries/Discover/Children/Babies-and-Toddlers", "cms_url": "https://moretonbay.admin.opencities.com/InformationManagement/ContentAdmin.aspx?id=d94f0e8a-5089-4ef9-b48e-003517bf816d" }, { "page_url": "https://www.moretonbay.qld.gov.au/libraries/Events/Baby-Rhyme-Time/Strathpine-Wed", "cms_url": "https://moretonbay.admin.opencities.com/InformationManagement/ContentAdmin.aspx?id=0c24019d-e5dd-472f-89f0-0651bb19ac39" } ] }
Umbraco - no Jira reference
Domain ID: 102152 URL: https://www.nordfynskommune.dk/umbraco#/content/content/edit/{contentid} REPLACEMENTS: [{ "var": "contentid", "type": "source", "css_selector": "meta[name='pageId']", "value_of": "attribute", "attribute_key": "content", "process": "none", "regex": null, "returns": "{result}", "default": null }] TESTING URLs [{ "page_url": "https://kommunalbestyrelsen.nordfynskommune.dk/organisation/", "cms_url": "https://www.nordfynskommune.dk/umbraco#/content/content/edit/8284" },{ "page_url": "https://kommunalbestyrelsen.nordfynskommune.dk/kommunikation/", "cms_url": "https://www.nordfynskommune.dk/umbraco#/content/content/edit/8270" }]
Wordpress: No Jira reference
Domain ID: 53784 URL: "https://www.buglife.org.uk/wp/wp-admin/post.php?post={article_id}&action=edit" # REPLACEMENTS [{ "var": "article_id", "type": "source", "css_selector": "body", "value_of": "attribute", "attribute_key": "class", "process": "regex", "regex": "(?:page|post)-id-(\\d+)", "returns": "{result}" }] # TESTING URLS [{ "page_url": "https://www.buglife.org.uk/campaigns/lower-thames-crossing/", "cms_url": "https://www.buglife.org.uk/wp/wp-admin/post.php?post=33182&action=edit" },{ "page_url": "https://www.buglife.org.uk/bugs/bug-directory/new-forest-cicada/", "cms_url": "https://www.buglife.org.uk/wp/wp-admin/post.php?post=5225&action=edit" }]