Documentation & Reference

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>

  1. 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 a regex 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"
}]