Acrobat Javascript: passing a UTM parameter from URL into a PDF button - javascript

I have a PDF that has a button with field name ctaButton.
ctaButton currently has a url pointing to https://mywebsite.com.
I want to host the PDF on my server at https://mywebsite.com/hosted.pdf.
And when I send someone a link to the PDF, I want to attach a UTM_term parameter ?utm_term=customer1 and then have the PDF read this parameter and update the ctaButton url to https://mywebsite.com/?utm_term=customer1.
I've been messing around with the Javascript actions in Acrobat for a couple of hours trying to make this happen. Any help greatly appreciated.

You can get the full url to the document using...
var myURL = this.url;
"this" in Acrobat JavaScript is the document context.

I did hours of research and came to this conclusion – Javascript in Acrobat is like trying to code in 1985 AND browsers will not execute whatever code you come up with.
So I used this workaround:
When I send the PDF to someone, I send it as a link with a base64
encoded stringified JSON package that contains a bunch of tracking
data but importantly, the name of the file to access as well as utm
parameters specific to the recipient
The link hits a server handler (NodeJS) that extracts the encoded
JSON package, and uses the data in the package to serve up an HTML
redirect page pointing to the right PDF file
Importantly, the HTML page also saves the JSON package to the
browser's localStorage . . . this comes in handy in subsequent
steps
The PDF file opens in browser (it doesn't have to, could be opened on
desktop) and the call to action link has a link to a get request
handler
The get request handler serves up ANOTHER redirect page
This second redirect page accesses the browser's local storage, looks
for the utm parameters I set for that user, and then redirects to the
sale page, with nice utm parameters attached
So to sum up, you don't add the utm parameters to the call to action link in the PDF (because that would make the world too easy to live in) and instead you do all these acrobatics (no pun intended) to attach utm parameters in the link clicks (via JSON strings saved in localStorage) during the process (i.e. when user opens email to extract file via link, and then when user clicks call to action in the PDF).
Any questions or clarifications please let me know in the comments and I will do my best to address.
Caveats
Only works if user uses same browser in all steps (i.e. if Susan opens the email in Safari, saves the PDF, then clicks the call to action in the PDF, and the link opens in Chrome, utm parameters will not be passed).
Assumes browser is modern and has localStorage
UPDATE: I came across another solution. It's a bit more convoluted. Diagram below.
Porky.io is a Javascript extension for Adobe Indesign. So flow is:
send Porky.io the customer data you need (e.g. utm's for links)
Porky.io generates PDF from a template you provide with the customer data you provided
Listen for a new file save from Porky
Do something with the file (e.g. email it to customer)
I believe you need to run an instance of Windows somewhere in the cloud (e.g. on Azure) to run Indesign with the Porky.io. Unless you want to rely on your laptop.
My project's not big enough yet to warrant setting this up . . . but good alternative if I need to make my current solution more robust.

Related

Protect your DOM's href safe from curious eyes [duplicate]

This question already has answers here:
How to disable View source and inspect element
(4 answers)
Closed 3 years ago.
I am having a display page where is shows all our reports like this,
On mouse over it shows the file url (where it is located in our server).
I want to protect this from users.
What is tried is this,
<li><a data-href="'.$value->uri.'">'.$value->filename.'</a></li>
and call script when click to download the file:
<script>
$("a").click(function(event){
var href = $(this).data("href");
window.location.href=href;
});
</script>
But still users can inspect and see url.
Is there any way to hide url from users?
Aside from the security implications of trying to enact a system like this (i.e. the level of security is hiding the href), as you've tagged PHP you could setup an endpoint in PHP that returns a 302 redirect for an href that redirects to the object on your server.
Use a DB to save the mapping of the 'public' href value that you see on mouseover and in the inspector, then when you hit this URI on your PHP server, look up the mapped resource and return it (if the user is authenticated).
First, never show server path in the URL.
Second, make these links href as /download_file.php?file_name=your_current_file_name.
Third is to have a script on server side, like download_file.php which gets the file name, searches in it's directory for the file and downloads them on the client browser.
Fourth is to hide this behind the authentication that only logged in users could see it.
Fifth, you could have a database table of each file against a user to make sure that other users don't get access to someone's file. As an alternative, you could also make folders based on user_id to make it easier to get the parent directory to search through, as you could get current logged user from session.
Always store uploaded files outside of your public_html so that they aren't accessible from the web, except from your server scripts.
Side note: Storing user ID in session is fine with regards to security. See here: php storing user id in session?
Note: Disabling inspect element is really not the right way to handle this.

How can I get share and download links from OneDrive API

I am using the OneDrive JS Picker and would like to get both a download and share value. The sample in the documentation lists the options for the action parameter separated by pipes. I was hoping to use bitwise operators to combine those values (e.g.
action: "share | download"
but that doesn't seem to allow both the webUrl value and the download url (#microsoft.graph.downloadUrl)... has anybody else been able to do this? Or is there a way to use the share URL (webUrl) to get a download url so we can get the text contents of files?
I know there is a REST service available though that may be deprecated, given the message at the top of that page:
This documentation is archived and is not being maintained.
but if that is still usable, perhaps we could use that to download the file... if so, can I put the file id in that download URL and an access token?
I was able to host the OneDrive.js file locally, un-minify it and modify the line below (line 104) to have the downloadUrl included in all queries on files. That allows us to get a shareUrl and a downloadUrl.
e.DEFAULT_QUERY_ITEM_PARAMETER = "expand=thumbnails&select=id,name,size,webUrl,folder,#content.downloadUrl";
sorry for the missleading pipe sign. Actually right now we only allow one action per request like (action: "query"). The pipeline sign in the doc means 'or' in English not in code.
Before my answer, I want to clarify the difference between a webUrl and a shareUrl.
A webUrl which you see in the response's 'webUrl' attribute is the
url pointed to the resource online which requires user login to see
it.
A shareUrl which contains the permission which everyone who has the
link could see/edit it based on the user's config.
JS Picker
If you want the download link and a webUrl back at the same time, it should be easy:
{
action: "query",
advanced: {queryParameters: "select=id,name,webUrl,#content.downloadUrl"}
}
If you want both the download link and share link back at the same time, it is not supported.
API
For using the API to achieve this, you can go to the new API page: https://dev.onedrive.com/items/get.htm
and get the item with already shared links should be
GET /v1.0/drive/items/<item-id>?select=id,name,#content.downloadUrl,webUrl&expand=permissions
all already shared links should be returned in the permissions array object.
If you don't have a shared link, and you need to create the shared link, you should try https://dev.onedrive.com/items/sharing_createLink.htm
while it does not return the webUrl and download url back so you need an extra request.

Canvas Image to an Image file

So i have a canvas on which the user signs, now instead of converting it to a base 64 string i simply want to save it as an image itslef. whats the easiest way to do it html5??
You can easily do that this way (specifying the format as png in this case):
var img = canvas.toDataURL("image/png");
You can specify different image formats.
Take a look at this answer.
I've answered a similar question here:
Simulating user event
Assuming you are saving locally
You can go the route of creating an image from a Data URL, but then saving it is the trickier part that currently isn't very nice using HTML5. It's hopefully going to get better soon, if browsers incorporate the download attribute of the a tag.
Obviously if you have higher permissions than a standard webpage... i.e. you are designing a browser plugin - then there are other options...
If I were to implement something like this myself, at the moment, I would conceed to using a flash plugin to handle the save to the local computer.
Assuming you are saving remotely
By the sounds of it you aren't saving to a server, but if so this is quite easy by just POSTing the base64 information to a script written in a server-side scripting language (i.e. like PHP) and getting that to write the data directly as binary to a file. Obviously you have to make certain you do this securely however, you don't want just any binary data written to your server's filesystem.
Best of both worlds
If you've got the development time, the best method to get a canvas image saved locally - without Flash - is to create a server-side script that instead of saving the data to your server actually writes the Base64 information you send it directly back as a realised binary image file. That way you can create a form that posts your Base64 data to a new tab, this request is evaluated by the server-side, and the binary image is returned... at which point the browser asks the user where they wish to save their image.
You'll need to define the correct headers to force an image to download (rather than display in-browser). A simple change to force this is to set the server-side script's Content-type header to 'image/octect-stream'... there are other header options to set which would be best researched (i.e. headers that control the filename and so forth).
reflect.php
<?php
/// a simple example..
if ( array_key_exists('data', $_POST) && ($data = $_POST['data']) ) {
header('Content-type: image/octet-stream');
echo base64_decode( $data );
exit;
}
and the form...
<form action="reflect.php" method="post" target="_blank">
<input name="data" type="hidden" value=" ... Base64 put here with JS ... ">
</form>
(The whole form should be created dynamically and submitted automatically with JavaScript)
Improving the user experience
There are ways to avoid a new tab being created, but you'd have to research to make sure these other methods don't cause cross-browser problems... for example you could post your form data as part of an iframe (which would keep the process hidden), or just post the data directly on the current window (..and hope that all the browsers receive the correct request and open a download rather than replace your page content - most modern browsers should handle this).
Improving security
With regards to a PHP script that automatically returns binary data, you should keep the access to this script secured by one time use key / authentication token or something similar, and keep a limit on how much Base64 data you are willing to accept. It might not seem like it poses a secutiry risk - as you are not modifying your server in any way with what the user sends - but the dodgy people of this world could take your script and use it to send download request to other users... which if downloaded (and turned out to be unwanted trojans or viruses) would make your server implicit in providing the dodgy file.
All in all
Due to the effort required to get a simple thing like an image saved to the desktop, I wouldn't blame you for doing the following:
Embed the image in the page (after taking your snapshot from canvas) and ask the user to right click and Save as...
Hopefully future things will make this situation better...

Facebook Open graph with GWT

We are developing a page with GWT that has a list view and selecting an item it opens a detail with ajax style, there is no refresh in the page and a new view is shown in the client. When that detail is shown( or accessed directly by its url), the meta tags for the Open Graph are set in the header. That detail is our Open Graph object.
The problem is that setting meta tags by code (even at the beginning of the onModuleLoad method) doesn't work because Facebook doesn't detect them when a user performs an action and Facebook thinks that the page is not an Open Graph one. We suppose FB reads the page directly without executing any javascript.
Any ideas or workaround with that?
Thanks in advance.
You'll need to this server-side, with a handler that takes an object id from the query string or path, and does two things:
write out the correct tags for facebook.
'deep-link' into your GWT app to show the detail view for the
object.
So for URLs like:
http://myapp.com/og/?type=movie&id=1234
http://myapp.com/og/?type=film&id=6789
The HTML output should have all the tags for the object specified, and it should launch your GWT app with a 'bookmark' or some other info it needs to navigate to the detail view.
Each object needs its own permanent, distinct URL. So when you pass it to the facebook API, facebook can 'crawl' it, and they can publish it as a link in news feed stories etc. (so machine readable, and shows the relevant content for non-machines!)
It should pass the test here:
http://developers.facebook.com/tools/debug
Some more recent information to refer to:
Put the OpenGraph tags in your server side HTML rendering, like detailed here:
http://www.gwtproject.org/articles/dynamic_host_page.html#servlet
Since Google considers AJAX crawling deprecated, they recommend using the HTML rendering on the server side as well:
https://webmasters.googleblog.com/2015/10/deprecating-our-ajax-crawling-scheme.html

Can you use JavaScript to detect a file download window created server side?

I have a jQuery plugin I use to dynamically create and render a form on a default.aspx asp.net page, then submit it. The page it gets submitted to is a pdf.aspx page. The page builds a PDF then uses Response.Write to write the file (application/pdf) to the browser. I use the same method to render XLSX files to the browser as well. It works really great, but I need a callback or some event to tell the button when to stop spinning. This prevents the user from continuously clicking the Excel or PDF buttons. Does anyone know a way to detect the file dialog window when it was not created using JavaScript? I am also open to other methods of callback from the server side as well.
The way I do that was suggested in response to a question I asked here a while ago by T.J. Crowder. I can't find the response from the last time I wrote this up because the Stackoverflow "search" facility is so incredibly lame, so I'll probably type in a blog post. The basic idea is that your client code (Javascript) should append an extra parameter when it submits the request for the download. The parameter should contain some generated random string (probably just the current timestamp is good enough). The server then looks for that parameter, and when it's preparing the response with the download file it also sets a cookie and gives it that random value.
Right after the submit (or right before; it doesn't really matter), the Javascript code should start an interval timer with a routine to look at the value of document.cookie and see if it contains that random string. As soon as the cookie does contain that string, then you know that the server has sent back its response and that the file download dialog has been presented.

Categories