[Code] Block Access After x Page Views

Article author
Duncan Hamra

In this article, Nicolas breaks down two custom code snippets you can use to block access to content after a certain number of seconds have passed. After the page count threshold has been reached, the user will get kicked to a page of your choosing. 

Block Access from Non-Members

In this article, Nicolas breaks down a custom code snippet you can use to block access to content for non-members. In other words, all members will have access and will not get redirected.

You'll want to add the following code to the Footer or <Body> section of any page that appears in your list of pages (0:40 in the video above). 


<script>
const logPageView =
  ({ pageLimit, redirectTo }) =>
  async (path) => {
    let pageViews = localStorage.getItem("pageViews") || "{}";
    pageViews = JSON.parse(pageViews);
    if (!pageViews[path]) {
      pageViews[path] = 0;
    }
    pageViews[path]++;
    let totalPageViews = 0;
    for (const [, views] of Object.entries(pageViews)) {
      totalPageViews += views;
    }
    if (totalPageViews > pageLimit) {
      window.location.href = redirectTo;
      return;
    }
    localStorage.setItem("pageViews", JSON.stringify(pageViews));
  };

function manageViews({ pageLimit, redirectTo, pages, condition }) {
  let path = window.location.pathname;
  const logView = logPageView({ pageLimit, redirectTo });
  // updated to match exact paths, last version was incorrect
	if(condition === "exact") {
     pages.forEach((page) => page === path && logView(path));
  }
  if (condition === "includes" || condition === "starts with") {
    pages.forEach((page) => {
      condition === "includes" && path.includes(page) && logView(path);
      condition === "starts with" && path.startsWith(page) && logView(path);
      return;
    });
  }
}

window.$memberstackDom.getCurrentMember().then(({ data: member }) => {
  !member && manageViews({
    pageLimit: 5, // total of views before redirecting | integer
    redirectTo: "/access-denied", // page to redirect to | text
    pages: ["/"], // array of pages
    condition: "exact", // "exact" | "includes" | "starts with"
  });
});
</script>

Block Access Based on Plans

In this section, Nicolas will show you how to block access to content based on a member's plans.

Copy and paste the following code snippet into your site's Footer or <Body> section of your site. You can see how Nicolas did it in the video above at around the 1:50 mark. 

Be sure to watch the whole video and update your code based on Nicolas's instructions. 

<script>
const PLAN_ALLOWLIST = ["pln_cku4gsei0000209l2hj3fdb4l", "pln_cku48230m9000209l2iseb4l"]

const logPageView =
  ({ pageLimit, redirectTo }) =>
  async (path) => {
    let pageViews = localStorage.getItem("pageViews") || "{}";
    pageViews = JSON.parse(pageViews);
    if (!pageViews[path]) {
      pageViews[path] = 0;
    }
    pageViews[path]++;
    let totalPageViews = 0;
    for (const [, views] of Object.entries(pageViews)) {
      totalPageViews += views;
    }
    if (totalPageViews > pageLimit) {
      window.location.href = redirectTo;
      return;
    }
    localStorage.setItem("pageViews", JSON.stringify(pageViews));
  };

function manageViews({ pageLimit, redirectTo, pages, condition }) {
  let path = window.location.pathname;
  const logView = logPageView({ pageLimit, redirectTo });
  if(condition === "exact") {
     pages.forEach((page) => page === path && logView(path));
  }
  if (condition === "includes" || condition === "starts with") {
    pages.forEach((page) => {
      condition === "includes" && path.includes(page) && logView(path);
      condition === "starts with" && path.startsWith(page) && logView(path);
      return;
    });
  }
}

function checkPlans({ plans, filter }) {
  return plans.some(plan => {
    let hasPlan = filter.includes(plan.planId) && plan.status === "ACTIVE"
    return hasPlan
  });
}

window.$memberstackDom.getCurrentMember().then(({ data: member }) => {
	let plans = member?.["planConnections"]
	if(member && plans) {
	  let hasPlans = checkPlans({ plans, filter: PLAN_ALLOWLIST })
	  !hasPlans && manageViews({
	    pageLimit: 5, // total of views before redirecting | integer
	    redirectTo: "/smart-watchlists", // page to redirect to | text
	    pages: ["/"], // array of pages
	    condition: "exact", // "exact" | "includes" | "starts with"
	  });
	}
});
</script>

Was this article helpful?

Comments

4 comments

  • Comment author
    MJ Petroni

    Is there a way to do this for specific elements and not just entire pages? Also, what effect would this have on SEO?

    Thanks

    1
  • Comment author
    Duncan Hamra

    Hey MJ Petroni It's possible, but would require updates to the custom code. 

    And I'm not entirely sure how it would effect SEO 🤔 

    0
  • Comment author
    MJ Petroni

    Thanks. Um, without asking you to take on being our developer, what kind of changes to the code are we talking about? This function would be really helpful for us. One way that I thought about it would be to just change the body text to a font like Block, which replaces letters with shapes. YEs, people could circumvent it, but it's for non-private static content, and ultimately we're more concerned with SEO and access than a really rigid wall for our static content (like articles/curriculum). Signing up or signing in would then switch the font back to the correct setting to be legible. 

    0
  • Comment author
    Duncan Hamra

    Hi MJ 👋 I think ChatGPT would be a helpful tool as you go to solve this. 

    You'd need to ask ChatGPT to add some new functionality that can obfuscate html elements with a data attribute. Maybe something like data-hide-content="change-font."

    ... I did not test this code, but I asked Chatgpt and here's what it sent back. 

    <script>
    const logPageView =
      ({ pageLimit }) =>
      async (path) => {
        let pageViews = localStorage.getItem("pageViews") || "{}";
        pageViews = JSON.parse(pageViews);
        if (!pageViews[path]) {
          pageViews[path] = 0;
        }
        pageViews[path]++;
        let totalPageViews = 0;
        for (const [, views] of Object.entries(pageViews)) {
          totalPageViews += views;
        }
        localStorage.setItem("pageViews", JSON.stringify(pageViews));
      };

    function manageViews({ pageLimit, pages, condition }) {
      let path = window.location.pathname;
      const logView = logPageView({ pageLimit });
      if (condition === "exact") {
        pages.forEach((page) => page === path && logView(path));
      }
      if (condition === "includes" || condition === "starts with") {
        pages.forEach((page) => {
          condition === "includes" && path.includes(page) && logView(path);
          condition === "starts with" && path.startsWith(page) && logView(path);
          return;
        });
      }
    }

    // New function to obfuscate HTML elements
    function obfuscateElements() {
      const elementsToObfuscate = document.querySelectorAll('[data-hide-content="change-font"]');
      elementsToObfuscate.forEach(element => {
        element.style.fontStyle = 'italic'; // You can change this to any font styling you want
        element.style.color = 'gray'; // Changing the color to gray, you can adjust this as well
      });
    }

    window.$memberstackDom.getCurrentMember().then(({ data: member }) => {
      if (!member) {
        manageViews({
          pageLimit: 5,
          pages: ["/"],
          condition: "exact",
        });
        obfuscateElements(); // Call the new function if the member does not have access
      }
    });
    </script>

    The modifications:

    1. Removed the redirectTo property and its references.
    2. Removed the redirection logic (window.location.href = redirectTo;) from the logPageView function.
    3. Updated the manageViews function's parameters to exclude redirectTo.

    Now, the script will no longer redirect non-members, but it will still obfuscate the HTML elements with the data-hide-content="change-font" attribute.

    0

Please sign in to leave a comment.