For LTI 1.1 take a look at: https://canvas.instructure.com/doc/api/file.content_item.html LTI 1.1 Content-Item Process.
basically, the key point is that you need 2 lti endpoints:
1. for the LTI content embed selection - this is the one that you see in the popup of the editor. It can specify for canvas different resources to load, It should return the content that you want canvas to embed on the page/activity. The one that you want is something like:
{
"@context": "http://purl.imsglobal.org/ctx/lti/v1/ContentItem",
"@graph": [
{
"@type": "LtiLinkItem",
"url": 'https://your.basic.lti.launch.url',
"mediaType": "application/vnd.ims.lti.v1.ltilink",
"text": "",
"placementAdvice": {
"presentationDocumentTarget": "iframe",
"displayWidth": 640,
"displayHeight": 360,
}
}
]
};
2. Your basic lti launch endpoint - this is the one that is going to be embedded as iframe on the activity/page, with no popup and should be the page tracker you want.
For more details: http://www.imsglobal.org/specs/lticiv1p0/specification
At step 1 the result should be submitted back to canvas as a forum. Some LMSs requires that the submitted result must be signed with oath1 signature, some accept unsigned.
If you are familiar with JSX maybe this code snippet can help (it has signed and unsigned versions):
<form action={this.returnUrl} method="post" encType="application/x-www-form-urlencoded" ref={(el) => this.itemSelectForm = el as HTMLFormElement}>
{signedData ? [
<input type="hidden" name="lti_message_type" value={signedData.lti_message_type} />,
<input type="hidden" name="lti_version" value={signedData.lti_version} />,
<input type="hidden" name="content_items" value={signedData.content_items} />,
signedData.data ? <input type="hidden" name="data" value={signedData.data} /> : null,
<input type="hidden" name="oauth_version" value={signedData.oauth_version} />,
<input type="hidden" name="oauth_nonce" value={signedData.oauth_nonce} />,
<input type="hidden" name="oauth_timestamp" value={signedData.oauth_timestamp} />,
<input type="hidden" name="oauth_consumer_key" value={signedData.oauth_consumer_key} />,
<input type="hidden" name="oauth_callback" value={signedData.oauth_callback} />,
<input type="hidden" name="oauth_signature_method" value={signedData.oauth_signature_method} />,
<input type="hidden" name="oauth_signature" value={signedData.oauth_signature} />
]
: [
<input type="hidden" name="lti_message_type" value="ContentItemSelection" />,
<input type="hidden" name="lti_version" value="LTI-1p0" />,
<input type="hidden" name="content_items" value={contentItems || ''} />,
this.contentData ? <input type="hidden" name="data" value={this.contentData} /> : null,
]}
</form>
signedData.content_items/contentItesms is the encoded JSON above.
There are more examples at spec: "3.2 Example Response".
Hope it helps.