11

We've build a CloudPage that looks like this:

<!doctype html>
<html>
<head>
 <meta charset="utf-8">
 <title></title>
</head>
<body>hello world</body>
</html>

Nothing complex here. If we view the page source in a web browser, we see the same content (with the inserted tracking script):

<!doctype html>
<html>
<head>
 <meta charset="utf-8">
 <title></title>
</head>
<body>hello world
<script>(function(a,m,i,g,o,s){o=a.createElement(g);s=a.getElementsByTagName(i)[0];o.src=m.origin+m.pathname+"/_t?eventType=CLOUDPAGESVISIT";o.width=0;o.height=0;o.style.display="none";s.appendChild(o);})(document,window.location,"body","img");</script>

    <script src="https:&#x2F;&#x2F;7230771.collect.igodigital.com&#x2F;collect.js"></script>
    <script>
        if (_etmc && typeof _etmc.push === 'function') {
            _etmc.push(['setOrgId', '7230771']);
            _etmc.push(['trackPageView']);
        }
    </script>

</body>
</html>

So far, so good. However, if we retrieve the page content using the following AMPscript...

%%[
var @cloudPage
set @cloudPage = HTTPGet('http://mydomain.com/page')
]%%
%%=v(@cloudPage)=%%

...then I see the following poop in the email preview:

email preview

I've figured out what is happening. If I inspect the HTTP response headers using cURL, I see that the page uses gzip encoding, so HTTPGet is essentially retrieving a binary file:

$ curl -I http://mydomain.com/page
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 429
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Expires: -1
Date: Wed, 01 Feb 2017 04:07:15 GMT
Connection: close

If I use cURL to save the CloudPage URL to a file, I can unzip the file and view the HTML.

So, in summary, CloudPages (including Code Resources) use gzip compression, so they can't be parsed by AMPscript. Does anyone know of a solution to this?

  • 2
    <rant>Product adding AMPScript's transparent support for gzip/deflate would be nice or their Product Marketing colleagues not forcing people onto betas would be nice. What you're trying to do used to be fairly standard stuff - creating webservice-like functionality with landing pages/microsites. Now, we have a "modernised" UI that I'm looking forward to the Lightening experience being applied to... without the functionality... much like MobileConnect was. Six years later MobileConnect still has its mongrel data model, provides no Enterprise features... Einstein...</rant> – Macca Feb 1 '17 at 11:03
  • I'd be interested in seeing what support says about gzip compression being enabled on Code Resources. Seems like that would be a bug. – Adam Spriggs Feb 1 '17 at 13:59
  • I've opened a support case. I'll let you know what they say... – Eliot Harper Feb 1 '17 at 15:05
  • 1
    @DavidDevoy I think you have a different issue here. Content Builder does not use gzip compression for images (I don't believe compression is supported in email clients anyway). I have made a quick test and it looks like the Base64Encode AMPscript function does not produce valid encoding for images. e.g. Base64Encode(HTTPGet('http://vignette4.wikia.nocookie.net/mrmen/images/5/52/Small.gif')) does not produce a valid encoded string. – Eliot Harper Feb 1 '17 at 18:27
  • 1
    You might be able to find a public API where you can make an HTTPPost/HTTPGet request with an image URL and get back a Base64 encoded string. I haven't been able to find such a service myself. Or you could build one and host, I suppose :-/ – Eliot Harper Feb 1 '17 at 19:18
4

For cloud pages you have to pass the accepted encoding

var targetSite = "https://pub.s7.exacttarget.com/f42z3hbhzzzz"
var result = HTTP.Get(targetSite,['Accept-Encoding'],['gzip, deflate, sdch, br']);

var targetSite = "https://pub.s7.exacttarget.com/f42z3hbhzzzz"
var result = HTTP.Post(targetSite,'text/html','test',['Accept-Encoding','x-request-id'],['gzip, deflate, sdch, br','cp']);
1

Eliott, you can use the REST API to retrieve the Content Builder asset for a Cloud Page. The call will return a json object, which contains the webpage content among with other things. You will need to know the asset ID of the Cloud Page first (and have a valid REST Token).

To my knowledge, the asset ID is not made visible in the SFMC UI. In my example, I was able to figure out the asset ID of the Cloud Page asset by using Chrome developer tools to review the page calls the SFMC application was making when I open the page.

My example was written in SSJS and was ran from a landing page. I know it is not best practice to use SSJS in emails, but maybe it can be translated to AMPScript.

<script runat='server'>
    Platform.Load('Core','1.1.1');
    var token = "xxxxxx";
    var id = 0;
    var url = "https://www.exacttargetapis.com/asset/v1/content/assets/" + id;
    var headerNames = ["Authorization"];
    var headerValues = ["Bearer " + token];
    var result = HTTP.Get(url, headerNames, headerValues);
    var content = eval("[" + result.Content + "]")[0];
    Write("<div>Data:</div>");
    Write("<textarea cols='80' rows='25'>");
    Write(content.views.html.content);
    Write("</textarea>");
</script>

Output:

enter image description here

  • Hi David, thanks this is useful information and if I simply needed to make an HTTPGET request, then this would work. However, I actually need to make an HTTPPost request to the CloudPage with form data (I simplified my question as this also an issue with GET requests). But thanks for sharing! – Eliot Harper Feb 5 '17 at 22:18
1

Have you tried setting the Accept-Encoding: identity header?

From https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding

Indicates the identity function (i.e. no compression, nor modification). This value is always considered as acceptable, even if not present.

  • No I haven't. Have you tried this? – Eliot Harper Sep 14 '17 at 5:36
0

Salesforce Marketing Cloud support advised me that there's no option to disable compression on CloudPage published pages and code resources. If you need to get a response back, then you will need to look at writing to a Data Extension and retrieving that value.

However, a word of caution if you choose to do this. I'm invoking the CloudPage by making a request from AMPscript in an email, and then once the CloudPage returns a response (which takes around 10 seconds as the CloudPage is doing a zillion things), we then retrieve the record from the DE created by the CloudPage.

Even though I can see the record is created in the DE before the email preview loads, an AMPscript Lookup() function returns a blank field. However, if I lookup the row, it appears:

%%[
var @letterId, @postBody, @callStatus

set @letterId = AttributeValue('LETTERID')

set @postBody = Concat('ContactKey=', _subscriberkey, '&letterIdValue=', @letterId, '&vawpUrlEncoded=', Base64Encode(view_email_url))

HTTPPost('https://pub.s7.exacttarget.com/f42z3hbhzzzz', 'application/x-www-form-urlencoded', @postBody, @callStatus)

/* wait until CloudPage has finished processing */
var @dataSource, @dataSourceRow, @channel
if Length(@callStatus) > 0 then
   set @dataSource = LookupRows('Channel','EventInstanceID',@letterId)
   set @dataSourceRow = Row(@dataSource, 1) /* there will only be 1 row anyway */
   set @channel = Field(@dataSourceRow,'Channel')
endif

]%%

So in summary, I:

  1. Make a POST request to a CloudPage with x-www-form-urlencoded name/value pairs
  2. Use @callStatus variable to wait until the CloudPage has returned a response (and I have no idea what the response is as it's a compressed binary string, so I hope it's not a 500 error). I simply check the length of the response, to see that there is a response.
  3. I set the @channel variable based on a DE field that the CloudPage created. As indicated earlier, even though the field exists a Lookup() function isn't returning the value immediately (but does work if I wait a few seconds, which I can't) but using LookupRows/Row/Field combination does return the DE field value.

What's interesting is that according to the HTTPPost documentation, @callStatus should be returning the HTTP status code (e.g. 200, 500, other) but instead it returns the response payload. I've tried the alternative HTTPPost2 method also, but still can't get the status code back. This would be preferred, as if there was a 500 error, then I could do something about this. Oh well.

  • Thanks for sharing, Eliot. My word that's creative! I didn't quite follow the concurrency type thing at the end, though. Could you enlarge on the lookup piece, please? – Macca Feb 2 '17 at 11:58
  • Sure, I have added a summary below my code block. – Eliot Harper Feb 2 '17 at 17:50
  • 1
    Interesting. It kind of feels like the two Lookup functions might be using different transaction isolation levels - one allowing a dirty read of the Cloudpage's incomplete transaction and the other not. Maybe. – Macca Feb 2 '17 at 20:42
0

This seemed to work best for me, adding on to what @sforce had provided:

<script runat="server">
  Platform.Load("core","1");

  var url = "http://PAGEID";
  var headerNames = ["Accept-Encoding"];
  var headerValues = ["gzip, deflate, sdch, br"];
  var response = HTTP.Get(url, headerNames, headerValues);

  Write(response.Content);
</script>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.